xref: /original-bsd/usr.bin/strip/strip.c (revision 6b651452)
14caa1449Sdist /*
29e2b6c6eSbostic  * Copyright (c) 1988, 1993
39e2b6c6eSbostic  *	The Regents of the University of California.  All rights reserved.
44155dea5Sbostic  *
5b6f040b4Sbostic  * %sccs.include.redist.c%
64caa1449Sdist  */
74caa1449Sdist 
81f71f7eaSsam #ifndef lint
99e2b6c6eSbostic static char copyright[] =
109e2b6c6eSbostic "@(#) Copyright (c) 1988, 1993\n\
119e2b6c6eSbostic 	The Regents of the University of California.  All rights reserved.\n";
124155dea5Sbostic #endif /* not lint */
134caa1449Sdist 
144caa1449Sdist #ifndef lint
15*6b651452Sbostic static char sccsid[] = "@(#)strip.c	8.3 (Berkeley) 05/16/95";
164155dea5Sbostic #endif /* not lint */
171f71f7eaSsam 
184155dea5Sbostic #include <sys/types.h>
1938db7755Sbostic #include <sys/stat.h>
20802ac1c5Sbostic #include <sys/mman.h>
21a100fa84Sbostic 
224155dea5Sbostic #include <a.out.h>
239f522cd5Sbostic #include <err.h>
249f522cd5Sbostic #include <errno.h>
259f522cd5Sbostic #include <fcntl.h>
269f522cd5Sbostic #include <limits.h>
274155dea5Sbostic #include <stdio.h>
28251518a8Sbostic #include <stdlib.h>
29251518a8Sbostic #include <string.h>
309f522cd5Sbostic #include <unistd.h>
31251518a8Sbostic 
322a747c51Sbostic typedef struct exec EXEC;
3338db7755Sbostic typedef struct nlist NLIST;
3438db7755Sbostic 
35802ac1c5Sbostic #define	strx	n_un.n_strx
36802ac1c5Sbostic 
3738db7755Sbostic void s_stab __P((const char *, int, EXEC *));
3838db7755Sbostic void s_sym __P((const char *, int, EXEC *));
3938db7755Sbostic void usage __P((void));
4038db7755Sbostic 
41af0dd030Sbostic int
main(argc,argv)42d36f38bcSbill main(argc, argv)
434155dea5Sbostic 	int argc;
44251518a8Sbostic 	char *argv[];
45d36f38bcSbill {
4638db7755Sbostic 	register int fd, nb;
474155dea5Sbostic 	EXEC head;
4838db7755Sbostic 	void (*sfcn)__P((const char *, int, EXEC *));
499f522cd5Sbostic 	int ch, eval;
5038db7755Sbostic 	char *fn;
51251518a8Sbostic 
5238db7755Sbostic 	sfcn = s_sym;
53251518a8Sbostic 	while ((ch = getopt(argc, argv, "d")) != EOF)
54251518a8Sbostic 		switch(ch) {
55251518a8Sbostic 		case 'd':
5638db7755Sbostic 			sfcn = s_stab;
57251518a8Sbostic 			break;
58251518a8Sbostic 		case '?':
59251518a8Sbostic 		default:
60251518a8Sbostic 			usage();
61251518a8Sbostic 		}
62251518a8Sbostic 	argc -= optind;
63251518a8Sbostic 	argv += optind;
64d36f38bcSbill 
65*6b651452Sbostic 	for (eval = 0; (fn = *argv++) != NULL;) {
669f522cd5Sbostic 		if ((fd = open(fn, O_RDWR)) < 0) {
679f522cd5Sbostic 			warn("%s", fn);
689f522cd5Sbostic 			eval = 1;
699f522cd5Sbostic 			continue;
709f522cd5Sbostic 		}
719f522cd5Sbostic 		if ((nb = read(fd, &head, sizeof(EXEC))) == -1) {
729f522cd5Sbostic 			warn("%s", fn);
739f522cd5Sbostic 			(void)close(fd);
749f522cd5Sbostic 			eval = 1;
754155dea5Sbostic 			continue;
76251518a8Sbostic 		}
7738db7755Sbostic 		if (nb != sizeof(EXEC) || N_BADMAG(head)) {
789f522cd5Sbostic 			warnx("%s: %s", fn, strerror(EFTYPE));
799f522cd5Sbostic 			(void)close(fd);
809f522cd5Sbostic 			eval = 1;
81251518a8Sbostic 			continue;
82251518a8Sbostic 		}
8338db7755Sbostic 		sfcn(fn, fd, &head);
849f522cd5Sbostic 		if (close(fd)) {
859f522cd5Sbostic 			warn("%s", fn);
869f522cd5Sbostic 			eval = 1;
879f522cd5Sbostic 		}
88251518a8Sbostic 	}
89a100fa84Sbostic 	exit(eval);
904155dea5Sbostic }
914155dea5Sbostic 
9238db7755Sbostic void
s_sym(fn,fd,ep)9338db7755Sbostic s_sym(fn, fd, ep)
9438db7755Sbostic 	const char *fn;
9538db7755Sbostic 	int fd;
9638db7755Sbostic 	register EXEC *ep;
9738db7755Sbostic {
9838db7755Sbostic 	register off_t fsize;
9938db7755Sbostic 
10038db7755Sbostic 	/* If no symbols or data/text relocation info, quit. */
10138db7755Sbostic 	if (!ep->a_syms && !ep->a_trsize && !ep->a_drsize)
10238db7755Sbostic 		return;
10338db7755Sbostic 
10438db7755Sbostic 	/*
1053df4c0f1Sralph 	 * New file size is the header plus text and data segments.
10638db7755Sbostic 	 */
1073df4c0f1Sralph 	fsize = N_DATOFF(*ep) + ep->a_data;
10838db7755Sbostic 
10938db7755Sbostic 	/* Set symbol size and relocation info values to 0. */
11038db7755Sbostic 	ep->a_syms = ep->a_trsize = ep->a_drsize = 0;
11138db7755Sbostic 
11238db7755Sbostic 	/* Rewrite the header and truncate the file. */
113af0dd030Sbostic 	if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
11438db7755Sbostic 	    write(fd, ep, sizeof(EXEC)) != sizeof(EXEC) ||
11538db7755Sbostic 	    ftruncate(fd, fsize))
116a100fa84Sbostic 		err(0, "%s: %s", fn, strerror(errno));
11738db7755Sbostic }
11838db7755Sbostic 
11938db7755Sbostic void
s_stab(fn,fd,ep)12038db7755Sbostic s_stab(fn, fd, ep)
12138db7755Sbostic 	const char *fn;
12238db7755Sbostic 	int fd;
12338db7755Sbostic 	EXEC *ep;
12438db7755Sbostic {
125af0dd030Sbostic 	register int cnt, len;
126802ac1c5Sbostic 	register char *nstr, *nstrbase, *p, *strbase;
127802ac1c5Sbostic 	register NLIST *sym, *nsym;
12838db7755Sbostic 	struct stat sb;
129802ac1c5Sbostic 	NLIST *symbase;
13038db7755Sbostic 
13138db7755Sbostic 	/* Quit if no symbols. */
13238db7755Sbostic 	if (ep->a_syms == 0)
13338db7755Sbostic 		return;
13438db7755Sbostic 
13562ae4d88Sbostic 	/* Stat the file. */
13662ae4d88Sbostic 	if (fstat(fd, &sb) < 0) {
13762ae4d88Sbostic 		err(0, "%s: %s", fn, strerror(errno));
13862ae4d88Sbostic 		return;
13962ae4d88Sbostic 	}
14062ae4d88Sbostic 
141a100fa84Sbostic 	/* Check size. */
142a100fa84Sbostic 	if (sb.st_size > SIZE_T_MAX) {
143a100fa84Sbostic 		err(0, "%s: %s", fn, strerror(EFBIG));
144a100fa84Sbostic 		return;
145a100fa84Sbostic 	}
146a100fa84Sbostic 
147802ac1c5Sbostic 	/* Map the file. */
14862ae4d88Sbostic 	if ((ep = (EXEC *)mmap(NULL, (size_t)sb.st_size,
149a100fa84Sbostic 	    PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0)) == (EXEC *)-1) {
150a100fa84Sbostic 		err(0, "%s: %s", fn, strerror(errno));
151a100fa84Sbostic 		return;
152a100fa84Sbostic 	}
15338db7755Sbostic 
15438db7755Sbostic 	/*
155802ac1c5Sbostic 	 * Initialize old and new symbol pointers.  They both point to the
156802ac1c5Sbostic 	 * beginning of the symbol table in memory, since we're deleting
157802ac1c5Sbostic 	 * entries.
15838db7755Sbostic 	 */
159802ac1c5Sbostic 	sym = nsym = symbase = (NLIST *)((char *)ep + N_SYMOFF(*ep));
160802ac1c5Sbostic 
161802ac1c5Sbostic 	/*
162802ac1c5Sbostic 	 * Allocate space for the new string table, initialize old and
163802ac1c5Sbostic 	 * new string pointers.  Handle the extra long at the beginning
164802ac1c5Sbostic 	 * of the string table.
165802ac1c5Sbostic 	 */
166802ac1c5Sbostic 	strbase = (char *)ep + N_STROFF(*ep);
167802ac1c5Sbostic 	if ((nstrbase = malloc((u_int)*(u_long *)strbase)) == NULL)
168a100fa84Sbostic 		err(1, "%s", strerror(errno));
169802ac1c5Sbostic 	nstr = nstrbase + sizeof(u_long);
17038db7755Sbostic 
17138db7755Sbostic 	/*
17238db7755Sbostic 	 * Read through the symbol table.  For each non-debugging symbol,
173802ac1c5Sbostic 	 * copy it and save its string in the new string table.  Keep
174802ac1c5Sbostic 	 * track of the number of symbols.
17538db7755Sbostic 	 */
176802ac1c5Sbostic 	for (cnt = ep->a_syms / sizeof(NLIST); cnt--; ++sym)
177802ac1c5Sbostic 		if (!(sym->n_type & N_STAB) && sym->strx) {
178802ac1c5Sbostic 			*nsym = *sym;
179802ac1c5Sbostic 			nsym->strx = nstr - nstrbase;
180802ac1c5Sbostic 			p = strbase + sym->strx;
18138db7755Sbostic 			len = strlen(p) + 1;
182802ac1c5Sbostic 			bcopy(p, nstr, len);
183802ac1c5Sbostic 			nstr += len;
184802ac1c5Sbostic 			++nsym;
18538db7755Sbostic 		}
18638db7755Sbostic 
18738db7755Sbostic 	/* Fill in new symbol table size. */
188802ac1c5Sbostic 	ep->a_syms = (nsym - symbase) * sizeof(NLIST);
18938db7755Sbostic 
19038db7755Sbostic 	/* Fill in the new size of the string table. */
191802ac1c5Sbostic 	*(u_long *)nstrbase = len = nstr - nstrbase;
19238db7755Sbostic 
193802ac1c5Sbostic 	/*
194802ac1c5Sbostic 	 * Copy the new string table into place.  Nsym should be pointing
195802ac1c5Sbostic 	 * at the address past the last symbol entry.
196802ac1c5Sbostic 	 */
197802ac1c5Sbostic 	bcopy(nstrbase, (void *)nsym, len);
19838db7755Sbostic 
19938db7755Sbostic 	/* Truncate to the current length. */
200802ac1c5Sbostic 	if (ftruncate(fd, (char *)nsym + len - (char *)ep))
201a100fa84Sbostic 		err(0, "%s: %s", fn, strerror(errno));
202010ad3f0Sbostic 	munmap((caddr_t)ep, (size_t)sb.st_size);
20338db7755Sbostic }
20438db7755Sbostic 
20538db7755Sbostic void
usage()206251518a8Sbostic usage()
2074155dea5Sbostic {
208251518a8Sbostic 	(void)fprintf(stderr, "usage: strip [-d] file ...\n");
2094155dea5Sbostic 	exit(1);
210d36f38bcSbill }
211