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