xref: /csrg-svn/old/symorder/symorder.c (revision 46222)
1 /*
2  * Copyright (c) 1980 The 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) 1980 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)symorder.c	5.5 (Berkeley) 02/01/91";
16 #endif /* not lint */
17 
18 /*
19  * symorder - reorder symbol table
20  */
21 
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <a.out.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #define SPACE 500
33 
34 struct	nlist order[SPACE];
35 
36 struct	exec exec;
37 struct	stat stb;
38 struct	nlist *newtab, *symtab;
39 off_t	sa;
40 int	nsym, strtabsize, symfound;
41 char	*kfile, *newstrings, *strings, asym[BUFSIZ];
42 
43 main(argc, argv)
44 	int argc;
45 	char **argv;
46 {
47 	register struct nlist *p, *symp;
48 	register FILE *f;
49 	register int i;
50 	register char *start, *t;
51 	int n, o;
52 
53 	if (argc != 3) {
54 		(void)fprintf(stderr, "usage: symorder orderlist file\n");
55 		exit(1);
56 	}
57 	if ((f = fopen(argv[1], "r")) == NULL)
58 		error(argv[1]);
59 
60 	for (p = order; fgets(asym, sizeof(asym), f) != NULL;) {
61 		for (t = asym; isspace(*t); ++t);
62 		if (!*(start = t))
63 			continue;
64 		while (*++t);
65 		if (*--t == '\n')
66 			*t = '\0';
67 		p->n_un.n_name = strdup(start);
68 		++p;
69 		++nsym;
70 	}
71 	(void)fclose(f);
72 
73 	kfile = argv[2];
74 	if ((f = fopen(kfile, "r")) == NULL)
75 		error(kfile);
76 	if ((o = open(kfile, O_WRONLY)) < 0)
77 		error(kfile);
78 
79 	/* read exec header */
80 	if ((fread(&exec, sizeof(exec), 1, f)) != 1)
81 		badfmt("no exec header");
82 	if (N_BADMAG(exec))
83 		badfmt("bad magic number");
84 	if (exec.a_syms == 0)
85 		badfmt("stripped");
86 	(void)fstat(fileno(f), &stb);
87 	if (stb.st_size < N_STROFF(exec) + sizeof(off_t))
88 		badfmt("no string table");
89 
90 	/* seek to and read the symbol table */
91 	sa = N_SYMOFF(exec);
92 	(void)fseek(f, sa, SEEK_SET);
93 	n = exec.a_syms;
94 	if (!(symtab = (struct nlist *)malloc(n)))
95 		error((char *)NULL);
96 	if (fread((char *)symtab, 1, n, f) != n)
97 		badfmt("corrupted symbol table");
98 
99 	/* read string table size and string table */
100 	if (fread((char *)&strtabsize, sizeof(int), 1, f) != 1 ||
101 	    strtabsize <= 0)
102 		badfmt("corrupted string table");
103 	strings = malloc(strtabsize);
104 	if (strings == (char *)NULL)
105 		error((char *)NULL);
106 	/*
107 	 * Subtract four from strtabsize since strtabsize includes itself,
108 	 * and we've already read it.
109 	 */
110 	if (fread(strings, 1, strtabsize - sizeof(int), f) !=
111 	    strtabsize - sizeof(int))
112 		badfmt("corrupted string table");
113 
114 	newtab = (struct nlist *)malloc(n);
115 	if (newtab == (struct nlist *)NULL)
116 		error((char *)NULL);
117 
118 	i = n / sizeof(struct nlist);
119 	reorder(symtab, newtab, i);
120 	free((char *)symtab);
121 	symtab = newtab;
122 
123 	newstrings = malloc(strtabsize);
124 	if (newstrings == (char *)NULL)
125 		error((char *)NULL);
126 	t = newstrings;
127 	for (symp = symtab; --i >= 0; symp++) {
128 		if (symp->n_un.n_strx == 0)
129 			continue;
130 		symp->n_un.n_strx -= sizeof(int);
131 		(void)strcpy(t, &strings[symp->n_un.n_strx]);
132 		symp->n_un.n_strx = (t - newstrings) + sizeof(int);
133 		t += strlen(t) + 1;
134 	}
135 
136 	(void)lseek(o, sa, SEEK_SET);
137 	if (write(o, (char *)symtab, n) != n)
138 		error(kfile);
139 	if (write(o, (char *)&strtabsize, sizeof(int)) != sizeof(int))
140 		error(kfile);
141 	if (write(o, newstrings, strtabsize - sizeof(int)) !=
142 	    strtabsize - sizeof(int))
143 		error(kfile);
144 	if ((i = nsym - symfound) > 0) {
145 		(void)printf("symorder: %d symbol%s not found:\n",
146 		    i, i == 1 ? "" : "s");
147 		for (i = 0; i < nsym; i++)
148 			if (order[i].n_value == 0)
149 				printf("%s\n", order[i].n_un.n_name);
150 	}
151 	exit(0);
152 }
153 
154 reorder(st1, st2, entries)
155 	register struct nlist *st1, *st2;
156 	int entries;
157 {
158 	register struct nlist *p;
159 	register int i, n;
160 
161 	for (p = st1, n = entries; --n >= 0; ++p)
162 		if (inlist(p) != -1)
163 			++symfound;
164 	for (p = st2 + symfound, n = entries; --n >= 0; ++st1) {
165 		i = inlist(st1);
166 		if (i == -1)
167 			*p++ = *st1;
168 		else
169 			st2[i] = *st1;
170 	}
171 }
172 
173 inlist(p)
174 	register struct nlist *p;
175 {
176 	register char *nam;
177 	register struct nlist *op;
178 
179 	if (p->n_type & N_STAB)
180 		return (-1);
181 	if (p->n_un.n_strx == 0)
182 		return (-1);
183 
184 	if (p->n_un.n_strx >= strtabsize)
185 		badfmt("corrupted symbol table");
186 
187 	nam = &strings[p->n_un.n_strx - sizeof(int)];
188 	for (op = &order[nsym]; --op >= order; ) {
189 		if (strcmp(op->n_un.n_name, nam) != 0)
190 			continue;
191 		op->n_value = 1;
192 		return (op - order);
193 	}
194 	return (-1);
195 }
196 
197 badfmt(why)
198 	char *why;
199 {
200 	(void)fprintf(stderr,
201 	    "symorder: %s: %s: %s\n", kfile, why, strerror(EFTYPE));
202 	exit(1);
203 }
204 
205 error(n)
206 	char *n;
207 {
208 	int sverr;
209 
210 	sverr = errno;
211 	(void)fprintf(stderr, "symorder: ");
212 	if (n)
213 		(void)fprintf(stderr, "%s: ", n);
214 	(void)fprintf(stderr, "%s\n", strerror(sverr));
215 	exit(1);
216 }
217