1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1988 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)strip.c 5.12 (Berkeley) 08/07/92"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <sys/mman.h> 21 22 #include <limits.h> 23 #include <fcntl.h> 24 #include <errno.h> 25 #include <a.out.h> 26 #include <unistd.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 typedef struct exec EXEC; 32 typedef struct nlist NLIST; 33 34 #define strx n_un.n_strx 35 36 void err __P((int, const char *fmt, ...)); 37 void s_stab __P((const char *, int, EXEC *)); 38 void s_sym __P((const char *, int, EXEC *)); 39 void usage __P((void)); 40 41 int eval; 42 43 int 44 main(argc, argv) 45 int argc; 46 char *argv[]; 47 { 48 register int fd, nb; 49 EXEC head; 50 void (*sfcn)__P((const char *, int, EXEC *)); 51 int ch; 52 char *fn; 53 54 sfcn = s_sym; 55 while ((ch = getopt(argc, argv, "d")) != EOF) 56 switch(ch) { 57 case 'd': 58 sfcn = s_stab; 59 break; 60 case '?': 61 default: 62 usage(); 63 } 64 argc -= optind; 65 argv += optind; 66 67 while (fn = *argv++) { 68 if ((fd = open(fn, O_RDWR)) < 0 || 69 (nb = read(fd, &head, sizeof(EXEC))) == -1) { 70 err(0, "%s: %s", fn, strerror(errno)); 71 continue; 72 } 73 if (nb != sizeof(EXEC) || N_BADMAG(head)) { 74 err(0, "%s: %s", fn, strerror(EFTYPE)); 75 continue; 76 } 77 sfcn(fn, fd, &head); 78 if (close(fd)) 79 err(0, "%s: %s", fn, strerror(errno)); 80 } 81 exit(eval); 82 } 83 84 void 85 s_sym(fn, fd, ep) 86 const char *fn; 87 int fd; 88 register EXEC *ep; 89 { 90 static int pagesize = -1; 91 register off_t fsize; 92 93 /* If no symbols or data/text relocation info, quit. */ 94 if (!ep->a_syms && !ep->a_trsize && !ep->a_drsize) 95 return; 96 97 /* 98 * New file size is the header plus text and data segments; OMAGIC 99 * and NMAGIC formats have the text/data immediately following the 100 * header. ZMAGIC format wastes the rest of of header page. 101 */ 102 if (ep->a_magic == ZMAGIC) 103 fsize = pagesize == -1 ? (pagesize = getpagesize()) : pagesize; 104 else 105 fsize = sizeof(EXEC); 106 fsize += ep->a_text + ep->a_data; 107 108 /* Set symbol size and relocation info values to 0. */ 109 ep->a_syms = ep->a_trsize = ep->a_drsize = 0; 110 111 /* Rewrite the header and truncate the file. */ 112 if (lseek(fd, (off_t)0, SEEK_SET) == -1 || 113 write(fd, ep, sizeof(EXEC)) != sizeof(EXEC) || 114 ftruncate(fd, fsize)) 115 err(0, "%s: %s", fn, strerror(errno)); 116 } 117 118 void 119 s_stab(fn, fd, ep) 120 const char *fn; 121 int fd; 122 EXEC *ep; 123 { 124 register int cnt, len; 125 register char *nstr, *nstrbase, *p, *strbase; 126 register NLIST *sym, *nsym; 127 struct stat sb; 128 NLIST *symbase; 129 130 /* Quit if no symbols. */ 131 if (ep->a_syms == 0) 132 return; 133 134 /* Stat the file. */ 135 if (fstat(fd, &sb) < 0) { 136 err(0, "%s: %s", fn, strerror(errno)); 137 return; 138 } 139 140 /* Check size. */ 141 if (sb.st_size > SIZE_T_MAX) { 142 err(0, "%s: %s", fn, strerror(EFBIG)); 143 return; 144 } 145 146 /* Map the file. */ 147 if ((ep = (EXEC *)mmap(NULL, (size_t)sb.st_size, 148 PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0)) == (EXEC *)-1) { 149 err(0, "%s: %s", fn, strerror(errno)); 150 return; 151 } 152 153 /* 154 * Initialize old and new symbol pointers. They both point to the 155 * beginning of the symbol table in memory, since we're deleting 156 * entries. 157 */ 158 sym = nsym = symbase = (NLIST *)((char *)ep + N_SYMOFF(*ep)); 159 160 /* 161 * Allocate space for the new string table, initialize old and 162 * new string pointers. Handle the extra long at the beginning 163 * of the string table. 164 */ 165 strbase = (char *)ep + N_STROFF(*ep); 166 if ((nstrbase = malloc((u_int)*(u_long *)strbase)) == NULL) 167 err(1, "%s", strerror(errno)); 168 nstr = nstrbase + sizeof(u_long); 169 170 /* 171 * Read through the symbol table. For each non-debugging symbol, 172 * copy it and save its string in the new string table. Keep 173 * track of the number of symbols. 174 */ 175 for (cnt = ep->a_syms / sizeof(NLIST); cnt--; ++sym) 176 if (!(sym->n_type & N_STAB) && sym->strx) { 177 *nsym = *sym; 178 nsym->strx = nstr - nstrbase; 179 p = strbase + sym->strx; 180 len = strlen(p) + 1; 181 bcopy(p, nstr, len); 182 nstr += len; 183 ++nsym; 184 } 185 186 /* Fill in new symbol table size. */ 187 ep->a_syms = (nsym - symbase) * sizeof(NLIST); 188 189 /* Fill in the new size of the string table. */ 190 *(u_long *)nstrbase = len = nstr - nstrbase; 191 192 /* 193 * Copy the new string table into place. Nsym should be pointing 194 * at the address past the last symbol entry. 195 */ 196 bcopy(nstrbase, (void *)nsym, len); 197 198 /* Truncate to the current length. */ 199 if (ftruncate(fd, (char *)nsym + len - (char *)ep)) 200 err(0, "%s: %s", fn, strerror(errno)); 201 munmap((caddr_t)ep, (size_t)sb.st_size); 202 } 203 204 void 205 usage() 206 { 207 (void)fprintf(stderr, "usage: strip [-d] file ...\n"); 208 exit(1); 209 } 210 211 #if __STDC__ 212 #include <stdarg.h> 213 #else 214 #include <varargs.h> 215 #endif 216 217 void 218 #if __STDC__ 219 err(int fatal, const char *fmt, ...) 220 #else 221 err(fatal, fmt, va_alist) 222 int fatal; 223 char *fmt; 224 va_dcl 225 #endif 226 { 227 va_list ap; 228 #if __STDC__ 229 va_start(ap, fmt); 230 #else 231 va_start(ap); 232 #endif 233 (void)fprintf(stderr, "strip: "); 234 (void)vfprintf(stderr, fmt, ap); 235 va_end(ap); 236 (void)fprintf(stderr, "\n"); 237 if (fatal) 238 exit(1); 239 eval = 1; 240 } 241