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