xref: /original-bsd/usr.bin/strip/strip.c (revision 155be1a3)
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