GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/crunchgen/crunchide.c Lines: 0 70 0.0 %
Date: 2017-11-13 Branches: 0 57 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: crunchide.c,v 1.12 2017/10/29 08:45:53 mpi Exp $	 */
2
3
/*
4
 * Copyright (c) 1994 University of Maryland
5
 * All Rights Reserved.
6
 *
7
 * Permission to use, copy, modify, distribute, and sell this software and its
8
 * documentation for any purpose is hereby granted without fee, provided that
9
 * the above copyright notice appear in all copies and that both that
10
 * copyright notice and this permission notice appear in supporting
11
 * documentation, and that the name of U.M. not be used in advertising or
12
 * publicity pertaining to distribution of the software without specific,
13
 * written prior permission.  U.M. makes no representations about the
14
 * suitability of this software for any purpose.  It is provided "as is"
15
 * without express or implied warranty.
16
 *
17
 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
 *
24
 * Author: James da Silva, Systems Design and Analysis Group
25
 *			   Computer Science Department
26
 *			   University of Maryland at College Park
27
 */
28
/*
29
 * crunchide.c - tiptoes through an a.out symbol table, hiding all defined
30
 *	global symbols.  Allows the user to supply a "keep list" of symbols
31
 *	that are not to be hidden.  This program relies on the use of the
32
 * 	linker's -dc flag to actually put global bss data into the file's
33
 * 	bss segment (rather than leaving it as undefined "common" data).
34
 *
35
 * 	The point of all this is to allow multiple programs to be linked
36
 *	together without getting multiple-defined errors.
37
 *
38
 *	For example, consider a program "foo.c".  It can be linked with a
39
 *	small stub routine, called "foostub.c", eg:
40
 *	    int foo_main(int argc, char **argv){ return main(argc, argv); }
41
 *      like so:
42
 *	    cc -c foo.c foostub.c
43
 *	    ld -dc -r foo.o foostub.o -o foo.combined.o
44
 *	    crunchide -k _foo_main foo.combined.o
45
 *	at this point, foo.combined.o can be linked with another program
46
 * 	and invoked with "foo_main(argc, argv)".  foo's main() and any
47
 * 	other globals are hidden and will not conflict with other symbols.
48
 *
49
 * TODO:
50
 *      - arrange that all the BSS segments start at the same address, so
51
 *	  that the final crunched binary BSS size is the max of all the
52
 *	  component programs' BSS sizes, rather than their sum.
53
 */
54
55
#include <sys/types.h>
56
#include <sys/mman.h>
57
#include <sys/stat.h>
58
59
#include <elf.h>
60
#include <fcntl.h>
61
#include <stdint.h>
62
#include <stdio.h>
63
#include <stdlib.h>
64
#include <string.h>
65
#include <unistd.h>
66
67
#include "mangle.h"
68
69
void	usage(void);
70
71
void	add_to_keep_list(char *);
72
void	add_file_to_keep_list(char *);
73
74
void	hide_syms(char *);
75
void	elf_hide(int, char *);
76
int	in_keep_list(char *symbol);
77
int	crunchide_main(int argc, char *argv[]);
78
79
extern char	*__progname;
80
extern int elf_mangle;
81
82
int
83
crunchide_main(int argc, char *argv[])
84
{
85
	int             ch;
86
87
	while ((ch = getopt(argc, argv, "Mhk:f:")) != -1)
88
		switch (ch) {
89
		case 'M':
90
			elf_mangle = 1;
91
			break;
92
		case 'h':
93
			break;
94
		case 'k':
95
			add_to_keep_list(optarg);
96
			break;
97
		case 'f':
98
			add_file_to_keep_list(optarg);
99
			break;
100
		default:
101
			usage();
102
		}
103
104
	argc -= optind;
105
	argv += optind;
106
107
	if (argc == 0)
108
		usage();
109
110
	if (elf_mangle)
111
		init_mangle_state();
112
113
	while (argc) {
114
		hide_syms(*argv);
115
		argc--;
116
		argv++;
117
	}
118
	if (elf_mangle)
119
		fini_mangle_state();
120
121
	return 0;
122
}
123
124
struct keep {
125
	struct keep    *next;
126
	char           *sym;
127
} *keep_list;
128
129
void
130
add_to_keep_list(char *symbol)
131
{
132
	struct keep    *newp, *prevp, *curp;
133
	int             cmp = 0;
134
135
	for (curp = keep_list, prevp = NULL; curp; prevp = curp, curp = curp->next)
136
		if ((cmp = strcmp(symbol, curp->sym)) <= 0)
137
			break;
138
139
	if (curp && cmp == 0)
140
		return;		/* already in table */
141
142
	newp = calloc(1, sizeof(struct keep));
143
	if (newp)
144
		newp->sym = strdup(symbol);
145
	if (newp == NULL || newp->sym == NULL) {
146
		fprintf(stderr, "%s: out of memory for keep list\n", __progname);
147
		exit(1);
148
	}
149
	newp->next = curp;
150
	if (prevp)
151
		prevp->next = newp;
152
	else
153
		keep_list = newp;
154
}
155
156
int
157
in_keep_list(char *symbol)
158
{
159
	struct keep    *curp;
160
	int             cmp = 0;
161
162
	for (curp = keep_list; curp; curp = curp->next)
163
		if ((cmp = strcmp(symbol, curp->sym)) <= 0)
164
			break;
165
166
	return curp && cmp == 0;
167
}
168
169
void
170
add_file_to_keep_list(char *filename)
171
{
172
	FILE           *keepf;
173
	char            symbol[1024];
174
	int             len;
175
176
	if ((keepf = fopen(filename, "r")) == NULL) {
177
		perror(filename);
178
		usage();
179
	}
180
	while (fgets(symbol, sizeof(symbol), keepf)) {
181
		len = strlen(symbol);
182
		if (len && symbol[len - 1] == '\n')
183
			symbol[len - 1] = '\0';
184
185
		add_to_keep_list(symbol);
186
	}
187
	fclose(keepf);
188
}
189
190
void
191
hide_syms(char *filename)
192
{
193
	int             inf;
194
	struct stat     infstat;
195
	char           *buf;
196
197
	/*
198
         * Open the file and do some error checking.
199
         */
200
201
	if ((inf = open(filename, O_RDWR)) == -1) {
202
		perror(filename);
203
		return;
204
	}
205
	if (fstat(inf, &infstat) == -1) {
206
		perror(filename);
207
		close(inf);
208
		return;
209
	}
210
	if (infstat.st_size < sizeof(Elf_Ehdr) || infstat.st_size > SIZE_MAX) {
211
		fprintf(stderr, "%s: invalid file size\n", filename);
212
		close(inf);
213
		return;
214
	}
215
	if ((buf = mmap(NULL, infstat.st_size, PROT_READ | PROT_WRITE,
216
	    MAP_FILE | MAP_SHARED, inf, 0)) == MAP_FAILED) {
217
		fprintf(stderr, "%s: cannot map\n", filename);
218
		close(inf);
219
		return;
220
	}
221
222
	if (buf[0] == ELFMAG0 && buf[1] == ELFMAG1 &&
223
	    buf[2] == ELFMAG2 && buf[3] == ELFMAG3) {
224
		elf_hide(inf, buf);
225
		return;
226
	}
227
228
	close(inf);
229
}