2 * Copyright (c) 1980 The Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#) Copyright (c) 1980 The Regents of the University of California. All rights reserved.
34 * @(#)symorder.c 5.8 (Berkeley) 4/1/91
35 * $FreeBSD: src/usr.bin/symorder/symorder.c,v 1.15 1999/08/28 01:05:57 peter Exp $
36 * $DragonFly: src/usr.bin/symorder/symorder.c,v 1.3 2003/10/04 20:36:51 hmp Exp $
40 * symorder - reorder symbol table
43 #include <sys/types.h>
58 #define NOTFOUNDEXIT 1
62 struct nlist order
[SPACE
];
66 struct nlist
*newtab
, *symtab
;
68 int nexclude
, nsym
, strtabsize
, symfound
, symkept
, small
, missing
, clean
;
69 char *kfile
, *newstrings
, *strings
, asym
[BUFSIZ
];
72 int excluded(struct nlist
*);
73 int inlist(struct nlist
*);
74 void reorder(struct nlist
*, struct nlist
*, int);
75 int savesymb(struct nlist
*);
76 static void usage(void);
79 main(int argc
, char **argv
)
81 register struct nlist
*p
, *symp
;
82 register FILE *f
, *xfile
;
84 register char *start
, *t
, *xfilename
;
88 while ((ch
= getopt(argc
, argv
, "cmtx:")) != -1)
100 if (xfilename
!= NULL
)
114 if ((f
= fopen(argv
[0], "r")) == NULL
)
115 err(ERREXIT
, "%s", argv
[0]);
117 for (p
= order
; fgets(asym
, sizeof(asym
), f
) != NULL
;) {
118 for (t
= asym
; isspace(*t
); ++t
);
124 p
->n_un
.n_name
= strdup(start
);
126 if (++nsym
>= sizeof order
/ sizeof order
[0])
131 if (xfilename
!= NULL
) {
132 if ((xfile
= fopen(xfilename
, "r")) == NULL
)
133 err(ERREXIT
, "%s", xfilename
);
134 for (; fgets(asym
, sizeof(asym
), xfile
) != NULL
;) {
135 for (t
= asym
; isspace(*t
); ++t
);
141 exclude
[nexclude
] = strdup(start
);
142 if (++nexclude
>= sizeof exclude
/ sizeof exclude
[0])
149 if ((f
= fopen(kfile
, "r")) == NULL
)
150 err(ERREXIT
, "%s", kfile
);
151 if ((o
= open(kfile
, O_WRONLY
)) < 0)
152 err(ERREXIT
, "%s", kfile
);
154 /* read exec header */
155 if ((fread(&exec
, sizeof(exec
), 1, f
)) != 1)
156 badfmt("no exec header");
158 badfmt("bad magic number");
159 if (exec
.a_syms
== 0)
161 (void)fstat(fileno(f
), &stb
);
162 if (stb
.st_size
< N_STROFF(exec
) + sizeof(off_t
))
163 badfmt("no string table");
165 /* seek to and read the symbol table */
167 (void)fseek(f
, sa
, SEEK_SET
);
169 if (!(symtab
= (struct nlist
*)malloc(n
)))
171 if (fread((void *)symtab
, 1, n
, f
) != n
)
172 badfmt("corrupted symbol table");
174 /* read string table size and string table */
175 if (fread((void *)&strtabsize
, sizeof(int), 1, f
) != 1 ||
177 badfmt("corrupted string table");
178 strings
= malloc(strtabsize
);
182 * Subtract four from strtabsize since strtabsize includes itself,
183 * and we've already read it.
185 if (fread(strings
, 1, strtabsize
- sizeof(int), f
) !=
186 strtabsize
- sizeof(int))
187 badfmt("corrupted string table");
189 i
= n
/ sizeof(struct nlist
);
191 newtab
= (struct nlist
*)malloc(n
);
192 if (newtab
== (struct nlist
*)NULL
)
194 memset(newtab
, 0, n
);
196 reorder(symtab
, newtab
, i
);
197 free((void *)symtab
);
203 newstrings
= malloc(strtabsize
);
204 if (newstrings
== NULL
)
207 for (symp
= symtab
; --i
>= 0; symp
++) {
208 if (symp
->n_un
.n_strx
== 0)
210 if (inlist(symp
) < 0) {
213 if (clean
&& !savesymb(symp
))
214 symp
->n_type
&= ~N_EXT
;
217 symp
->n_un
.n_strx
-= sizeof(int);
218 (void)strcpy(t
, &strings
[symp
->n_un
.n_strx
]);
219 symp
->n_un
.n_strx
= (t
- newstrings
) + sizeof(int);
223 /* update shrunk sizes */
224 strtabsize
= t
- newstrings
+ sizeof(int);
225 n
= symkept
* sizeof(struct nlist
);
227 /* fix exec sym size */
228 (void)lseek(o
, (off_t
)0, SEEK_SET
);
230 if (write(o
, (void *)&exec
, sizeof(exec
)) != sizeof(exec
))
231 err(ERREXIT
, "%s", kfile
);
233 (void)lseek(o
, sa
, SEEK_SET
);
234 if (write(o
, (void *)symtab
, n
) != n
)
235 err(ERREXIT
, "%s", kfile
);
236 if (write(o
, (void *)&strtabsize
, sizeof(int)) != sizeof(int))
237 err(ERREXIT
, "%s", kfile
);
238 if (write(o
, newstrings
, strtabsize
- sizeof(int)) !=
239 strtabsize
- sizeof(int))
240 err(ERREXIT
, "%s", kfile
);
242 ftruncate(o
, lseek(o
, (off_t
)0, SEEK_CUR
));
244 if ((i
= nsym
- symfound
) > 0) {
245 (void)printf("symorder: %d symbol%s not found:\n",
246 i
, i
== 1 ? "" : "s");
247 for (i
= 0; i
< nsym
; i
++)
248 if (order
[i
].n_value
== 0)
249 printf("%s\n", order
[i
].n_un
.n_name
);
257 savesymb(register struct nlist
*s
)
259 if ((s
->n_type
& N_EXT
) != N_EXT
)
261 switch (s
->n_type
& N_TYPE
) {
271 reorder(register struct nlist
*st1
, register struct nlist
*st2
, int entries
)
273 register struct nlist
*p
;
276 for (p
= st1
, n
= entries
; --n
>= 0; ++p
)
279 for (p
= st2
+ symfound
, n
= entries
; --n
>= 0; ++st1
) {
292 inlist(register struct nlist
*p
)
295 register struct nlist
*op
;
297 if (p
->n_type
& N_STAB
|| p
->n_un
.n_strx
== 0)
299 if (p
->n_un
.n_strx
< sizeof(int) || p
->n_un
.n_strx
>= strtabsize
)
300 badfmt("corrupted symbol table");
301 nam
= &strings
[p
->n_un
.n_strx
- sizeof(int)];
302 for (op
= &order
[nsym
]; --op
>= order
; ) {
303 if (strcmp(op
->n_un
.n_name
, nam
) != 0)
312 excluded(register struct nlist
*p
)
317 if (p
->n_type
& N_STAB
|| p
->n_un
.n_strx
== 0)
319 if (p
->n_un
.n_strx
< sizeof(int) || p
->n_un
.n_strx
>= strtabsize
)
320 badfmt("corrupted symbol table");
321 nam
= &strings
[p
->n_un
.n_strx
- sizeof(int)];
322 for (x
= nexclude
; --x
>= 0; )
323 if (strcmp(nam
, exclude
[x
]) == 0)
331 errx(ERREXIT
, "%s: %s: %s", kfile
, why
, strerror(EFTYPE
));
337 (void)fprintf(stderr
,
338 "usage: symorder [-c] [-m] [-t] [-x excludelist] symlist file\n");