1 /* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1988, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)strip.c 8.1 (Berkeley) 06/06/93"; 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 register off_t fsize; 91 92 /* If no symbols or data/text relocation info, quit. */ 93 if (!ep->a_syms && !ep->a_trsize && !ep->a_drsize) 94 return; 95 96 /* 97 * New file size is the header plus text and data segments. 98 */ 99 fsize = N_DATOFF(*ep) + ep->a_data; 100 101 /* Set symbol size and relocation info values to 0. */ 102 ep->a_syms = ep->a_trsize = ep->a_drsize = 0; 103 104 /* Rewrite the header and truncate the file. */ 105 if (lseek(fd, (off_t)0, SEEK_SET) == -1 || 106 write(fd, ep, sizeof(EXEC)) != sizeof(EXEC) || 107 ftruncate(fd, fsize)) 108 err(0, "%s: %s", fn, strerror(errno)); 109 } 110 111 void 112 s_stab(fn, fd, ep) 113 const char *fn; 114 int fd; 115 EXEC *ep; 116 { 117 register int cnt, len; 118 register char *nstr, *nstrbase, *p, *strbase; 119 register NLIST *sym, *nsym; 120 struct stat sb; 121 NLIST *symbase; 122 123 /* Quit if no symbols. */ 124 if (ep->a_syms == 0) 125 return; 126 127 /* Stat the file. */ 128 if (fstat(fd, &sb) < 0) { 129 err(0, "%s: %s", fn, strerror(errno)); 130 return; 131 } 132 133 /* Check size. */ 134 if (sb.st_size > SIZE_T_MAX) { 135 err(0, "%s: %s", fn, strerror(EFBIG)); 136 return; 137 } 138 139 /* Map the file. */ 140 if ((ep = (EXEC *)mmap(NULL, (size_t)sb.st_size, 141 PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0)) == (EXEC *)-1) { 142 err(0, "%s: %s", fn, strerror(errno)); 143 return; 144 } 145 146 /* 147 * Initialize old and new symbol pointers. They both point to the 148 * beginning of the symbol table in memory, since we're deleting 149 * entries. 150 */ 151 sym = nsym = symbase = (NLIST *)((char *)ep + N_SYMOFF(*ep)); 152 153 /* 154 * Allocate space for the new string table, initialize old and 155 * new string pointers. Handle the extra long at the beginning 156 * of the string table. 157 */ 158 strbase = (char *)ep + N_STROFF(*ep); 159 if ((nstrbase = malloc((u_int)*(u_long *)strbase)) == NULL) 160 err(1, "%s", strerror(errno)); 161 nstr = nstrbase + sizeof(u_long); 162 163 /* 164 * Read through the symbol table. For each non-debugging symbol, 165 * copy it and save its string in the new string table. Keep 166 * track of the number of symbols. 167 */ 168 for (cnt = ep->a_syms / sizeof(NLIST); cnt--; ++sym) 169 if (!(sym->n_type & N_STAB) && sym->strx) { 170 *nsym = *sym; 171 nsym->strx = nstr - nstrbase; 172 p = strbase + sym->strx; 173 len = strlen(p) + 1; 174 bcopy(p, nstr, len); 175 nstr += len; 176 ++nsym; 177 } 178 179 /* Fill in new symbol table size. */ 180 ep->a_syms = (nsym - symbase) * sizeof(NLIST); 181 182 /* Fill in the new size of the string table. */ 183 *(u_long *)nstrbase = len = nstr - nstrbase; 184 185 /* 186 * Copy the new string table into place. Nsym should be pointing 187 * at the address past the last symbol entry. 188 */ 189 bcopy(nstrbase, (void *)nsym, len); 190 191 /* Truncate to the current length. */ 192 if (ftruncate(fd, (char *)nsym + len - (char *)ep)) 193 err(0, "%s: %s", fn, strerror(errno)); 194 munmap((caddr_t)ep, (size_t)sb.st_size); 195 } 196 197 void 198 usage() 199 { 200 (void)fprintf(stderr, "usage: strip [-d] file ...\n"); 201 exit(1); 202 } 203 204 #if __STDC__ 205 #include <stdarg.h> 206 #else 207 #include <varargs.h> 208 #endif 209 210 void 211 #if __STDC__ 212 err(int fatal, const char *fmt, ...) 213 #else 214 err(fatal, fmt, va_alist) 215 int fatal; 216 char *fmt; 217 va_dcl 218 #endif 219 { 220 va_list ap; 221 #if __STDC__ 222 va_start(ap, fmt); 223 #else 224 va_start(ap); 225 #endif 226 (void)fprintf(stderr, "strip: "); 227 (void)vfprintf(stderr, fmt, ap); 228 va_end(ap); 229 (void)fprintf(stderr, "\n"); 230 if (fatal) 231 exit(1); 232 eval = 1; 233 } 234