xref: /openbsd-src/usr.sbin/crunchgen/elf_hide.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /* $OpenBSD: elf_hide.c,v 1.6 2010/07/20 02:08:15 deraadt 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();
49 char	*get_str(int indx);
50 
51 void	load_symtab(Elf_Ehdr * pehdr, char *pexe);
52 void	dump_symtab();
53 
54 void	load_shstr_tab(Elf_Ehdr * pehdr, char *pexe);
55 char	*get_shstr(int indx);
56 void	fprint_shstr(FILE * channel, int indx);
57 
58 void	hide_sym();
59 void	reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
60 	    Elf_Sym * symtab, int symtabsize, int symtabsecnum);
61 typedef long    Symmap;
62 void	renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap,
63 	    int symtabsecnum);
64 
65 
66 char           *pexe;
67 
68 void
69 elf_hide(int pfile, char *p)
70 {
71 	Elf_Ehdr       *pehdr;
72 #ifdef DEBUG
73 	Elf_Shdr       *pshdr;
74 	Elf_Phdr       *pphdr;
75 	int             i;
76 #endif
77 
78 	pexe = p;
79 	pehdr = (Elf_Ehdr *) pexe;
80 
81 #ifdef DEBUG
82 	printf("elf header\n");
83 	printf("e_type %x\n", pehdr->e_type);
84 	printf("e_machine %x\n", pehdr->e_machine);
85 	printf("e_version %x\n", pehdr->e_version);
86 	printf("e_entry %x\n", pehdr->e_entry);
87 	printf("e_phoff %x\n", pehdr->e_phoff);
88 	printf("e_shoff %x\n", pehdr->e_shoff);
89 	printf("e_flags %x\n", pehdr->e_flags);
90 	printf("e_ehsize %x\n", pehdr->e_ehsize);
91 	printf("e_phentsize %x\n", pehdr->e_phentsize);
92 	printf("e_phnum %x\n", pehdr->e_phnum);
93 	printf("e_shentsize %x\n", pehdr->e_shentsize);
94 	printf("e_shnum %x\n", pehdr->e_shnum);
95 	printf("e_shstrndx %x\n", pehdr->e_shstrndx);
96 #endif
97 
98 	load_shstr_tab(pehdr, pexe);
99 #ifdef DEBUG
100 	for (i = 0; i < pehdr->e_shnum; i++) {
101 		pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
102 		    (i * pehdr->e_shentsize));
103 
104 		printf("section header %d\n", i);
105 		printf("sh_name %x ", pshdr->sh_name);
106 		fprint_shstr(stdout, pshdr->sh_name);
107 		printf("\n");
108 		printf("sh_type %x\n", pshdr->sh_type);
109 		printf("sh_flags %x\n", pshdr->sh_flags);
110 		printf("sh_addr %x\n", pshdr->sh_addr);
111 		printf("sh_offset %x\n", pshdr->sh_offset);
112 		printf("sh_size %x\n", pshdr->sh_size);
113 		printf("sh_link %x\n", pshdr->sh_link);
114 		printf("sh_info %x\n", pshdr->sh_info);
115 		printf("sh_addralign %x\n", pshdr->sh_addralign);
116 		printf("sh_entsize %x\n", pshdr->sh_entsize);
117 	}
118 #endif				/* DEBUG */
119 
120 #ifdef DEBUG
121 	for (i = 0; i < pehdr->e_phnum; i++) {
122 		pshdr = (Elf_Phdr *) (pexe + pehdr->e_phoff +
123 		    (i * pehdr->e_phentsize));
124 
125 		printf("program header %d\n", i);
126 		printf("p_type %x\n", pphdr->p_type);
127 		printf("p_offset %x\n", pphdr->p_offset);
128 		printf("p_vaddr %x\n", pphdr->p_vaddr);
129 		printf("p_paddr %x\n", pphdr->p_paddr);
130 		printf("p_filesz %x\n", pphdr->p_filesz);
131 		printf("p_memsz %x\n", pphdr->p_memsz);
132 		printf("p_flags %x\n", pphdr->p_flags);
133 		printf("p_align %x\n", pphdr->p_align);
134 	}
135 #endif				/* DEBUG */
136 #if 0
137 	for (i = 0; i < pehdr->e_shnum; i++) {
138 		pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
139 		    (i * pehdr->e_shentsize));
140 		if (strcmp(".strtab", get_shstr(pshdr->sh_name)) == 0)
141 			break;
142 	}
143 	fprint_shstr(stdout, pshdr->sh_name);
144 	printf("\n");
145 #endif
146 
147 	load_strtab(pehdr, pexe);
148 	load_symtab(pehdr, pexe);
149 	close(pfile);
150 }
151 char           *shstrtab;
152 
153 void
154 load_shstr_tab(Elf_Ehdr * pehdr, char *pexe)
155 {
156 	Elf_Shdr       *pshdr;
157 	shstrtab = NULL;
158 	if (pehdr->e_shstrndx == 0)
159 		return;
160 	pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
161 	    (pehdr->e_shstrndx * pehdr->e_shentsize));
162 
163 	shstrtab = (char *) (pexe + pshdr->sh_offset);
164 }
165 
166 void
167 fprint_shstr(FILE * channel, int indx)
168 {
169 	if (shstrtab != NULL)
170 		fprintf(channel, "\"%s\"", &(shstrtab[indx]));
171 }
172 
173 char           *
174 get_shstr(int indx)
175 {
176 	return &(shstrtab[indx]);
177 }
178 
179 void
180 load_symtab(Elf_Ehdr * pehdr, char *pexe)
181 {
182 	Elf_Sym        *symtab;
183 	Elf_Shdr       *symsect;
184 	int             symtabsize;
185 	Elf_Shdr       *psymshdr;
186 	Elf_Shdr       *pshdr;
187 #ifdef DEBUG
188 	char           *shname;
189 #endif
190 	int             i;
191 
192 	symtab = NULL;
193 	for (i = 0; i < pehdr->e_shnum; i++) {
194 		pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
195 		    (i * pehdr->e_shentsize));
196 		if (SHT_REL != pshdr->sh_type && SHT_RELA != pshdr->sh_type)
197 			continue;
198 		psymshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
199 		    (pshdr->sh_link * pehdr->e_shentsize));
200 #ifdef DEBUG
201 		fprint_shstr(stdout, pshdr->sh_name);
202 		printf("\n");
203 #endif
204 		symtab = (Elf_Sym *) (pexe + psymshdr->sh_offset);
205 		symsect = psymshdr;
206 		symtabsize = psymshdr->sh_size;
207 
208 #ifdef DEBUG
209 		dump_symtab(symsect, symtab, symtabsize);
210 #endif
211 		hide_sym(pehdr, symsect, symtab, symtabsize, pshdr->sh_link);
212 	}
213 
214 }
215 
216 void
217 dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize)
218 {
219 	int             i;
220 	Elf_Sym        *psymtab;
221 
222 	for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
223 		psymtab = &(symtab[i]);
224 		if ((psymtab->st_info & 0xf0) == 0x10 &&
225 		    (psymtab->st_shndx != SHN_UNDEF)) {
226 			printf("symbol %d:\n", i);
227 			printf("st_name %x \"%s\"\n", psymtab->st_name,
228 			    get_str(psymtab->st_name));
229 			printf("st_value %llx\n", (unsigned long long)psymtab->st_value);
230 			printf("st_size %llx\n", (unsigned long long)psymtab->st_size);
231 			printf("st_info %x\n", psymtab->st_info);
232 			printf("st_other %x\n", psymtab->st_other);
233 			printf("st_shndx %x\n", psymtab->st_shndx);
234 		}
235 	}
236 }
237 
238 char           *strtab;
239 int             strtabsize;
240 void
241 load_strtab(Elf_Ehdr * pehdr, char *pexe)
242 {
243 	Elf_Shdr       *pshdr = NULL;
244 	char           *shname;
245 	int             i;
246 	strtab = NULL;
247 	for (i = 0; i < pehdr->e_shnum; i++) {
248 		pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
249 		    (i * pehdr->e_shentsize));
250 
251 		shname = get_shstr(pshdr->sh_name);
252 		if (strcmp(".strtab", shname) == 0)
253 			break;
254 	}
255 #ifdef DEBUG
256 	fprint_shstr(stdout, pshdr->sh_name);
257 	printf("\n");
258 #endif
259 
260 	strtab = (char *) (pexe + pshdr->sh_offset);
261 
262 	strtabsize = pshdr->sh_size;
263 
264 #ifdef DEBUG
265 	dump_strtab();
266 #endif
267 }
268 
269 void
270 dump_strtab()
271 {
272 	int             index;
273 	char           *pstr;
274 	char           *pnstr;
275 	int             i = 0;
276 	index = 0;
277 	pstr = strtab;
278 	while (index < strtabsize) {
279 		printf("string %x: \"%s\"\n", i, pstr);
280 		pnstr = pstr + strlen(pstr) + 1;
281 		index = pnstr - strtab;
282 		pstr = pnstr;
283 		i++;
284 	}
285 
286 }
287 
288 void
289 fprint_str(FILE * channel, int indx)
290 {
291 	if (strtab != NULL)
292 		fprintf(channel, "\"%s\"", &(strtab[indx]));
293 }
294 
295 char *
296 get_str(int indx)
297 {
298 	return &(strtab[indx]);
299 }
300 
301 int             in_keep_list(char *symbol);
302 
303 void
304 hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
305     Elf_Sym * symtab, int symtabsize, int symtabsecnum)
306 {
307 	int             i;
308 	unsigned char   info;
309 	Elf_Sym        *psymtab;
310 
311 	for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
312 		psymtab = &(symtab[i]);
313 		if ((psymtab->st_info & 0xf0) == 0x10 &&
314 		    (psymtab->st_shndx != SHN_UNDEF)) {
315 			if (in_keep_list(get_str(psymtab->st_name)))
316 				continue;
317 #ifdef DEBUG
318 			printf("symbol %d:\n", i);
319 			printf("st_name %x \"%s\"\n", psymtab->st_name,
320 			    get_str(psymtab->st_name));
321 			printf("st_info %x\n", psymtab->st_info);
322 #endif
323 			if (!elf_mangle) {
324 				info = psymtab->st_info;
325 				info = info & 0xf;
326 				psymtab->st_info = info;
327 			} else {
328 				mangle_str(get_str(psymtab->st_name));
329 			}
330 #ifdef DEBUG
331 			printf("st_info %x\n", psymtab->st_info);
332 #endif
333 		}
334 	}
335 	reorder_syms(ehdr, symsect, symtab, symtabsize, symtabsecnum);
336 }
337 
338 void
339 reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
340     Elf_Sym * symtab, int symtabsize, int symtabsecnum)
341 {
342 	int             i;
343 	int             nsyms;
344 	int             cursym;
345 	Elf_Sym        *tmpsymtab;
346 	Symmap         *symmap;
347 
348 
349 	nsyms = symtabsize / sizeof(Elf_Sym);
350 
351 	tmpsymtab = (Elf_Sym *) calloc(1, symtabsize);
352 	symmap = (Symmap *) calloc(nsyms, sizeof(Symmap));
353 	if (!tmpsymtab || !symmap)
354 		errx(5, "calloc: %s", strerror(ENOMEM));
355 
356 	bcopy(symtab, tmpsymtab, symtabsize);
357 
358 	cursym = 1;
359 	for (i = 1; i < nsyms; i++) {
360 		if ((tmpsymtab[i].st_info & 0xf0) == 0x00) {
361 #ifdef DEBUG
362 			printf("copying  l o%d n%d <%s>\n", i, cursym,
363 			    get_str(tmpsymtab[i].st_name));
364 #endif
365 			bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
366 			    sizeof(Elf_Sym));
367 			symmap[i] = cursym;
368 			cursym++;
369 		}
370 	}
371 	symsect->sh_info = cursym;
372 	for (i = 1; i < nsyms; i++) {
373 		if ((tmpsymtab[i].st_info & 0xf0) != 0x00) {
374 #ifdef DEBUG
375 			printf("copying nl o%d n%d <%s>\n", i, cursym,
376 			    get_str(tmpsymtab[i].st_name));
377 #endif
378 			bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
379 			    sizeof(Elf_Sym));
380 			symmap[i] = cursym;
381 			cursym++;
382 		}
383 	}
384 	if (cursym != nsyms) {
385 		printf("miscounted symbols somewhere c %d n %d \n",
386 		    cursym, nsyms);
387 		exit(5);
388 	}
389 	renum_reloc_syms(ehdr, symmap, symtabsecnum);
390 	free(tmpsymtab);
391 	free(symmap);
392 }
393 
394 void
395 renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap, int symtabsecnum)
396 {
397 	Elf_Shdr       *pshdr;
398 	int             i, j;
399 	int             num_reloc;
400 	Elf_Rel        *prel;
401 	Elf_RelA       *prela;
402 	int             symnum;
403 
404 	for (i = 0; i < ehdr->e_shnum; i++) {
405 		pshdr = (Elf_Shdr *) (pexe + ehdr->e_shoff +
406 		    (i * ehdr->e_shentsize));
407 		if ((pshdr->sh_type == SHT_RELA) &&
408 		    pshdr->sh_link == symtabsecnum) {
409 
410 #ifdef DEBUG
411 			printf("section %d has rela relocations in symtab\n", i);
412 #endif
413 			prela = (Elf_RelA *) (pexe + pshdr->sh_offset);
414 			num_reloc = pshdr->sh_size / sizeof(Elf_RelA);
415 			for (j = 0; j < num_reloc; j++) {
416 				symnum = ELF_R_SYM(prela[j].r_info);
417 #ifdef DEBUG
418 				printf("sym num o %d n %d\n", symnum,
419 				    symmap[symnum]);
420 #endif
421 				prela[j].r_info = ELF_R_INFO(symmap[symnum],
422 				    ELF_R_TYPE(prela[j].r_info));
423 			}
424 		}
425 		if ((pshdr->sh_type == SHT_REL) &&
426 		    pshdr->sh_link == symtabsecnum) {
427 #ifdef DEBUG
428 			printf("section %d has rel relocations in symtab\n", i);
429 #endif
430 			prel = (Elf_Rel *) (pexe + pshdr->sh_offset);
431 			num_reloc = pshdr->sh_size / sizeof(Elf_Rel);
432 			for (j = 0; j < num_reloc; j++) {
433 				symnum = ELF_R_SYM(prel[j].r_info);
434 #ifdef DEBUG
435 				printf("sym num o %d n %d\n", symnum,
436 				    symmap[symnum]);
437 #endif
438 				prel[j].r_info = ELF_R_INFO(symmap[symnum],
439 				    ELF_R_TYPE(prel[j].r_info));
440 			}
441 		}
442 	}
443 
444 }
445 #endif				/* _NLIST_DO_ELF */
446