xref: /openbsd-src/usr.sbin/crunchgen/elf_hide.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /* $OpenBSD: elf_hide.c,v 1.8 2014/05/20 01:25:24 guenther Exp $ */
2 
3 /*
4  * Copyright (c) 1997 Dale Rahn.
5  * All rights reserved.
6  *
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <sys/mman.h>
31 #include <sys/stat.h>
32 #include <err.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/exec.h>
40 #include "mangle.h"
41 
42 #ifdef _NLIST_DO_ELF
43 #include <sys/exec_elf.h>
44 
45 extern	int elf_mangle;
46 
47 void	load_strtab(Elf_Ehdr * pehdr, char *pexe);
48 void	dump_strtab(void);
49 char	*get_str(int indx);
50 
51 void	load_symtab(Elf_Ehdr * pehdr, char *pexe);
52 void	dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize);
53 void	fprint_str(FILE * channel, int indx);
54 
55 void	load_shstr_tab(Elf_Ehdr * pehdr, char *pexe);
56 char	*get_shstr(int indx);
57 void	fprint_shstr(FILE * channel, int indx);
58 
59 void	hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
60 	    Elf_Sym * symtab, int symtabsize, int symtabsecnum);
61 void	reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
62 	    Elf_Sym * symtab, int symtabsize, int symtabsecnum);
63 typedef long    Symmap;
64 void	renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap,
65 	    int symtabsecnum);
66 void	elf_hide(int pfile, char *p);
67 
68 
69 char           *pexe;
70 
71 void
72 elf_hide(int pfile, char *p)
73 {
74 	Elf_Ehdr       *pehdr;
75 #ifdef DEBUG
76 	Elf_Shdr       *pshdr;
77 	Elf_Phdr       *pphdr;
78 	int             i;
79 #endif
80 
81 	pexe = p;
82 	pehdr = (Elf_Ehdr *) pexe;
83 
84 #ifdef DEBUG
85 	printf("elf header\n");
86 	printf("e_type %x\n", pehdr->e_type);
87 	printf("e_machine %x\n", pehdr->e_machine);
88 	printf("e_version %x\n", pehdr->e_version);
89 	printf("e_entry %x\n", pehdr->e_entry);
90 	printf("e_phoff %x\n", pehdr->e_phoff);
91 	printf("e_shoff %x\n", pehdr->e_shoff);
92 	printf("e_flags %x\n", pehdr->e_flags);
93 	printf("e_ehsize %x\n", pehdr->e_ehsize);
94 	printf("e_phentsize %x\n", pehdr->e_phentsize);
95 	printf("e_phnum %x\n", pehdr->e_phnum);
96 	printf("e_shentsize %x\n", pehdr->e_shentsize);
97 	printf("e_shnum %x\n", pehdr->e_shnum);
98 	printf("e_shstrndx %x\n", pehdr->e_shstrndx);
99 #endif
100 
101 	load_shstr_tab(pehdr, pexe);
102 #ifdef DEBUG
103 	for (i = 0; i < pehdr->e_shnum; i++) {
104 		pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
105 		    (i * pehdr->e_shentsize));
106 
107 		printf("section header %d\n", i);
108 		printf("sh_name %x ", pshdr->sh_name);
109 		fprint_shstr(stdout, pshdr->sh_name);
110 		printf("\n");
111 		printf("sh_type %x\n", pshdr->sh_type);
112 		printf("sh_flags %x\n", pshdr->sh_flags);
113 		printf("sh_addr %x\n", pshdr->sh_addr);
114 		printf("sh_offset %x\n", pshdr->sh_offset);
115 		printf("sh_size %x\n", pshdr->sh_size);
116 		printf("sh_link %x\n", pshdr->sh_link);
117 		printf("sh_info %x\n", pshdr->sh_info);
118 		printf("sh_addralign %x\n", pshdr->sh_addralign);
119 		printf("sh_entsize %x\n", pshdr->sh_entsize);
120 	}
121 #endif				/* DEBUG */
122 
123 #ifdef DEBUG
124 	for (i = 0; i < pehdr->e_phnum; i++) {
125 		pshdr = (Elf_Phdr *) (pexe + pehdr->e_phoff +
126 		    (i * pehdr->e_phentsize));
127 
128 		printf("program header %d\n", i);
129 		printf("p_type %x\n", pphdr->p_type);
130 		printf("p_offset %x\n", pphdr->p_offset);
131 		printf("p_vaddr %x\n", pphdr->p_vaddr);
132 		printf("p_paddr %x\n", pphdr->p_paddr);
133 		printf("p_filesz %x\n", pphdr->p_filesz);
134 		printf("p_memsz %x\n", pphdr->p_memsz);
135 		printf("p_flags %x\n", pphdr->p_flags);
136 		printf("p_align %x\n", pphdr->p_align);
137 	}
138 #endif				/* DEBUG */
139 #if 0
140 	for (i = 0; i < pehdr->e_shnum; i++) {
141 		pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
142 		    (i * pehdr->e_shentsize));
143 		if (strcmp(".strtab", get_shstr(pshdr->sh_name)) == 0)
144 			break;
145 	}
146 	fprint_shstr(stdout, pshdr->sh_name);
147 	printf("\n");
148 #endif
149 
150 	load_strtab(pehdr, pexe);
151 	load_symtab(pehdr, pexe);
152 	close(pfile);
153 }
154 char           *shstrtab;
155 
156 void
157 load_shstr_tab(Elf_Ehdr * pehdr, char *pexe)
158 {
159 	Elf_Shdr       *pshdr;
160 	shstrtab = NULL;
161 	if (pehdr->e_shstrndx == 0)
162 		return;
163 	pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
164 	    (pehdr->e_shstrndx * pehdr->e_shentsize));
165 
166 	shstrtab = (char *) (pexe + pshdr->sh_offset);
167 }
168 
169 void
170 fprint_shstr(FILE * channel, int indx)
171 {
172 	if (shstrtab != NULL)
173 		fprintf(channel, "\"%s\"", &(shstrtab[indx]));
174 }
175 
176 char           *
177 get_shstr(int indx)
178 {
179 	return &(shstrtab[indx]);
180 }
181 
182 void
183 load_symtab(Elf_Ehdr * pehdr, char *pexe)
184 {
185 	Elf_Sym        *symtab;
186 	Elf_Shdr       *symsect;
187 	int             symtabsize;
188 	Elf_Shdr       *psymshdr;
189 	Elf_Shdr       *pshdr;
190 #ifdef DEBUG
191 	char           *shname;
192 #endif
193 	int             i;
194 
195 	symtab = NULL;
196 	for (i = 0; i < pehdr->e_shnum; i++) {
197 		pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
198 		    (i * pehdr->e_shentsize));
199 		if (SHT_REL != pshdr->sh_type && SHT_RELA != pshdr->sh_type)
200 			continue;
201 		psymshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
202 		    (pshdr->sh_link * pehdr->e_shentsize));
203 #ifdef DEBUG
204 		fprint_shstr(stdout, pshdr->sh_name);
205 		printf("\n");
206 #endif
207 		symtab = (Elf_Sym *) (pexe + psymshdr->sh_offset);
208 		symsect = psymshdr;
209 		symtabsize = psymshdr->sh_size;
210 
211 #ifdef DEBUG
212 		dump_symtab(symsect, symtab, symtabsize);
213 #endif
214 		hide_sym(pehdr, symsect, symtab, symtabsize, pshdr->sh_link);
215 	}
216 
217 }
218 
219 void
220 dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize)
221 {
222 	int             i;
223 	Elf_Sym        *psymtab;
224 
225 	for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
226 		psymtab = &(symtab[i]);
227 		if ((psymtab->st_info & 0xf0) == 0x10 &&
228 		    (psymtab->st_shndx != SHN_UNDEF)) {
229 			printf("symbol %d:\n", i);
230 			printf("st_name %x \"%s\"\n", psymtab->st_name,
231 			    get_str(psymtab->st_name));
232 			printf("st_value %llx\n", (unsigned long long)psymtab->st_value);
233 			printf("st_size %llx\n", (unsigned long long)psymtab->st_size);
234 			printf("st_info %x\n", psymtab->st_info);
235 			printf("st_other %x\n", psymtab->st_other);
236 			printf("st_shndx %x\n", psymtab->st_shndx);
237 		}
238 	}
239 }
240 
241 char           *strtab;
242 int             strtabsize;
243 void
244 load_strtab(Elf_Ehdr * pehdr, char *pexe)
245 {
246 	Elf_Shdr       *pshdr = NULL;
247 	char           *shname;
248 	int             i;
249 	strtab = NULL;
250 	for (i = 0; i < pehdr->e_shnum; i++) {
251 		pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
252 		    (i * pehdr->e_shentsize));
253 
254 		shname = get_shstr(pshdr->sh_name);
255 		if (strcmp(".strtab", shname) == 0)
256 			break;
257 	}
258 #ifdef DEBUG
259 	fprint_shstr(stdout, pshdr->sh_name);
260 	printf("\n");
261 #endif
262 
263 	strtab = (char *) (pexe + pshdr->sh_offset);
264 
265 	strtabsize = pshdr->sh_size;
266 
267 #ifdef DEBUG
268 	dump_strtab();
269 #endif
270 }
271 
272 void
273 dump_strtab()
274 {
275 	int             index;
276 	char           *pstr;
277 	char           *pnstr;
278 	int             i = 0;
279 	index = 0;
280 	pstr = strtab;
281 	while (index < strtabsize) {
282 		printf("string %x: \"%s\"\n", i, pstr);
283 		pnstr = pstr + strlen(pstr) + 1;
284 		index = pnstr - strtab;
285 		pstr = pnstr;
286 		i++;
287 	}
288 
289 }
290 
291 void
292 fprint_str(FILE * channel, int indx)
293 {
294 	if (strtab != NULL)
295 		fprintf(channel, "\"%s\"", &(strtab[indx]));
296 }
297 
298 char *
299 get_str(int indx)
300 {
301 	return &(strtab[indx]);
302 }
303 
304 int             in_keep_list(char *symbol);
305 
306 void
307 hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
308     Elf_Sym * symtab, int symtabsize, int symtabsecnum)
309 {
310 	int             i;
311 	unsigned char   info;
312 	Elf_Sym        *psymtab;
313 
314 	for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
315 		psymtab = &(symtab[i]);
316 		if ((psymtab->st_info & 0xf0) == 0x10 &&
317 		    (psymtab->st_shndx != SHN_UNDEF)) {
318 			if (in_keep_list(get_str(psymtab->st_name)))
319 				continue;
320 #ifdef DEBUG
321 			printf("symbol %d:\n", i);
322 			printf("st_name %x \"%s\"\n", psymtab->st_name,
323 			    get_str(psymtab->st_name));
324 			printf("st_info %x\n", psymtab->st_info);
325 #endif
326 			if (!elf_mangle) {
327 				info = psymtab->st_info;
328 				info = info & 0xf;
329 				psymtab->st_info = info;
330 			} else {
331 				mangle_str(get_str(psymtab->st_name));
332 			}
333 #ifdef DEBUG
334 			printf("st_info %x\n", psymtab->st_info);
335 #endif
336 		}
337 	}
338 	reorder_syms(ehdr, symsect, symtab, symtabsize, symtabsecnum);
339 }
340 
341 void
342 reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
343     Elf_Sym * symtab, int symtabsize, int symtabsecnum)
344 {
345 	int             i;
346 	int             nsyms;
347 	int             cursym;
348 	Elf_Sym        *tmpsymtab;
349 	Symmap         *symmap;
350 
351 
352 	nsyms = symtabsize / sizeof(Elf_Sym);
353 
354 	tmpsymtab = (Elf_Sym *) calloc(1, symtabsize);
355 	symmap = (Symmap *) calloc(nsyms, sizeof(Symmap));
356 	if (!tmpsymtab || !symmap)
357 		errc(5, ENOMEM, "calloc");
358 
359 	bcopy(symtab, tmpsymtab, symtabsize);
360 
361 	cursym = 1;
362 	for (i = 1; i < nsyms; i++) {
363 		if ((tmpsymtab[i].st_info & 0xf0) == 0x00) {
364 #ifdef DEBUG
365 			printf("copying  l o%d n%d <%s>\n", i, cursym,
366 			    get_str(tmpsymtab[i].st_name));
367 #endif
368 			bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
369 			    sizeof(Elf_Sym));
370 			symmap[i] = cursym;
371 			cursym++;
372 		}
373 	}
374 	symsect->sh_info = cursym;
375 	for (i = 1; i < nsyms; i++) {
376 		if ((tmpsymtab[i].st_info & 0xf0) != 0x00) {
377 #ifdef DEBUG
378 			printf("copying nl o%d n%d <%s>\n", i, cursym,
379 			    get_str(tmpsymtab[i].st_name));
380 #endif
381 			bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
382 			    sizeof(Elf_Sym));
383 			symmap[i] = cursym;
384 			cursym++;
385 		}
386 	}
387 	if (cursym != nsyms) {
388 		printf("miscounted symbols somewhere c %d n %d \n",
389 		    cursym, nsyms);
390 		exit(5);
391 	}
392 	renum_reloc_syms(ehdr, symmap, symtabsecnum);
393 	free(tmpsymtab);
394 	free(symmap);
395 }
396 
397 void
398 renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap, int symtabsecnum)
399 {
400 	Elf_Shdr       *pshdr;
401 	int             i, j;
402 	int             num_reloc;
403 	Elf_Rel        *prel;
404 	Elf_RelA       *prela;
405 	int             symnum;
406 
407 	for (i = 0; i < ehdr->e_shnum; i++) {
408 		pshdr = (Elf_Shdr *) (pexe + ehdr->e_shoff +
409 		    (i * ehdr->e_shentsize));
410 		if ((pshdr->sh_type == SHT_RELA) &&
411 		    pshdr->sh_link == symtabsecnum) {
412 
413 #ifdef DEBUG
414 			printf("section %d has rela relocations in symtab\n", i);
415 #endif
416 			prela = (Elf_RelA *) (pexe + pshdr->sh_offset);
417 			num_reloc = pshdr->sh_size / sizeof(Elf_RelA);
418 			for (j = 0; j < num_reloc; j++) {
419 				symnum = ELF_R_SYM(prela[j].r_info);
420 #ifdef DEBUG
421 				printf("sym num o %d n %d\n", symnum,
422 				    symmap[symnum]);
423 #endif
424 				prela[j].r_info = ELF_R_INFO(symmap[symnum],
425 				    ELF_R_TYPE(prela[j].r_info));
426 			}
427 		}
428 		if ((pshdr->sh_type == SHT_REL) &&
429 		    pshdr->sh_link == symtabsecnum) {
430 #ifdef DEBUG
431 			printf("section %d has rel relocations in symtab\n", i);
432 #endif
433 			prel = (Elf_Rel *) (pexe + pshdr->sh_offset);
434 			num_reloc = pshdr->sh_size / sizeof(Elf_Rel);
435 			for (j = 0; j < num_reloc; j++) {
436 				symnum = ELF_R_SYM(prel[j].r_info);
437 #ifdef DEBUG
438 				printf("sym num o %d n %d\n", symnum,
439 				    symmap[symnum]);
440 #endif
441 				prel[j].r_info = ELF_R_INFO(symmap[symnum],
442 				    ELF_R_TYPE(prel[j].r_info));
443 			}
444 		}
445 	}
446 
447 }
448 #endif				/* _NLIST_DO_ELF */
449