1 /* $NetBSD: crunchide.c,v 1.12 2004/08/24 12:25:26 wiz Exp $ */
4 * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved.
5 * Copyright (c) 1994 University of Maryland
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of U.M. not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. U.M. makes no representations about the
15 * suitability of this software for any purpose. It is provided "as is"
16 * without express or implied warranty.
18 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
20 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 * Author: James da Silva, Systems Design and Analysis Group
26 * Computer Science Department
27 * University of Maryland at College Park
31 * crunchide.c - tiptoes through a symbol table, hiding all defined
32 * global symbols. Allows the user to supply a "keep list" of symbols
33 * that are not to be hidden. This program relies on the use of the
34 * linker's -dc flag to actually put global bss data into the file's
35 * bss segment (rather than leaving it as undefined "common" data).
37 * The point of all this is to allow multiple programs to be linked
38 * together without getting multiple-defined errors.
40 * For example, consider a program "foo.c". It can be linked with a
41 * small stub routine, called "foostub.c", eg:
42 * int foo_main(int argc, char **argv){ return main(argc, argv); }
44 * cc -c foo.c foostub.c
45 * ld -dc -r foo.o foostub.o -o foo.combined.o
46 * crunchide -k _foo_main foo.combined.o
47 * at this point, foo.combined.o can be linked with another program
48 * and invoked with "foo_main(argc, argv)". foo's main() and any
49 * other globals are hidden and will not conflict with other symbols.
52 * - resolve the theoretical hanging reloc problem (see check_reloc()
53 * below). I have yet to see this problem actually occur in any real
54 * program. In what cases will gcc/gas generate code that needs a
55 * relative reloc from a global symbol, other than PIC? The
56 * solution is to not hide the symbol from the linker in this case,
57 * but to generate some random name for it so that it doesn't link
58 * with anything but holds the place for the reloc.
59 * - arrange that all the BSS segments start at the same address, so
60 * that the final crunched binary BSS size is the max of all the
61 * component programs' BSS sizes, rather than their sum.
64 #include <sys/cdefs.h>
66 __RCSID("$NetBSD: crunchide.c,v 1.12 2004/08/24 12:25:26 wiz Exp $");
75 #include <sys/types.h>
82 void add_to_keep_list(char *symbol
);
83 void add_file_to_keep_list(char *filename
);
85 int hide_syms(const char *filename
);
90 main(int argc
, char *argv
[])
96 while ((ch
= getopt(argc
, argv
, "k:f:v")) != -1)
99 add_to_keep_list(optarg
);
102 add_file_to_keep_list(optarg
);
119 if (hide_syms(*argv
))
131 "Usage: %s [-k keep-symbol] [-f keep-list-file] object-file\n"
132 "\t\t [object-file ...]\n",
137 /* ---------------------------- */
145 add_to_keep_list(char *symbol
)
147 struct keep
*newp
, *prevp
, *curp
;
152 for (curp
= keep_list
, prevp
= NULL
; curp
; prevp
= curp
, curp
= curp
->next
)
153 if ((cmp
= strcmp(symbol
, curp
->sym
)) <= 0)
156 if (curp
&& cmp
== 0)
157 return; /* already in table */
159 newp
= (struct keep
*) malloc(sizeof(struct keep
));
161 newp
->sym
= strdup(symbol
);
162 if (newp
== NULL
|| newp
->sym
== NULL
) {
163 fprintf(stderr
, "%s: out of memory for keep list\n", getprogname());
175 in_keep_list(const char *symbol
)
182 for (curp
= keep_list
; curp
; curp
= curp
->next
)
183 if((cmp
= strcmp(symbol
, curp
->sym
)) <= 0)
186 return curp
&& cmp
== 0;
190 add_file_to_keep_list(char *filename
)
196 if ((keepf
= fopen(filename
, "r")) == NULL
) {
201 while (fgets(symbol
, 1024, keepf
)) {
202 len
= strlen(symbol
);
203 if (len
&& symbol
[len
-1] == '\n')
204 symbol
[len
-1] = '\0';
206 add_to_keep_list(symbol
);
211 /* ---------------------------- */
215 int (*check
)(int, const char *); /* 1 if match, zero if not */
216 int (*hide
)(int, const char *); /* non-zero if error */
219 { "a.out", check_aout
, hide_aout
, },
222 { "COFF", check_coff
, hide_coff
, },
225 { "ECOFF", check_ecoff
, hide_ecoff
, },
228 { "ELF32", check_elf32
, hide_elf32
, },
231 { "ELF64", check_elf64
, hide_elf64
, },
236 hide_syms(const char *filename
)
240 fd
= open(filename
, O_RDWR
, 0);
248 n
= sizeof exec_formats
/ sizeof exec_formats
[0];
249 for (i
= 0; i
< n
; i
++) {
250 if (lseek(fd
, 0, SEEK_SET
) != 0) {
254 if ((*exec_formats
[i
].check
)(fd
, filename
) != 0)
258 fprintf(stderr
, "%s: unknown executable format\n", filename
);
263 fprintf(stderr
, "%s is an %s binary\n", filename
,
264 exec_formats
[i
].name
);
266 if (lseek(fd
, 0, SEEK_SET
) != 0) {
270 rv
= (*exec_formats
[i
].hide
)(fd
, filename
);