1 /*
2  * Copyright 2003-2012 Gentoo Foundation
3  * Distributed under the terms of the GNU General Public License v2
4  *
5  * Copyright 2005-2012 Ned Ludd        - <solar@gentoo.org>
6  * Copyright 2005-2012 Mike Frysinger  - <vapier@gentoo.org>
7  */
8 
9 #include "paxinc.h"
10 
11 /*
12  * Setup a bunch of helper functions to translate
13  * binary defines into readable strings.
14  */
15 #define QUERY(n) { #n, n }
16 typedef const struct {
17 	const char *str;
18 	/* We use unsigned int as we assume it's at least 32 bits.  This covers
19 	   all our uses so far as they have been limited to that size.  */
20 	unsigned int value;
21 } pairtype;
find_pairtype(pairtype * pt,unsigned int type)22 static inline const char *find_pairtype(pairtype *pt, unsigned int type)
23 {
24 	size_t i;
25 	for (i = 0; pt[i].str; ++i)
26 		if (type == pt[i].value)
27 			return pt[i].str;
28 	return "UNKNOWN_TYPE";
29 }
30 
31 /* translate misc elf EI_ defines */
32 static pairtype elf_ei_class[] = {
33 	QUERY(ELFCLASSNONE),
34 	QUERY(ELFCLASS32),
35 	QUERY(ELFCLASS64),
36 	{ 0, 0 }
37 };
38 static pairtype elf_ei_data[] = {
39 	QUERY(ELFDATANONE),
40 	QUERY(ELFDATA2LSB),
41 	QUERY(ELFDATA2MSB),
42 	{ 0, 0 }
43 };
44 static pairtype elf_ei_version[] = {
45 	QUERY(EV_NONE),
46 	QUERY(EV_CURRENT),
47 	{ 0, 0 }
48 };
49 static pairtype elf_ei_osabi[] = {
50 	QUERY(ELFOSABI_NONE),
51 	QUERY(ELFOSABI_SYSV),
52 	QUERY(ELFOSABI_HPUX),
53 	QUERY(ELFOSABI_NETBSD),
54 	QUERY(ELFOSABI_GNU),
55 	QUERY(ELFOSABI_LINUX),
56 	QUERY(ELFOSABI_SOLARIS),
57 	QUERY(ELFOSABI_AIX),
58 	QUERY(ELFOSABI_IRIX),
59 	QUERY(ELFOSABI_FREEBSD),
60 	QUERY(ELFOSABI_TRU64),
61 	QUERY(ELFOSABI_MODESTO),
62 	QUERY(ELFOSABI_OPENBSD),
63 	QUERY(ELFOSABI_ARM_AEABI),
64 	QUERY(ELFOSABI_ARM),
65 	QUERY(ELFOSABI_STANDALONE),
66 	{ 0, 0 }
67 };
get_elfeitype(int ei_type,int type)68 const char *get_elfeitype(int ei_type, int type)
69 {
70 	switch (ei_type) {
71 		case EI_CLASS:   return find_pairtype(elf_ei_class, type);
72 		case EI_DATA:    return find_pairtype(elf_ei_data, type);
73 		case EI_VERSION: return find_pairtype(elf_ei_version, type);
74 		case EI_OSABI:   return find_pairtype(elf_ei_osabi, type);
75 	}
76 	return "UNKNOWN_EI_TYPE";
77 }
78 
79 /* translate elf ET_ defines */
80 static pairtype elf_etypes[] = {
81 	QUERY(ET_NONE),
82 	QUERY(ET_REL),
83 	QUERY(ET_EXEC),
84 	QUERY(ET_DYN),
85 	QUERY(ET_CORE),
86 	{ 0, 0 }
87 };
88 
get_etype(const elfobj * elf)89 unsigned int get_etype(const elfobj *elf)
90 {
91 	if (elf->elf_class == ELFCLASS32)
92 		return EGET(EHDR32(elf->ehdr)->e_type);
93 	else
94 		return EGET(EHDR64(elf->ehdr)->e_type);
95 }
96 
get_elfetype(const elfobj * elf)97 const char *get_elfetype(const elfobj *elf)
98 {
99 	return find_pairtype(elf_etypes, get_etype(elf));
100 }
101 
get_endian(const elfobj * elf)102 const char *get_endian(const elfobj *elf)
103 {
104 	switch (elf->data[EI_DATA]) {
105 		case ELFDATA2LSB: return "LE";
106 		case ELFDATA2MSB: return "BE";
107 		default:          return "??";
108 	}
109 }
110 
111 /* translate elf EF_ defines -- tricky as it's based on EM_ */
get_eflags(const elfobj * elf)112 static unsigned int get_eflags(const elfobj *elf)
113 {
114 	if (elf->elf_class == ELFCLASS32)
115 		return EGET(EHDR32(elf->ehdr)->e_flags);
116 	else
117 		return EGET(EHDR64(elf->ehdr)->e_flags);
118 }
119 
arm_eabi_poker(const elfobj * elf)120 static int arm_eabi_poker(const elfobj *elf)
121 {
122 	unsigned int emachine, eflags;
123 
124 	if (ELFOSABI_NONE != elf->data[EI_OSABI])
125 		return -1;
126 
127 	emachine = get_emtype(elf);
128 	eflags = get_eflags(elf);
129 
130 	if (emachine == EM_ARM)
131 		return EF_ARM_EABI_VERSION(eflags) >> 24;
132 	else
133 		return -1;
134 }
135 
get_elf_eabi(const elfobj * elf)136 const char *get_elf_eabi(const elfobj *elf)
137 {
138 	static char buf[26];
139 	int eabi = arm_eabi_poker(elf);
140 	if (eabi >= 0)
141 		snprintf(buf, sizeof(buf), "%i", eabi);
142 	else
143 		strcpy(buf, "?");
144 	return buf;
145 }
146 
get_elfosabi(const elfobj * elf)147 const char *get_elfosabi(const elfobj *elf)
148 {
149 	const char *str = get_elfeitype(EI_OSABI, elf->data[EI_OSABI]);
150 	if (strncmp(str, "ELFOSABI_", 9) == 0)
151 		str += 9;
152 	return str;
153 }
154 
print_etypes(FILE * stream)155 void print_etypes(FILE *stream)
156 {
157 	int i, wrap = 0;
158 	for (i = 0; elf_etypes[i].str; ++i) {
159 		fprintf(stream, " (%4x) = %-10s", elf_etypes[i].value, elf_etypes[i].str);
160 		if (++wrap >= 4) {
161 			fprintf(stream, "\n");
162 			wrap = 0;
163 		}
164 	}
165 	if (wrap)
166 		fprintf(stream, "\n");
167 }
168 
etype_lookup(const char * str)169 unsigned int etype_lookup(const char *str)
170 {
171 	if (*str == 'E') {
172 		size_t i;
173 		for (i = 0; elf_etypes[i].str; ++i) {
174 			if (strcmp(str, elf_etypes[i].str) == 0)
175 				return elf_etypes[i].value;
176 		}
177 	}
178 	return atoi(str);
179 }
180 
181 /* translate elf EM_ defines */
182 static pairtype elf_emtypes[] = {
183 	QUERY(EM_NONE),
184 	QUERY(EM_M32),
185 	QUERY(EM_SPARC),
186 	QUERY(EM_386),
187 	QUERY(EM_68K),
188 	QUERY(EM_88K),
189 	QUERY(EM_860),
190 	QUERY(EM_MIPS),
191 	QUERY(EM_S370),
192 	QUERY(EM_MIPS_RS3_LE),
193 	QUERY(EM_PARISC),
194 	QUERY(EM_VPP500),
195 	QUERY(EM_SPARC32PLUS),
196 	QUERY(EM_960),
197 	QUERY(EM_PPC),
198 	QUERY(EM_PPC64),
199 	QUERY(EM_S390),
200 	QUERY(EM_V800),
201 	QUERY(EM_FR20),
202 	QUERY(EM_RH32),
203 	QUERY(EM_RCE),
204 	QUERY(EM_ARM),
205 	QUERY(EM_FAKE_ALPHA),
206 	QUERY(EM_SH),
207 	QUERY(EM_SPARCV9),
208 	QUERY(EM_TRICORE),
209 	QUERY(EM_ARC),
210 	QUERY(EM_H8_300),
211 	QUERY(EM_H8_300H),
212 	QUERY(EM_H8S),
213 	QUERY(EM_H8_500),
214 	QUERY(EM_IA_64),
215 	QUERY(EM_MIPS_X),
216 	QUERY(EM_COLDFIRE),
217 	QUERY(EM_68HC12),
218 	QUERY(EM_MMA),
219 	QUERY(EM_PCP),
220 	QUERY(EM_NCPU),
221 	QUERY(EM_NDR1),
222 	QUERY(EM_STARCORE),
223 	QUERY(EM_ME16),
224 	QUERY(EM_ST100),
225 	QUERY(EM_TINYJ),
226 	QUERY(EM_X86_64),
227 	QUERY(EM_PDSP),
228 	QUERY(EM_FX66),
229 	QUERY(EM_ST9PLUS),
230 	QUERY(EM_ST7),
231 	QUERY(EM_68HC16),
232 	QUERY(EM_68HC11),
233 	QUERY(EM_68HC08),
234 	QUERY(EM_68HC05),
235 	QUERY(EM_SVX),
236 	QUERY(EM_ST19),
237 	QUERY(EM_VAX),
238 	QUERY(EM_CRIS),
239 	QUERY(EM_JAVELIN),
240 	QUERY(EM_FIREPATH),
241 	QUERY(EM_ZSP),
242 	QUERY(EM_MMIX),
243 	QUERY(EM_HUANY),
244 	QUERY(EM_PRISM),
245 	QUERY(EM_AVR),
246 	QUERY(EM_FR30),
247 	QUERY(EM_D10V),
248 	QUERY(EM_D30V),
249 	QUERY(EM_V850),
250 	QUERY(EM_M32R),
251 	QUERY(EM_MN10300),
252 	QUERY(EM_MN10200),
253 	QUERY(EM_PJ),
254 	QUERY(EM_OPENRISC),
255 	QUERY(EM_ARC_A5),
256 	QUERY(EM_XTENSA),
257 	QUERY(EM_VIDEOCORE),
258 	QUERY(EM_TMM_GPP),
259 	QUERY(EM_NS32K),
260 	QUERY(EM_TPC),
261 	QUERY(EM_SNP1K),
262 	QUERY(EM_ST200),
263 	QUERY(EM_IP2K),
264 	QUERY(EM_MAX),
265 	QUERY(EM_CR),
266 	QUERY(EM_F2MC16),
267 	QUERY(EM_MSP430),
268 	QUERY(EM_BLACKFIN),
269 	QUERY(EM_SE_C33),
270 	QUERY(EM_SEP),
271 	QUERY(EM_ARCA),
272 	QUERY(EM_UNICORE),
273 	QUERY(EM_ALTERA_NIOS2),
274 	QUERY(EM_AARCH64),
275 	QUERY(EM_TILEPRO),
276 	QUERY(EM_MICROBLAZE),
277 	QUERY(EM_TILEGX),
278 	QUERY(EM_ALPHA),
279 	QUERY(EM_RISCV),
280 	{ 0, 0 }
281 };
282 
get_emtype(const elfobj * elf)283 unsigned int get_emtype(const elfobj *elf)
284 {
285 	if (elf->elf_class == ELFCLASS32)
286 		return EGET(EHDR32(elf->ehdr)->e_machine);
287 	else
288 		return EGET(EHDR64(elf->ehdr)->e_machine);
289 }
290 
get_elfemtype(const elfobj * elf)291 const char *get_elfemtype(const elfobj *elf)
292 {
293 	return find_pairtype(elf_emtypes, get_emtype(elf));
294 }
295 
296 /* translate elf PT_ defines */
297 static pairtype elf_ptypes[] = {
298 	QUERY(PT_NULL),
299 	QUERY(PT_LOAD),
300 	QUERY(PT_DYNAMIC),
301 	QUERY(PT_INTERP),
302 	QUERY(PT_NOTE),
303 	QUERY(PT_SHLIB),
304 	QUERY(PT_PHDR),
305 	QUERY(PT_TLS),
306 	QUERY(PT_GNU_EH_FRAME),
307 	QUERY(PT_GNU_STACK),
308 	QUERY(PT_GNU_RELRO),
309 	QUERY(PT_PAX_FLAGS),
310 	{ 0, 0 }
311 };
get_elfptype(int type)312 const char *get_elfptype(int type)
313 {
314 	return find_pairtype(elf_ptypes, type);
315 }
316 
317 /* translate elf PT_ defines */
318 static pairtype elf_dtypes[] = {
319 	QUERY(DT_NULL),
320 	QUERY(DT_NEEDED),
321 	QUERY(DT_PLTRELSZ),
322 	QUERY(DT_PLTGOT),
323 	QUERY(DT_HASH),
324 	QUERY(DT_STRTAB),
325 	QUERY(DT_SYMTAB),
326 	QUERY(DT_RELA),
327 	QUERY(DT_RELASZ),
328 	QUERY(DT_RELAENT),
329 	QUERY(DT_STRSZ),
330 	QUERY(DT_SYMENT),
331 	QUERY(DT_INIT),
332 	QUERY(DT_FINI),
333 	QUERY(DT_SONAME),
334 	QUERY(DT_RPATH),
335 	QUERY(DT_SYMBOLIC),
336 	QUERY(DT_REL),
337 	QUERY(DT_RELSZ),
338 	QUERY(DT_RELENT),
339 	QUERY(DT_PLTREL),
340 	QUERY(DT_DEBUG),
341 	QUERY(DT_TEXTREL),
342 	QUERY(DT_JMPREL),
343 	QUERY(DT_BIND_NOW),
344 	QUERY(DT_INIT_ARRAY),
345 	QUERY(DT_FINI_ARRAY),
346 	QUERY(DT_INIT_ARRAYSZ),
347 	QUERY(DT_FINI_ARRAYSZ),
348 	QUERY(DT_RUNPATH),
349 	QUERY(DT_FLAGS),
350 	QUERY(DT_ENCODING),
351 	QUERY(DT_PREINIT_ARRAY),
352 	QUERY(DT_PREINIT_ARRAYSZ),
353 	QUERY(DT_GNU_PRELINKED),
354 	QUERY(DT_GNU_CONFLICTSZ),
355 	QUERY(DT_GNU_LIBLISTSZ),
356 	QUERY(DT_CHECKSUM),
357 	QUERY(DT_PLTPADSZ),
358 	QUERY(DT_MOVEENT),
359 	QUERY(DT_MOVESZ),
360 	QUERY(DT_GNU_HASH),
361 	QUERY(DT_TLSDESC_PLT),
362 	QUERY(DT_TLSDESC_GOT),
363 	QUERY(DT_GNU_CONFLICT),
364 	QUERY(DT_GNU_LIBLIST),
365 	QUERY(DT_CONFIG),
366 	QUERY(DT_DEPAUDIT),
367 	QUERY(DT_AUDIT),
368 	QUERY(DT_PLTPAD),
369 	QUERY(DT_MOVETAB),
370 	QUERY(DT_SYMINFO),
371 	QUERY(DT_VERSYM),
372 	QUERY(DT_RELACOUNT),
373 	QUERY(DT_RELCOUNT),
374 	QUERY(DT_FLAGS_1),
375 	QUERY(DT_VERDEF),
376 	QUERY(DT_VERDEFNUM),
377 	QUERY(DT_VERNEED),
378 	QUERY(DT_VERNEEDNUM),
379 	QUERY(DT_AUXILIARY),
380 	QUERY(DT_FILTER),
381 	{ 0, 0 }
382 };
get_elfdtype(int type)383 const char *get_elfdtype(int type)
384 {
385 	return find_pairtype(elf_dtypes, type);
386 }
387 
388 /* translate elf SHT_ defines */
389 static pairtype elf_shttypes[] = {
390 	QUERY(SHT_NULL),
391 	QUERY(SHT_PROGBITS),
392 	QUERY(SHT_SYMTAB),
393 	QUERY(SHT_STRTAB),
394 	QUERY(SHT_RELA),
395 	QUERY(SHT_HASH),
396 	QUERY(SHT_DYNAMIC),
397 	QUERY(SHT_NOTE),
398 	QUERY(SHT_NOBITS),
399 	QUERY(SHT_REL),
400 	QUERY(SHT_SHLIB),
401 	QUERY(SHT_DYNSYM),
402 	QUERY(SHT_INIT_ARRAY),
403 	QUERY(SHT_FINI_ARRAY),
404 	QUERY(SHT_PREINIT_ARRAY),
405 	QUERY(SHT_GROUP),
406 	QUERY(SHT_SYMTAB_SHNDX),
407 	QUERY(SHT_GNU_ATTRIBUTES),
408 	QUERY(SHT_GNU_HASH),
409 	QUERY(SHT_GNU_LIBLIST),
410 	QUERY(SHT_CHECKSUM),
411 	QUERY(SHT_SUNW_move),
412 	QUERY(SHT_SUNW_COMDAT),
413 	QUERY(SHT_SUNW_syminfo),
414 	QUERY(SHT_GNU_verdef),
415 	QUERY(SHT_GNU_verneed),
416 	QUERY(SHT_GNU_versym),
417 	{ 0, 0 }
418 };
get_elfshttype(int type)419 const char *get_elfshttype(int type)
420 {
421 	return find_pairtype(elf_shttypes, type);
422 }
423 
424 /* translate elf STT_ defines */
425 static pairtype elf_stttypes[] = {
426 	QUERY(STT_NOTYPE),
427 	QUERY(STT_OBJECT),
428 	QUERY(STT_FUNC),
429 	QUERY(STT_SECTION),
430 	QUERY(STT_FILE),
431 	QUERY(STT_COMMON),
432 	QUERY(STT_TLS),
433 	QUERY(STT_GNU_IFUNC),
434 	{ 0, 0 }
435 };
get_elfstttype(int type)436 const char *get_elfstttype(int type)
437 {
438 	return find_pairtype(elf_stttypes, type);
439 }
440 
441 /* translate elf STB_ defines */
442 static pairtype elf_stbtypes[] = {
443 	QUERY(STB_LOCAL),
444 	QUERY(STB_GLOBAL),
445 	QUERY(STB_WEAK),
446 	QUERY(STB_GNU_UNIQUE),
447 	{ 0, 0 }
448 };
get_elfstbtype(int type)449 const char *get_elfstbtype(int type)
450 {
451 	return find_pairtype(elf_stbtypes, type);
452 }
453 
454 /* translate elf STV_ defines */
455 static pairtype elf_stvtypes[] = {
456 	QUERY(STV_DEFAULT),
457 	QUERY(STV_INTERNAL),
458 	QUERY(STV_HIDDEN),
459 	QUERY(STV_PROTECTED),
460 	{ 0, 0 }
461 };
get_elfstvtype(int type)462 const char *get_elfstvtype(int type)
463 {
464 	return find_pairtype(elf_stvtypes, type);
465 }
466 
467 /* translate elf SHN_ defines */
468 static pairtype elf_shntypes[] = {
469 	QUERY(SHN_UNDEF),
470 	QUERY(SHN_BEFORE),
471 	QUERY(SHN_AFTER),
472 	QUERY(SHN_ABS),
473 	QUERY(SHN_COMMON),
474 	QUERY(SHN_XINDEX),
475 	{ 0, 0 }
476 };
get_elfshntype(int type)477 const char *get_elfshntype(int type)
478 {
479 	if (type && type < SHN_LORESERVE)
480 		return "DEFINED";
481 	return find_pairtype(elf_shntypes, type);
482 }
483 
484 /* translate elf NT_ defines */
485 static pairtype elf_nttypes_GNU[] = {
486 	QUERY(NT_GNU_ABI_TAG),
487 	QUERY(NT_GNU_HWCAP),
488 	QUERY(NT_GNU_BUILD_ID),
489 	QUERY(NT_GNU_GOLD_VERSION),
490 	{ 0, 0 }
491 };
492 static pairtype elf_nttypes_core[] = {
493 	QUERY(NT_PRSTATUS),
494 	QUERY(NT_FPREGSET),
495 	QUERY(NT_PRPSINFO),
496 	QUERY(NT_PRXREG),
497 	QUERY(NT_TASKSTRUCT),
498 	QUERY(NT_PLATFORM),
499 	QUERY(NT_AUXV),
500 	QUERY(NT_GWINDOWS),
501 	QUERY(NT_ASRS),
502 	QUERY(NT_PSTATUS),
503 	QUERY(NT_PSINFO),
504 	QUERY(NT_PRCRED),
505 	QUERY(NT_UTSNAME),
506 	QUERY(NT_LWPSTATUS),
507 	QUERY(NT_LWPSINFO),
508 	QUERY(NT_PRFPXREG),
509 	QUERY(NT_SIGINFO),
510 	QUERY(NT_FILE),
511 	QUERY(NT_PRXFPREG),
512 	QUERY(NT_PPC_VMX),
513 	QUERY(NT_PPC_SPE),
514 	QUERY(NT_PPC_VSX),
515 	QUERY(NT_386_TLS),
516 	QUERY(NT_386_IOPERM),
517 	QUERY(NT_X86_XSTATE),
518 	QUERY(NT_S390_HIGH_GPRS),
519 	QUERY(NT_S390_TIMER),
520 	QUERY(NT_S390_TODCMP),
521 	QUERY(NT_S390_TODPREG),
522 	QUERY(NT_S390_CTRS),
523 	QUERY(NT_S390_PREFIX),
524 	QUERY(NT_S390_LAST_BREAK),
525 	QUERY(NT_S390_SYSTEM_CALL),
526 	QUERY(NT_S390_TDB),
527 	QUERY(NT_ARM_VFP),
528 	QUERY(NT_ARM_TLS),
529 	QUERY(NT_ARM_HW_BREAK),
530 	QUERY(NT_ARM_HW_WATCH),
531 	{ 0, 0 }
532 };
533 static pairtype elf_nttypes_fallback[] = {
534 	QUERY(NT_VERSION),
535 	{ 0, 0 }
536 };
get_elfnttype(uint16_t e_type,const char * name,int type)537 const char *get_elfnttype(uint16_t e_type, const char *name, int type)
538 {
539 	if (name) {
540 		if (!strcmp(name, "GNU"))
541 			return find_pairtype(elf_nttypes_GNU, type);
542 
543 		/* Unknown extension, so just fallback to common ones. */
544 	}
545 
546 	if (e_type == ET_CORE)
547 		return find_pairtype(elf_nttypes_core, type);
548 	else
549 		return find_pairtype(elf_nttypes_fallback, type);
550 }
551 
552 /* Read an ELF into memory */
553 #define IS_ELF_BUFFER(buff) \
554 	(buff[EI_MAG0] == ELFMAG0 && \
555 	 buff[EI_MAG1] == ELFMAG1 && \
556 	 buff[EI_MAG2] == ELFMAG2 && \
557 	 buff[EI_MAG3] == ELFMAG3)
558 #define DO_WE_LIKE_ELF(buff) \
559 	((buff[EI_CLASS] == ELFCLASS32 || buff[EI_CLASS] == ELFCLASS64) && \
560 	 (buff[EI_DATA] == ELFDATA2LSB || buff[EI_DATA] == ELFDATA2MSB) && \
561 	 (buff[EI_VERSION] == EV_CURRENT))
readelf_buffer(const char * filename,const void * buffer,size_t buffer_len)562 elfobj *readelf_buffer(const char *filename, const void *buffer, size_t buffer_len)
563 {
564 	elfobj *elf;
565 
566 	/* make sure we have enough bytes to scan e_ident */
567 	if (buffer == NULL || buffer_len < EI_NIDENT)
568 		return NULL;
569 
570 	elf = xzalloc(sizeof(*elf));
571 
572 	elf->fd = -1;
573 	elf->len = buffer_len;
574 	elf->data = buffer;
575 	elf->data_end = buffer + buffer_len;
576 
577 	/* make sure we have an elf */
578 	if (!IS_ELF_BUFFER(elf->data)) {
579 free_elf_and_return:
580 		free(elf);
581 		return NULL;
582 	}
583 
584 	/* check class and stuff */
585 	if (!DO_WE_LIKE_ELF(elf->data)) {
586 		warn("we no likey %s: {%s,%s,%s,%s}",
587 		     filename,
588 		     get_elfeitype(EI_CLASS, elf->data[EI_CLASS]),
589 		     get_elfeitype(EI_DATA, elf->data[EI_DATA]),
590 		     get_elfeitype(EI_VERSION, elf->data[EI_VERSION]),
591 		     get_elfeitype(EI_OSABI, elf->data[EI_OSABI]));
592 		goto free_elf_and_return;
593 	}
594 
595 	elf->filename = filename;
596 	elf->base_filename = strrchr(filename, '/');
597 	if (elf->base_filename == NULL)
598 		elf->base_filename = elf->filename;
599 	else
600 		elf->base_filename = elf->base_filename + 1;
601 	elf->elf_class = elf->data[EI_CLASS];
602 	do_reverse_endian = (ELF_DATA != elf->data[EI_DATA]);
603 
604 	/* for arches that need alignment, we have to make sure the buffer
605 	 * is strictly aligned.  archive (.a) files only align to 2 bytes
606 	 * while the arch can easily require 8.  so dupe the buffer so
607 	 * that our local copy is always aligned (since we can't shift the
608 	 * file mapping back and forth a few bytes).
609 	 */
610 	if (!__PAX_UNALIGNED_OK && ((unsigned long)elf->vdata & 0x7)) {
611 		elf->_data = xmalloc(elf->len);
612 		memcpy(elf->_data, elf->data, elf->len);
613 		elf->data = elf->_data;
614 		elf->data_end = elf->_data + elf->len;
615 	}
616 
617 #define READELF_HEADER(B) \
618 	if (elf->elf_class == ELFCLASS ## B) { \
619 		char invalid; \
620 		const Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
621 		Elf ## B ## _Off size; \
622 		/* verify program header */ \
623 		invalid = 0; \
624 		if (EGET(ehdr->e_phnum) <= 0) \
625 			invalid = 1; /* this is not abnormal so dont warn */ \
626 		else if (EGET(ehdr->e_phentsize) != sizeof(Elf ## B ## _Phdr)) \
627 			invalid = 3; \
628 		else { \
629 			elf->phdr = elf->vdata + EGET(ehdr->e_phoff); \
630 			size = EGET(ehdr->e_phnum) * EGET(ehdr->e_phentsize); \
631 			if (elf->phdr < elf->ehdr || /* check overflow */ \
632 			    elf->phdr + size < elf->phdr || /* before start of mem */ \
633 			    elf->phdr + size > elf->ehdr + elf->len) /* before end of mem */ \
634 				invalid = 2; \
635 		} \
636 		if (invalid > 1) \
637 			warn("%s: Invalid program header info (%i)", filename, invalid); \
638 		if (invalid) \
639 			elf->phdr = NULL; \
640 		/* verify section header */ \
641 		invalid = 0; \
642 		if (EGET(ehdr->e_shnum) <= 0) \
643 			invalid = 1; /* this is not abnormal so dont warn */ \
644 		else if (EGET(ehdr->e_shentsize) != sizeof(Elf ## B ## _Shdr)) \
645 			invalid = 3; \
646 		else { \
647 			elf->shdr = elf->vdata + EGET(ehdr->e_shoff); \
648 			size = EGET(ehdr->e_shnum) * EGET(ehdr->e_shentsize); \
649 			if (elf->shdr < elf->ehdr || /* check overflow */ \
650 			    elf->shdr + size < elf->shdr || /* before start of mem */ \
651 			    elf->shdr + size > elf->ehdr + elf->len) /* before end of mem */ \
652 				invalid = 2; \
653 		} \
654 		if (invalid > 1) \
655 			warn("%s: Invalid section header info (%i)", filename, invalid); \
656 		if (invalid) \
657 			elf->shdr = NULL; \
658 	}
659 	READELF_HEADER(32)
660 	READELF_HEADER(64)
661 	/* { char *p; strncpy(elf->basename, (p = strrchr(filename, '/')) == NULL ? "?" : p+1 , sizeof(elf->basename)); } */
662 
663 	return elf;
664 }
_readelf_fd(const char * filename,int fd,size_t len,int read_only)665 elfobj *_readelf_fd(const char *filename, int fd, size_t len, int read_only)
666 {
667 	char *buffer;
668 	elfobj *ret;
669 
670 	if (len == 0) {
671 		struct stat st;
672 		if (fstat(fd, &st) == -1)
673 			return NULL;
674 		len = st.st_size;
675 		if (len == 0)
676 			return NULL;
677 	}
678 
679 	buffer = mmap(0, len, PROT_READ | (read_only ? 0 : PROT_WRITE), (read_only ? MAP_PRIVATE : MAP_SHARED), fd, 0);
680 	if (buffer == MAP_FAILED) {
681 		warn("mmap on '%s' of %li bytes failed :(", filename, (unsigned long)len);
682 		return NULL;
683 	}
684 
685 	ret = readelf_buffer(filename, buffer, len);
686 	if (ret == NULL)
687 		munmap(buffer, len);
688 	else {
689 		ret->fd = fd;
690 		ret->is_mmap = 1;
691 	}
692 
693 	return ret;
694 }
_readelf(const char * filename,int read_only)695 elfobj *_readelf(const char *filename, int read_only)
696 {
697 	elfobj *ret;
698 	struct stat st;
699 	int fd;
700 
701 	if ((fd = open(filename, (read_only ? O_RDONLY : O_RDWR))) == -1)
702 		return NULL;
703 
704 	if (fstat(fd, &st) == -1) {
705  close_fd_and_return:
706 		close(fd);
707 		return NULL;
708 	}
709 
710 	/* make sure we have enough bytes to scan e_ident */
711 	if (st.st_size <= EI_NIDENT)
712 		goto close_fd_and_return;
713 
714 	ret = readelf_fd(filename, fd, st.st_size);
715 	if (ret == NULL)
716 		goto close_fd_and_return;
717 
718 	return ret;
719 }
720 
721 /* undo the readelf() stuff */
unreadelf(elfobj * elf)722 void unreadelf(elfobj *elf)
723 {
724 	if (elf->is_mmap) munmap((void *)elf->vdata, elf->len);
725 	if (elf->fd != -1) close(elf->fd);
726 	if (!__PAX_UNALIGNED_OK) free(elf->_data);
727 	free(elf);
728 }
729 
pax_short_hf_flags(unsigned long flags)730 const char *pax_short_hf_flags(unsigned long flags)
731 {
732 	static char buffer[7];
733 
734 	buffer[0] = (flags & HF_PAX_PAGEEXEC ? 'p' : 'P');
735 	buffer[1] = (flags & HF_PAX_EMUTRAMP ? 'E' : 'e');
736 	buffer[2] = (flags & HF_PAX_MPROTECT ? 'm' : 'M');
737 	buffer[3] = (flags & HF_PAX_RANDMMAP ? 'r' : 'R');
738 	buffer[4] = (flags & HF_PAX_RANDEXEC ? 'X' : 'x');
739 	buffer[5] = (flags & HF_PAX_SEGMEXEC ? 's' : 'S');
740 	buffer[6] = 0;
741 
742 	return buffer;
743 }
744 
745 /* PT_PAX_FLAGS are tristate ...
746  * the display logic is:
747  * lower case: explicitly disabled
748  * upper case: explicitly enabled
749  *      -    : default */
pax_short_pf_flags(unsigned long flags)750 const char *pax_short_pf_flags(unsigned long flags)
751 {
752 	static char buffer[7];
753 
754 #define PAX_STATE(pf_on, pf_off, disp_on, disp_off) \
755 	(flags & pf_on ? disp_on : (flags & pf_off ? disp_off : '-'))
756 
757 	buffer[0] = PAX_STATE(PF_PAGEEXEC, PF_NOPAGEEXEC, 'P', 'p');
758 	buffer[1] = PAX_STATE(PF_SEGMEXEC, PF_NOSEGMEXEC, 'S', 's');
759 	buffer[2] = PAX_STATE(PF_MPROTECT, PF_NOMPROTECT, 'M', 'm');
760 	buffer[3] = PAX_STATE(PF_RANDEXEC, PF_NORANDEXEC, 'X', 'x');
761 	buffer[4] = PAX_STATE(PF_EMUTRAMP, PF_NOEMUTRAMP, 'E', 'e');
762 	buffer[5] = PAX_STATE(PF_RANDMMAP, PF_NORANDMMAP, 'R', 'r');
763 	buffer[6] = 0;
764 
765 	if (((flags & PF_PAGEEXEC) && (flags & PF_NOPAGEEXEC)) || \
766 	    ((flags & PF_SEGMEXEC) && (flags & PF_NOSEGMEXEC)) || \
767 	    ((flags & PF_RANDMMAP) && (flags & PF_NORANDMMAP)) || \
768 	    ((flags & PF_RANDEXEC) && (flags & PF_NORANDEXEC)) || \
769 	    ((flags & PF_EMUTRAMP) && (flags & PF_NOEMUTRAMP)) || \
770 	    ((flags & PF_RANDMMAP) && (flags & PF_NORANDMMAP)))
771 		warn("inconsistent state detected.  flags=%lX", flags);
772 
773 	return buffer;
774 }
775 
gnu_short_stack_flags(unsigned long flags)776 const char *gnu_short_stack_flags(unsigned long flags)
777 {
778 	static char buffer[4];
779 
780 	buffer[0] = (flags & PF_R ? 'R' : '-');
781 	buffer[1] = (flags & PF_W ? 'W' : '-');
782 	buffer[2] = (flags & PF_X ? 'X' : '-');
783 	buffer[3] = 0;
784 
785 	return buffer;
786 }
787 
elf_findsecbyname(const elfobj * elf,const char * name)788 const void *elf_findsecbyname(const elfobj *elf, const char *name)
789 {
790 	unsigned int i;
791 	const char *shdr_name;
792 	const void *ret = NULL;
793 
794 	if (elf->shdr == NULL) return NULL;
795 
796 #define FINDSEC(B) \
797 	if (elf->elf_class == ELFCLASS ## B) { \
798 	const Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
799 	const Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \
800 	const Elf ## B ## _Shdr *strtbl; \
801 	Elf ## B ## _Off offset; \
802 	uint16_t shstrndx = EGET(ehdr->e_shstrndx); \
803 	uint16_t shnum = EGET(ehdr->e_shnum); \
804 	if (shstrndx >= shnum) return NULL; \
805 	strtbl = &(shdr[shstrndx]); \
806 	for (i = 0; i < shnum; ++i) { \
807 		offset = EGET(strtbl->sh_offset) + EGET(shdr[i].sh_name); \
808 		if (offset >= (Elf ## B ## _Off)elf->len) continue; \
809 		shdr_name = elf->data + offset; \
810 		if (!strcmp(shdr_name, name)) { \
811 			if (ret) warnf("Multiple '%s' sections !?", name); \
812 			ret = &shdr[i]; \
813 		} \
814 	} }
815 	FINDSEC(32)
816 	FINDSEC(64)
817 
818 	return ret;
819 }
820