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.7 (Berkeley) 05/26/91"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <fcntl.h> 21 #include <errno.h> 22 #include <a.out.h> 23 #include <unistd.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 typedef struct exec EXEC; 29 typedef struct nlist NLIST; 30 31 void err __P((const char *fmt, ...)); 32 void s_stab __P((const char *, int, EXEC *)); 33 void s_sym __P((const char *, int, EXEC *)); 34 void usage __P((void)); 35 36 int eval; 37 38 main(argc, argv) 39 int argc; 40 char *argv[]; 41 { 42 register int fd, nb; 43 EXEC head; 44 void (*sfcn)__P((const char *, int, EXEC *)); 45 int ch; 46 char *fn; 47 48 sfcn = s_sym; 49 while ((ch = getopt(argc, argv, "d")) != EOF) 50 switch(ch) { 51 case 'd': 52 sfcn = s_stab; 53 break; 54 case '?': 55 default: 56 usage(); 57 } 58 argc -= optind; 59 argv += optind; 60 61 while (fn = *argv++) { 62 if ((fd = open(fn, O_RDWR)) < 0 || 63 (nb = read(fd, &head, sizeof(EXEC))) == -1) { 64 err("%s: %s", fn, strerror(errno)); 65 continue; 66 } 67 if (nb != sizeof(EXEC) || N_BADMAG(head)) { 68 err("%s: %s", fn, strerror(EFTYPE)); 69 continue; 70 } 71 sfcn(fn, fd, &head); 72 if (close(fd)) 73 err("%s: %s", fn, strerror(errno)); 74 } 75 exit(eval); 76 } 77 78 void 79 s_sym(fn, fd, ep) 80 const char *fn; 81 int fd; 82 register EXEC *ep; 83 { 84 static int pagesize = -1; 85 register off_t fsize; 86 87 /* If no symbols or data/text relocation info, quit. */ 88 if (!ep->a_syms && !ep->a_trsize && !ep->a_drsize) 89 return; 90 91 /* 92 * New file size is the header plus text and data segments; OMAGIC 93 * and NMAGIC formats have the text/data immediately following the 94 * header. ZMAGIC format wastes the rest of of header page. 95 */ 96 if (ep->a_magic == ZMAGIC) 97 fsize = pagesize == -1 ? (pagesize = getpagesize()) : pagesize; 98 else 99 fsize = sizeof(EXEC); 100 fsize += ep->a_text + ep->a_data; 101 102 /* Set symbol size and relocation info values to 0. */ 103 ep->a_syms = ep->a_trsize = ep->a_drsize = 0; 104 105 /* Rewrite the header and truncate the file. */ 106 if (lseek(fd, 0L, SEEK_SET) == -1 || 107 write(fd, ep, sizeof(EXEC)) != sizeof(EXEC) || 108 ftruncate(fd, fsize)) 109 err("%s: %s", fn, strerror(errno)); 110 } 111 112 void 113 s_stab(fn, fd, ep) 114 const char *fn; 115 int fd; 116 EXEC *ep; 117 { 118 struct stat sb; 119 register NLIST *bsym2, *sym1, *sym2; 120 register u_long nsym1, nsym2; 121 register char *p, *bstr2, *str1, *str2; 122 register int len, symlen; 123 off_t fsize; 124 int nb; 125 char *bp; 126 127 /* Quit if no symbols. */ 128 if (ep->a_syms == 0) 129 return; 130 131 bsym2 = NULL; 132 bp = bstr2 = NULL; 133 134 /* Read the file into memory. XXX mmap */ 135 if (fstat(fd, &sb)) 136 goto syserr; 137 if ((bp = malloc(sb.st_size)) == NULL) 138 goto syserr; 139 if (lseek(fd, 0L, SEEK_SET) == -1) 140 goto syserr; 141 if ((nb = read(fd, bp, (int)sb.st_size)) == -1) 142 goto syserr; 143 if (nb != sb.st_size) { 144 errno = EIO; 145 goto syserr; 146 } 147 148 /* 149 * Allocate space for new symbol and string tables. Allocate before 150 * reading the symbol tables so we can do it all in a single pass. 151 * This loses if there weren't any symbols to strip, but that's life. 152 */ 153 sym1 = (NLIST *)(bp + N_SYMOFF(*ep)); 154 if ((bsym2 = sym2 = malloc((u_int)ep->a_syms)) == NULL) { 155 err("%s", strerror(errno)); 156 goto mem; 157 } 158 str1 = bp + N_STROFF(*ep); 159 if ((bstr2 = malloc((u_int)*(u_long *)str1)) == NULL) { 160 err("%s", strerror(errno)); 161 goto mem; 162 } 163 str2 = bstr2 + sizeof(u_long); 164 symlen = sizeof(u_long); 165 166 /* 167 * Read through the symbol table. For each non-debugging symbol, 168 * copy it into the new symbol and string tables. Keep track of 169 * how many symbols are copied and the length of the new string 170 * table. 171 */ 172 #define strx n_un.n_strx 173 nsym2 = 0; 174 for (nsym1 = ep->a_syms / sizeof(NLIST); nsym1--; ++sym1) 175 if (!(sym1->n_type & N_STAB) && sym1->strx) { 176 *sym2 = *sym1; 177 sym2->strx = str2 - bstr2; 178 p = str1 + sym1->strx; 179 len = strlen(p) + 1; 180 bcopy(p, str2, len); 181 symlen += len; 182 str2 += len; 183 ++sym2; 184 ++nsym2; 185 } 186 187 /* If no debugging symbols, quit. */ 188 if (!nsym2) 189 goto mem; 190 191 /* Fill in new symbol table size. */ 192 ep->a_syms = nsym2 * sizeof(NLIST); 193 194 /* Write out the header. */ 195 if (lseek(fd, 0L, SEEK_SET) == -1 || 196 write(fd, ep, sizeof(EXEC)) != sizeof(EXEC)) 197 goto syserr; 198 199 /* Write out the symbol table. */ 200 if (lseek(fd, N_SYMOFF(*ep), SEEK_SET) == -1 || 201 write(fd, bsym2, ep->a_syms) != ep->a_syms) 202 goto syserr; 203 204 /* Fill in the new size of the string table. */ 205 *(u_long *)bstr2 = symlen; 206 207 /* Write out the string table. */ 208 if (write(fd, bstr2, symlen) != symlen) 209 goto syserr; 210 211 /* Truncate to the current length. */ 212 if ((fsize = lseek(fd, 0L, SEEK_CUR)) == -1) 213 goto syserr; 214 if (ftruncate(fd, fsize)) 215 syserr: err("%s: %s", fn, strerror(errno)); 216 217 mem: if (bp) 218 free(bp); 219 if (bstr2) 220 free(bstr2); 221 if (bsym2) 222 free(bsym2); 223 } 224 225 void 226 usage() 227 { 228 229 (void)fprintf(stderr, "usage: strip [-d] file ...\n"); 230 exit(1); 231 } 232 233 #if __STDC__ 234 #include <stdarg.h> 235 #else 236 #include <varargs.h> 237 #endif 238 239 void 240 #if __STDC__ 241 err(const char *fmt, ...) 242 #else 243 err(fmt, va_alist) 244 char *fmt; 245 va_dcl 246 #endif 247 { 248 va_list ap; 249 #if __STDC__ 250 va_start(ap, fmt); 251 #else 252 va_start(ap); 253 #endif 254 (void)fprintf(stderr, "strip: "); 255 (void)vfprintf(stderr, fmt, ap); 256 va_end(ap); 257 (void)fprintf(stderr, "\n"); 258 eval = 1; 259 } 260