1 /* $NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem 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
30 * crunchide.c - tiptoes through an a.out symbol table, hiding all defined
31 * global symbols. Allows the user to supply a "keep list" of symbols
32 * that are not to be hidden. This program relies on the use of the
33 * linker's -dc flag to actually put global bss data into the file's
34 * bss segment (rather than leaving it as undefined "common" data).
36 * The point of all this is to allow multiple programs to be linked
37 * together without getting multiple-defined errors.
39 * For example, consider a program "foo.c". It can be linked with a
40 * small stub routine, called "foostub.c", eg:
41 * int foo_main(int argc, char **argv){ return main(argc, argv); }
43 * cc -c foo.c foostub.c
44 * ld -dc -r foo.o foostub.o -o foo.combined.o
45 * crunchide -k _foo_main foo.combined.o
46 * at this point, foo.combined.o can be linked with another program
47 * and invoked with "foo_main(argc, argv)". foo's main() and any
48 * other globals are hidden and will not conflict with other symbols.
51 * - resolve the theoretical hanging reloc problem (see check_reloc()
52 * below). I have yet to see this problem actually occur in any real
53 * program. In what cases will gcc/gas generate code that needs a
54 * relative reloc from a global symbol, other than PIC? The
55 * solution is to not hide the symbol from the linker in this case,
56 * but to generate some random name for it so that it doesn't link
57 * with anything but holds the place for the reloc.
58 * - arrange that all the BSS segments start at the same address, so
59 * that the final crunched binary BSS size is the max of all the
60 * component programs' BSS sizes, rather than their sum.
62 #include <sys/cdefs.h>
64 __RCSID("$NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem Exp $");
73 #include <sys/types.h>
75 #include <sys/errno.h>
79 char *pname
= "crunchide";
83 void add_to_keep_list(char *symbol
);
84 void add_file_to_keep_list(char *filename
);
86 int hide_syms(const char *filename
);
90 int main(int, char *[]);
98 if(argc
> 0) pname
= argv
[0];
100 while ((ch
= getopt(argc
, argv
, "k:f:v")) != -1)
103 add_to_keep_list(optarg
);
106 add_file_to_keep_list(optarg
);
118 if(argc
== 0) usage();
122 if (hide_syms(*argv
))
133 "usage: %s [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n",
138 /* ---------------------------- */
145 void 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) break;
156 return; /* already in table */
158 newp
= (struct keep
*) malloc(sizeof(struct keep
));
159 if(newp
) newp
->sym
= strdup(symbol
);
160 if(newp
== NULL
|| newp
->sym
== NULL
) {
161 fprintf(stderr
, "%s: out of memory for keep list\n", pname
);
166 if(prevp
) prevp
->next
= newp
;
167 else keep_list
= newp
;
170 int in_keep_list(const char *symbol
)
177 for(curp
= keep_list
; curp
; curp
= curp
->next
)
178 if((cmp
= strcmp(symbol
, curp
->sym
)) <= 0) break;
180 return curp
&& cmp
== 0;
183 void add_file_to_keep_list(char *filename
)
189 if((keepf
= fopen(filename
, "r")) == NULL
) {
194 while(fgets(symbol
, sizeof(symbol
), keepf
)) {
195 len
= strlen(symbol
);
196 if(len
&& symbol
[len
-1] == '\n')
197 symbol
[len
-1] = '\0';
199 add_to_keep_list(symbol
);
204 /* ---------------------------- */
208 int (*check
)(int, const char *); /* 1 if match, zero if not */
209 int (*hide
)(int, const char *); /* non-zero if error */
212 { "a.out", check_aout
, hide_aout
, },
215 { "ECOFF", check_elf64
, hide_elf64
, },
218 { "ELF32", check_elf32
, hide_elf32
, },
221 { "ELF64", check_elf64
, hide_elf64
, },
225 int hide_syms(const char *filename
)
229 fd
= open(filename
, O_RDWR
, 0);
237 n
= sizeof exec_formats
/ sizeof exec_formats
[0];
238 for (i
= 0; i
< n
; i
++) {
239 if (lseek(fd
, 0, SEEK_SET
) != 0) {
243 if ((*exec_formats
[i
].check
)(fd
, filename
) != 0)
247 fprintf(stderr
, "%s: unknown executable format\n", filename
);
252 fprintf(stderr
, "%s is an %s binary\n", filename
,
253 exec_formats
[i
].name
);
255 if (lseek(fd
, 0, SEEK_SET
) != 0) {
259 rv
= (*exec_formats
[i
].hide
)(fd
, filename
);