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