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.11 (Berkeley) 06/24/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 /* Check size. */ 135 if (sb.st_size > SIZE_T_MAX) { 136 err(0, "%s: %s", fn, strerror(EFBIG)); 137 return; 138 } 139 140 /* Map the file. */ 141 if (fstat(fd, &sb) || 142 (ep = (EXEC *)mmap(NULL, (size_t)sb.st_size, 143 PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0)) == (EXEC *)-1) { 144 err(0, "%s: %s", fn, strerror(errno)); 145 return; 146 } 147 148 /* 149 * Initialize old and new symbol pointers. They both point to the 150 * beginning of the symbol table in memory, since we're deleting 151 * entries. 152 */ 153 sym = nsym = symbase = (NLIST *)((char *)ep + N_SYMOFF(*ep)); 154 155 /* 156 * Allocate space for the new string table, initialize old and 157 * new string pointers. Handle the extra long at the beginning 158 * of the string table. 159 */ 160 strbase = (char *)ep + N_STROFF(*ep); 161 if ((nstrbase = malloc((u_int)*(u_long *)strbase)) == NULL) 162 err(1, "%s", strerror(errno)); 163 nstr = nstrbase + sizeof(u_long); 164 165 /* 166 * Read through the symbol table. For each non-debugging symbol, 167 * copy it and save its string in the new string table. Keep 168 * track of the number of symbols. 169 */ 170 for (cnt = ep->a_syms / sizeof(NLIST); cnt--; ++sym) 171 if (!(sym->n_type & N_STAB) && sym->strx) { 172 *nsym = *sym; 173 nsym->strx = nstr - nstrbase; 174 p = strbase + sym->strx; 175 len = strlen(p) + 1; 176 bcopy(p, nstr, len); 177 nstr += len; 178 ++nsym; 179 } 180 181 /* Fill in new symbol table size. */ 182 ep->a_syms = (nsym - symbase) * sizeof(NLIST); 183 184 /* Fill in the new size of the string table. */ 185 *(u_long *)nstrbase = len = nstr - nstrbase; 186 187 /* 188 * Copy the new string table into place. Nsym should be pointing 189 * at the address past the last symbol entry. 190 */ 191 bcopy(nstrbase, (void *)nsym, len); 192 193 /* Truncate to the current length. */ 194 if (ftruncate(fd, (char *)nsym + len - (char *)ep)) 195 err(0, "%s: %s", fn, strerror(errno)); 196 munmap((caddr_t)ep, (size_t)sb.st_size); 197 } 198 199 void 200 usage() 201 { 202 (void)fprintf(stderr, "usage: strip [-d] file ...\n"); 203 exit(1); 204 } 205 206 #if __STDC__ 207 #include <stdarg.h> 208 #else 209 #include <varargs.h> 210 #endif 211 212 void 213 #if __STDC__ 214 err(int fatal, const char *fmt, ...) 215 #else 216 err(fatal, fmt, va_alist) 217 int fatal; 218 char *fmt; 219 va_dcl 220 #endif 221 { 222 va_list ap; 223 #if __STDC__ 224 va_start(ap, fmt); 225 #else 226 va_start(ap); 227 #endif 228 (void)fprintf(stderr, "strip: "); 229 (void)vfprintf(stderr, fmt, ap); 230 va_end(ap); 231 (void)fprintf(stderr, "\n"); 232 if (fatal) 233 exit(1); 234 eval = 1; 235 } 236