1 /*-
2  * Copyright (c) 2003 David O'Brien.  All rights reserved.
3  * Copyright (c) 2001 Jake Burkholder
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: src/usr.bin/elfdump/elfdump.c,v 1.12.8.2 2006/01/28 18:40:55 marcel Exp $");
30 
31 #include <sys/types.h>
32 #include <sys/elf32.h>
33 #include <sys/elf64.h>
34 #include <sys/endian.h>
35 #include <sys/mman.h>
36 #include <sys/stat.h>
37 #include <err.h>
38 #include <fcntl.h>
39 #include <inttypes.h>
40 #include <stddef.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #include "elfdump.h"
47 
48 #define	elf_get_addr	elf_get_quad
49 #define	elf_get_off	elf_get_quad
50 #define	elf_get_size	elf_get_quad
51 
52 enum elf_member {
53 	D_TAG = 1, D_PTR, D_VAL,
54 
55 	E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY,
56 	E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE,
57 	E_SHNUM, E_SHSTRNDX,
58 
59 	N_NAMESZ, N_DESCSZ, N_TYPE,
60 
61 	P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS,
62 	P_ALIGN,
63 
64 	SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK,
65 	SH_INFO, SH_ADDRALIGN, SH_ENTSIZE,
66 
67 	ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX,
68 
69 	R_OFFSET, R_INFO,
70 
71 	RA_OFFSET, RA_INFO, RA_ADDEND
72 };
73 
74 typedef enum elf_member elf_member_t;
75 
76 static int elf32_offsets[] = {
77 	0,
78 
79 	offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr),
80 	offsetof(Elf32_Dyn, d_un.d_val),
81 
82 	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
83 	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
84 	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
85 	offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine),
86 	offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry),
87 	offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff),
88 	offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize),
89 	offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum),
90 	offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum),
91 	offsetof(Elf32_Ehdr, e_shstrndx),
92 
93 	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
94 	offsetof(Elf_Note, n_type),
95 
96 	offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset),
97 	offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr),
98 	offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz),
99 	offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align),
100 
101 	offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type),
102 	offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr),
103 	offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size),
104 	offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info),
105 	offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize),
106 
107 	offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value),
108 	offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info),
109 	offsetof(Elf32_Sym, st_shndx),
110 
111 	offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info),
112 
113 	offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info),
114 	offsetof(Elf32_Rela, r_addend)
115 };
116 
117 static int elf64_offsets[] = {
118 	0,
119 
120 	offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr),
121 	offsetof(Elf64_Dyn, d_un.d_val),
122 
123 	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
124 	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
125 	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
126 	offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine),
127 	offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry),
128 	offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff),
129 	offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize),
130 	offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum),
131 	offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum),
132 	offsetof(Elf64_Ehdr, e_shstrndx),
133 
134 	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
135 	offsetof(Elf_Note, n_type),
136 
137 	offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset),
138 	offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr),
139 	offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz),
140 	offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align),
141 
142 	offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type),
143 	offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr),
144 	offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size),
145 	offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info),
146 	offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize),
147 
148 	offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value),
149 	offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info),
150 	offsetof(Elf64_Sym, st_shndx),
151 
152 	offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info),
153 
154 	offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info),
155 	offsetof(Elf64_Rela, r_addend)
156 };
157 
158 /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
159 static const char *
d_tags(u_int64_t tag)160 d_tags(u_int64_t tag) {
161 	switch (tag) {
162 	case 0: return "DT_NULL";
163 	case 1: return "DT_NEEDED";
164 	case 2: return "DT_PLTRELSZ";
165 	case 3: return "DT_PLTGOT";
166 	case 4: return "DT_HASH";
167 	case 5: return "DT_STRTAB";
168 	case 6: return "DT_SYMTAB";
169 	case 7: return "DT_RELA";
170 	case 8: return "DT_RELASZ";
171 	case 9: return "DT_RELAENT";
172 	case 10: return "DT_STRSZ";
173 	case 11: return "DT_SYMENT";
174 	case 12: return "DT_INIT";
175 	case 13: return "DT_FINI";
176 	case 14: return "DT_SONAME";
177 	case 15: return "DT_RPATH";
178 	case 16: return "DT_SYMBOLIC";
179 	case 17: return "DT_REL";
180 	case 18: return "DT_RELSZ";
181 	case 19: return "DT_RELENT";
182 	case 20: return "DT_PLTREL";
183 	case 21: return "DT_DEBUG";
184 	case 22: return "DT_TEXTREL";
185 	case 23: return "DT_JMPREL";
186 	case 24: return "DT_BIND_NOW";
187 	case 25: return "DT_INIT_ARRAY";
188 	case 26: return "DT_FINI_ARRAY";
189 	case 27: return "DT_INIT_ARRAYSZ";
190 	case 28: return "DT_FINI_ARRAYSZ";
191 	case 29: return "DT_RUNPATH";
192 	case 30: return "DT_FLAGS";
193 	case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */
194 	case 33: return "DT_PREINIT_ARRAYSZ";
195 	/* 0x6000000D - 0x6ffff000 operating system-specific semantics */
196 	case 0x6ffffdf5: return "DT_GNU_PRELINKED";
197 	case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
198 	case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
199 	case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
200 	case 0x6ffffdf9: return "DT_PLTPADSZ";
201 	case 0x6ffffdfa: return "DT_MOVEENT";
202 	case 0x6ffffdfb: return "DT_MOVESZ";
203 	case 0x6ffffdfc: return "DT_FEATURE";
204 	case 0x6ffffdfd: return "DT_POSFLAG_1";
205 	case 0x6ffffdfe: return "DT_SYMINSZ";
206 	case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)";
207 	case 0x6ffffe00: return "DT_ADDRRNGLO";
208 	case 0x6ffffef8: return "DT_GNU_CONFLICT";
209 	case 0x6ffffef9: return "DT_GNU_LIBLIST";
210 	case 0x6ffffefa: return "DT_SUNW_CONFIG";
211 	case 0x6ffffefb: return "DT_SUNW_DEPAUDIT";
212 	case 0x6ffffefc: return "DT_SUNW_AUDIT";
213 	case 0x6ffffefd: return "DT_SUNW_PLTPAD";
214 	case 0x6ffffefe: return "DT_SUNW_MOVETAB";
215 	case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)";
216 	case 0x6ffffff9: return "DT_RELACOUNT";
217 	case 0x6ffffffa: return "DT_RELCOUNT";
218 	case 0x6ffffffb: return "DT_FLAGS_1";
219 	case 0x6ffffffc: return "DT_VERDEF";
220 	case 0x6ffffffd: return "DT_VERDEFNUM";
221 	case 0x6ffffffe: return "DT_VERNEED";
222 	case 0x6fffffff: return "DT_VERNEEDNUM";
223 	case 0x6ffffff0: return "DT_GNU_VERSYM";
224 	/* 0x70000000 - 0x7fffffff processor-specific semantics */
225 	case 0x70000000: return "DT_IA_64_PLT_RESERVE";
226 	case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
227 	case 0x7ffffffe: return "DT_SUNW_USED";
228 	case 0x7fffffff: return "DT_SUNW_FILTER";
229 	default: return "ERROR: TAG NOT DEFINED";
230 	}
231 }
232 
233 static const char *
e_machines(u_int mach)234 e_machines(u_int mach)
235 {
236 	static char machdesc[64];
237 
238 	switch (mach) {
239 	case EM_NONE:	return "EM_NONE";
240 	case EM_M32:	return "EM_M32";
241 	case EM_SPARC:	return "EM_SPARC";
242 	case EM_386:	return "EM_386";
243 	case EM_68K:	return "EM_68K";
244 	case EM_88K:	return "EM_88K";
245 	case EM_860:	return "EM_860";
246 	case EM_MIPS:	return "EM_MIPS";
247 	case EM_PPC:	return "EM_PPC";
248 	case EM_ARM:	return "EM_ARM";
249 	case EM_ALPHA:	return "EM_ALPHA (legacy)";
250 	case EM_SPARCV9:return "EM_SPARCV9";
251 	case EM_IA_64:	return "EM_IA_64";
252 	case EM_X86_64:	return "EM_X86_64";
253 	}
254 	snprintf(machdesc, sizeof(machdesc),
255 	    "(unknown machine) -- type 0x%x", mach);
256 	return (machdesc);
257 }
258 
259 static const char *e_types[] = {
260 	"ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE"
261 };
262 
263 static const char *ei_versions[] = {
264 	"EV_NONE", "EV_CURRENT"
265 };
266 
267 static const char *ei_classes[] = {
268 	"ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64"
269 };
270 
271 static const char *ei_data[] = {
272 	"ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB"
273 };
274 
275 static const char *ei_abis[] = {
276 	"ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX",
277 	"ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS",
278 	"ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD",
279 	"ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD"
280 };
281 
282 static const char *p_types[] = {
283 	"PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE",
284 	"PT_SHLIB", "PT_PHDR", "PT_TLS"
285 };
286 
287 static const char *p_flags[] = {
288 	"", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R",
289 	"PF_X|PF_W|PF_R"
290 };
291 
292 /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
293 static const char *
sh_types(u_int64_t sht)294 sh_types(u_int64_t sht)
295 {
296 	switch (sht) {
297 	case 0:	return "SHT_NULL";
298 	case 1: return "SHT_PROGBITS";
299 	case 2: return "SHT_SYMTAB";
300 	case 3: return "SHT_STRTAB";
301 	case 4: return "SHT_RELA";
302 	case 5: return "SHT_HASH";
303 	case 6: return "SHT_DYNAMIC";
304 	case 7: return "SHT_NOTE";
305 	case 8: return "SHT_NOBITS";
306 	case 9: return "SHT_REL";
307 	case 10: return "SHT_SHLIB";
308 	case 11: return "SHT_DYNSYM";
309 	case 14: return "SHT_INIT_ARRAY";
310 	case 15: return "SHT_FINI_ARRAY";
311 	case 16: return "SHT_PREINIT_ARRAY";
312 	case 17: return "SHT_GROUP";
313 	case 18: return "SHT_SYMTAB_SHNDX";
314 	/* 0x60000000 - 0x6fffffff operating system-specific semantics */
315 	case 0x6ffffff0: return "XXX:VERSYM";
316 	case 0x6ffffff7: return "SHT_GNU_LIBLIST";
317 	case 0x6ffffffc: return "XXX:VERDEF";
318 	case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef";
319 	case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed";
320 	case 0x6fffffff: return "SHT_SUNW(GNU)_versym";
321 	/* 0x70000000 - 0x7fffffff processor-specific semantics */
322 	case 0x70000000: return "SHT_IA_64_EXT";
323 	case 0x70000001: return "SHT_IA_64_UNWIND";
324 	case 0x7ffffffd: return "XXX:AUXILIARY";
325 	case 0x7fffffff: return "XXX:FILTER";
326 	/* 0x80000000 - 0xffffffff application programs */
327 	default: return "ERROR: SHT NOT DEFINED";
328 	}
329 }
330 
331 static const char *sh_flags[] = {
332 	"", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR",
333 	"SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR",
334 	"SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR"
335 };
336 
337 static const char *st_types[] = {
338 	"STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE"
339 };
340 
341 static const char *st_bindings[] = {
342 	"STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
343 };
344 
345 /*
346  * The environment used by the parsing routines.
347  */
348 struct _env {
349 	const char	*dynstr;
350 	const char	*shstrtab;
351 	const char	*strtab;
352 	FILE		*out;
353 	Elf32_Ehdr	*e;
354 
355 	struct elfdump_info *retval;
356 };
357 
358 typedef struct _env env_t;
359 
360 static u_int64_t elf_get_byte(Elf32_Ehdr *, const void *, elf_member_t);
361 static u_int64_t elf_get_quarter(Elf32_Ehdr *, const void *, elf_member_t);
362 //static u_int64_t elf_get_half(Elf32_Ehdr *, const void *, elf_member_t);
363 static u_int64_t elf_get_word(Elf32_Ehdr *, const void *, elf_member_t);
364 static u_int64_t elf_get_quad(Elf32_Ehdr *, const void *, elf_member_t);
365 
366 /* various print routines */
367 static void elf_print_ehdr(env_t *va);
368 static void elf_print_phdr(env_t *va, const void *p);
369 static void elf_print_shdr(env_t *va, const void *sh);
370 static void elf_print_symtab(env_t *va, const void *sh, const char *str);
371 static void elf_print_dynamic(env_t *va, const void *sh);
372 static void elf_print_rel(env_t *va, const void *r);
373 static void elf_print_rela(env_t *va, const void *ra);
374 static void elf_print_interp(env_t *va, const void *p);
375 static void elf_print_got(env_t *vae, const void *sh);
376 static void elf_print_hash(env_t *va, const void *sh);
377 static void elf_print_note(env_t *va, const void *sh);
378 
379 /* internal function doing the main processing */
380 static struct elfdump_info *elfdump_main(u_int flags,
381 	const char*file, const char *symbols, FILE *out);
382 
383 /* The externally visible function */
384 struct elfdump_info *
elfdump(u_int flags,const char * file,const char * symbols)385 elfdump(u_int flags, const char *file, const char *symbols)
386 {
387 	return elfdump_main(flags, file, symbols, NULL);
388 }
389 
390 /* return a pointer to the name for the section */
391 static const char *
elf_name(env_t * va,const char * base)392 elf_name(env_t *va, const char *base)
393 {
394 	return va->shstrtab + elf_get_word(va->e, base, SH_NAME);
395 }
396 
397 #ifndef STANDALONE
398 static void
usage(void)399 usage(void)
400 {
401 	fprintf(stderr, "usage: elfdump -a | -cdeGhinprs [-w file] file\n");
402 	exit(1);
403 }
404 
405 int
main(int ac,char ** av)406 main(int ac, char **av)
407 {
408 	u_int flags = 0;
409 	int ch;
410 	FILE *out = stdout;
411 	const char *symbols = NULL;
412 
413 	while ((ch = getopt(ac, av, "acdeiGhnpqrsw:")) != -1) {
414 		switch (ch) {
415 		case 'a':
416 			flags = ED_ALL;
417 			break;
418 		case 'c':
419 			flags |= ED_SHDR;
420 			break;
421 		case 'd':
422 			flags |= ED_DYN;
423 			break;
424 		case 'e':
425 			flags |= ED_EHDR;
426 			break;
427 		case 'i':
428 			flags |= ED_INTERP;
429 			break;
430 		case 'G':
431 			flags |= ED_GOT;
432 			break;
433 		case 'h':
434 			flags |= ED_HASH;
435 			break;
436 		case 'n':
437 			flags |= ED_NOTE;
438 			break;
439 		case 'p':
440 			flags |= ED_PHDR;
441 			break;
442 		case 'q':
443 			out = NULL;	/* quiet */
444 			break;
445 		case 'r':
446 			flags |= ED_REL;
447 			break;
448 		case 's':
449 			flags |= ED_SYMTAB;
450 			break;
451 		case 'w':
452 			if ((out = fopen(optarg, "w")) == NULL)
453 				err(1, "%s", optarg);
454 			break;
455 		case '?':
456 		default:
457 			usage();
458 		}
459 	}
460 	ac -= optind;
461 	av += optind;
462 	if (ac == 0 || flags == 0)
463 		usage();
464 	if (ac > 1)
465 		symbols = av[1];
466 	elfdump_main(flags, *av, symbols, out);
467 	return 0;
468 }
469 #endif
470 
471 struct elfdump_info *
elfdump_main(u_int flags,const char * file,const char * symbols,FILE * out)472 elfdump_main(u_int flags, const char *file, const char *symbols,
473 	FILE *out)
474 {
475 	u_int64_t shentsize;
476 	u_int64_t shnum;
477 	u_int64_t shstrndx;
478 	u_int64_t offset;
479 	u_int64_t type;
480 	struct stat sb;
481 	Elf32_Ehdr *e;
482 	void *p;
483 	const char *sh;
484 	const void *v;
485 	int fd;
486 	int i;
487 	env_t env, *va = &env;
488 
489 	bzero(va, sizeof(env));
490 	va->out = out;
491 
492 	/* prepare the storage for the match info */
493 	if (symbols) {
494 		int ml, l = strlen(symbols) + 1;
495 		void *mem;
496 		char *syms;
497 
498 		/* count number of entries to match */
499 		for (i = 0, sh = symbols; (ml = strcspn(sh, ",|;")) ; i++) {
500 			sh += ml;
501 			if (*sh)
502 				sh++;
503 		}
504 
505 		mem = calloc(1, l + sizeof(struct elfdump_info) +
506 				i * sizeof(struct elf_entry));
507 		if (mem == NULL)
508 			err(1, "calloc failures");
509 		va->retval = mem;
510 		va->retval->count = i;
511 		mem = (char *)mem + l + sizeof(struct elfdump_info) +
512 				i * sizeof(struct elf_entry);
513 		strcpy(mem, symbols);	/* writable string */
514 		for (i = 0, syms = mem; syms; i++) {
515 			va->retval->m[i].name =syms;
516 			strsep(&syms, ",;|");
517 		}
518 	}
519 
520 	if ((fd = open(file, O_RDONLY)) < 0 ||
521 	    fstat(fd, &sb) < 0)
522 		err(1, "%s", file);
523 	va->e = e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
524 	if (va->e == MAP_FAILED)
525 		err(1, NULL);
526 	if (!IS_ELF(*(Elf32_Ehdr *)e))
527 		errx(1, "not an elf file");
528 	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
529 	shnum = elf_get_quarter(e, e, E_SHNUM);
530 	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
531 	p = (char *)e + elf_get_off(va->e, e, E_PHOFF);
532 	sh = (char *)e + elf_get_off(va->e, e, E_SHOFF);
533 	offset = elf_get_off(e, sh + shstrndx * shentsize, SH_OFFSET);
534 	va->shstrtab = (char *)e + offset;
535 	for (i = 0; (u_int64_t)i < shnum; i++) {
536 		const char *x = elf_name(va, sh + i * shentsize);
537 		offset = elf_get_off(e, sh + i * shentsize, SH_OFFSET);
538 		if (strcmp(x, ".strtab") == 0)
539 			va->strtab = (char *)e + offset;
540 		if (strcmp(x, ".dynstr") == 0)
541 			va->dynstr = (char *)e + offset;
542 	}
543 	if (va->out) {
544 		u_int64_t phnum = elf_get_quarter(e, e, E_PHNUM);
545 		u_int64_t phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
546 
547 		if (flags & ED_EHDR && va->out)
548 			elf_print_ehdr(va);
549 		if (flags & ED_PHDR && va->out)
550 			elf_print_phdr(va, p);
551 		if (flags & ED_SHDR && va->out)
552 			elf_print_shdr(va, sh);
553 
554 		for (i = 0; (u_int64_t)i < phnum; i++) {
555 			v = (char *)p + i * phentsize;
556 			type = elf_get_word(e, v, P_TYPE);
557 			switch (type) {
558 			case PT_INTERP:
559 				if (flags & ED_INTERP)
560 					elf_print_interp(va, v);
561 				break;
562 			case PT_NULL:
563 			case PT_LOAD:
564 			case PT_DYNAMIC:
565 			case PT_NOTE:
566 			case PT_SHLIB:
567 			case PT_PHDR:
568 				break;
569 			}
570 		}
571 	}
572 	for (i = 0; (u_int64_t)i < shnum; i++) {
573 		v = sh + i * shentsize;
574 		type = elf_get_word(e, v, SH_TYPE);
575 		switch (type) {
576 		case SHT_SYMTAB:
577 			if (flags & ED_SYMTAB)
578 				elf_print_symtab(va, v, va->strtab);
579 			break;
580 		case SHT_DYNAMIC:
581 			if (flags & ED_DYN && va->out)
582 				elf_print_dynamic(va, v);
583 			break;
584 		case SHT_RELA:
585 			if (flags & ED_REL && va->out)
586 				elf_print_rela(va, v);
587 			break;
588 		case SHT_REL:
589 			if (flags & ED_REL && va->out)
590 				elf_print_rel(va, v);
591 			break;
592 		case SHT_NOTE:
593 			if (flags & ED_NOTE && va->out &&
594 			    strcmp(elf_name(va, v), ".note.ABI-tag") == 0)
595 				elf_print_note(va, v);
596 			break;
597 		case SHT_DYNSYM:
598 			if (flags & ED_SYMTAB)
599 				elf_print_symtab(va, v, va->dynstr);
600 			break;
601 		case SHT_PROGBITS:
602 			if (flags & ED_GOT && va->out &&
603 			    strcmp(elf_name(va, v), ".got") == 0)
604 				elf_print_got(va, v);
605 			break;
606 		case SHT_HASH:
607 			if (flags & ED_HASH && va->out)
608 				elf_print_hash(va, v);
609 			break;
610 		case SHT_NULL:
611 		case SHT_STRTAB:
612 		case SHT_NOBITS:
613 		case SHT_SHLIB:
614 			break;
615 		}
616 	}
617 
618 	return va->retval;
619 }
620 
621 static void
elf_print_ehdr(env_t * va)622 elf_print_ehdr(env_t *va)
623 {
624 	u_int64_t type;
625 	u_int64_t machine;
626 	u_int64_t version;
627 	u_int64_t entry;
628 	u_int64_t phoff;
629 	u_int64_t shoff;
630 	u_int64_t flags;
631 	u_int64_t ehsize;
632 	u_int64_t phentsize;
633 	u_int64_t phnum;
634 	u_int64_t shentsize;
635 	u_int64_t shnum;
636 	u_int64_t shstrndx;
637 	Elf32_Ehdr *e = va->e;
638 	FILE *out = va->out;
639 
640 	type = elf_get_quarter(e, e, E_TYPE);
641 	machine = elf_get_quarter(e, e, E_MACHINE);
642 	version = elf_get_word(e, e, E_VERSION);
643 	entry = elf_get_addr(e, e, E_ENTRY);
644 	phoff = elf_get_off(e, e, E_PHOFF);
645 	shoff = elf_get_off(e, e, E_SHOFF);
646 	flags = elf_get_word(e, e, E_FLAGS);
647 	ehsize = elf_get_quarter(e, e, E_EHSIZE);
648 	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
649 	phnum = elf_get_quarter(e, e, E_PHNUM);
650 	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
651 	shnum = elf_get_quarter(e, e, E_SHNUM);
652 	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
653 	fprintf(out, "\nelf header:\n\n");
654 	fprintf(out, "\te_ident: %s %s %s\n",
655 	    ei_classes[elf_get_byte(e, e, E_CLASS)],
656 	    ei_data[elf_get_byte(e, e, E_DATA)],
657 	    ei_abis[elf_get_byte(e, e, E_OSABI)]);
658 	fprintf(out, "\te_type: %s\n", e_types[type]);
659 	fprintf(out, "\te_machine: %s\n", e_machines(machine));
660 	fprintf(out, "\te_version: %s\n", ei_versions[version]);
661 	fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry);
662 	fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff);
663 	fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff);
664 	fprintf(out, "\te_flags: %jd\n", (intmax_t)flags);
665 	fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize);
666 	fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize);
667 	fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum);
668 	fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize);
669 	fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum);
670 	fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx);
671 }
672 
673 static void
elf_print_phdr(env_t * va,const void * p)674 elf_print_phdr(env_t *va, const void *p)
675 {
676 	u_int64_t phentsize;
677 	u_int64_t phnum;
678 	u_int64_t type;
679 	u_int64_t offset;
680 	u_int64_t vaddr;
681 	u_int64_t paddr;
682 	u_int64_t filesz;
683 	u_int64_t memsz;
684 	u_int64_t flags;
685 	u_int64_t align;
686 	const void *v;
687 	int i;
688 	Elf32_Ehdr *e = va->e;
689 	FILE *out = va->out;
690 
691 	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
692 	phnum = elf_get_quarter(e, e, E_PHNUM);
693 	fprintf(out, "\nprogram header:\n");
694 	for (i = 0; (u_int64_t)i < phnum; i++) {
695 		v = (const char *)p + i * phentsize;
696 		type = elf_get_word(e, v, P_TYPE);
697 		offset = elf_get_off(e, v, P_OFFSET);
698 		vaddr = elf_get_addr(e, v, P_VADDR);
699 		paddr = elf_get_addr(e, v, P_PADDR);
700 		filesz = elf_get_size(e, v, P_FILESZ);
701 		memsz = elf_get_size(e, v, P_MEMSZ);
702 		flags = elf_get_word(e, v, P_FLAGS);
703 		align = elf_get_size(e, v, P_ALIGN);
704 		fprintf(out, "\nentry: %d\n", i);
705 		fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]);
706 		fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset);
707 		fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr);
708 		fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr);
709 		fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz);
710 		fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz);
711 		fprintf(out, "\tp_flags: %s\n", p_flags[flags]);
712 		fprintf(out, "\tp_align: %jd\n", (intmax_t)align);
713 	}
714 }
715 
716 static void
elf_print_shdr(env_t * va,const void * sh)717 elf_print_shdr(env_t *va, const void *sh)
718 {
719 	u_int64_t shentsize;
720 	u_int64_t shnum;
721 	u_int64_t type;
722 	u_int64_t flags;
723 	u_int64_t addr;
724 	u_int64_t offset;
725 	u_int64_t size;
726 	u_int64_t shlink;
727 	u_int64_t info;
728 	u_int64_t addralign;
729 	u_int64_t entsize;
730 	const void *v;
731 	int i;
732 
733 	Elf32_Ehdr *e = va->e;
734 	FILE *out = va->out;
735 	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
736 	shnum = elf_get_quarter(e, e, E_SHNUM);
737 	fprintf(out, "\nsection header:\n");
738 	for (i = 0; (u_int64_t)i < shnum; i++) {
739 		v = (const char *)sh + i * shentsize;
740 		type = elf_get_word(e, v, SH_TYPE);
741 		flags = elf_get_word(e, v, SH_FLAGS);
742 		addr = elf_get_addr(e, v, SH_ADDR);
743 		offset = elf_get_off(e, v, SH_OFFSET);
744 		size = elf_get_size(e, v, SH_SIZE);
745 		shlink = elf_get_word(e, v, SH_LINK);
746 		info = elf_get_word(e, v, SH_INFO);
747 		addralign = elf_get_size(e, v, SH_ADDRALIGN);
748 		entsize = elf_get_size(e, v, SH_ENTSIZE);
749 		fprintf(out, "\nentry: %d\n", i);
750 		fprintf(out, "\tsh_name: %s\n", elf_name(va, v));
751 		fprintf(out, "\tsh_type: %s\n", sh_types(type));
752 		fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]);
753 		fprintf(out, "\tsh_addr: %#jx\n", addr);
754 		fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset);
755 		fprintf(out, "\tsh_size: %jd\n", (intmax_t)size);
756 		fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink);
757 		fprintf(out, "\tsh_info: %jd\n", (intmax_t)info);
758 		fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign);
759 		fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize);
760 	}
761 }
762 
763 static void
elf_print_symtab(env_t * va,const void * sh,const char * str)764 elf_print_symtab(env_t *va, const void *sh, const char *str)
765 {
766 	u_int64_t offset;
767 	u_int64_t entsize;
768 	u_int64_t size;
769 	u_int64_t name;
770 	u_int64_t value;
771 	u_int64_t info;
772 	u_int64_t shndx;
773 	void *st;
774 	int len;
775 	int i;
776 
777 	Elf32_Ehdr *e = va->e;
778 	FILE *out = va->out;
779 
780 	offset = elf_get_off(e, sh, SH_OFFSET);
781 	entsize = elf_get_size(e, sh, SH_ENTSIZE);
782 	size = elf_get_size(e, sh, SH_SIZE);
783 	len = size / entsize;
784 	if (out)
785 		fprintf(out, "\nsymbol table (%s):\n", elf_name(va, sh));
786 	for (i = 0; i < len; i++) {
787 		st = (char *)e + offset + i * entsize;
788 		name = elf_get_word(e, st, ST_NAME);
789 		value = elf_get_addr(e, st, ST_VALUE);
790 		size = elf_get_size(e, st, ST_SIZE);
791 		info = elf_get_byte(e, st, ST_INFO);
792 		shndx = elf_get_quarter(e, st, ST_SHNDX);
793 		if (va->retval) {
794 			int j;
795 
796 			for (j = 0; j < va->retval->count; j++) {
797 				if (!strcmp(str + name, va->retval->m[j].name))
798 					break;	/* found */
799 			}
800 			if (j == va->retval->count)
801 				continue;	/* not found */
802 			va->retval->m[j].value = value;
803 			va->retval->m[j].size = size;
804 			fprintf(stderr, "entry %d %s 0x%x 0x%x\n",
805 				j, va->retval->m[j].name,
806 				(int)value, (int)size);
807 		}
808 		if (!out)
809 			continue;
810 		fprintf(out, "\nentry: %d\n", i);
811 		fprintf(out, "\tst_name: %s\n", str + name);
812 		fprintf(out, "\tst_value: %#jx\n", value);
813 		fprintf(out, "\tst_size: %jd\n", (intmax_t)size);
814 		fprintf(out, "\tst_info: %s %s\n",
815 		    st_types[ELF32_ST_TYPE(info)],
816 		    st_bindings[ELF32_ST_BIND(info)]);
817 		fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx);
818 	}
819 }
820 
821 static void
elf_print_dynamic(env_t * va,const void * sh)822 elf_print_dynamic(env_t *va, const void *sh)
823 {
824 	u_int64_t offset;
825 	u_int64_t entsize;
826 	u_int64_t size;
827 	int64_t tag;
828 	u_int64_t ptr;
829 	u_int64_t val;
830 	void *d;
831 	int i;
832 
833 	Elf32_Ehdr *e = va->e;
834 	FILE *out = va->out;
835 
836 	offset = elf_get_off(e, sh, SH_OFFSET);
837 	entsize = elf_get_size(e, sh, SH_ENTSIZE);
838 	size = elf_get_size(e, sh, SH_SIZE);
839 	fprintf(out, "\ndynamic:\n");
840 	for (i = 0; (u_int64_t)i < size / entsize; i++) {
841 		d = (char *)e + offset + i * entsize;
842 		tag = elf_get_size(e, d, D_TAG);
843 		ptr = elf_get_size(e, d, D_PTR);
844 		val = elf_get_addr(e, d, D_VAL);
845 		fprintf(out, "\nentry: %d\n", i);
846 		fprintf(out, "\td_tag: %s\n", d_tags(tag));
847 		switch (tag) {
848 		case DT_NEEDED:
849 		case DT_SONAME:
850 		case DT_RPATH:
851 			fprintf(out, "\td_val: %s\n", va->dynstr + val);
852 			break;
853 		case DT_PLTRELSZ:
854 		case DT_RELA:
855 		case DT_RELASZ:
856 		case DT_RELAENT:
857 		case DT_STRSZ:
858 		case DT_SYMENT:
859 		case DT_RELSZ:
860 		case DT_RELENT:
861 		case DT_PLTREL:
862 			fprintf(out, "\td_val: %jd\n", (intmax_t)val);
863 			break;
864 		case DT_PLTGOT:
865 		case DT_HASH:
866 		case DT_STRTAB:
867 		case DT_SYMTAB:
868 		case DT_INIT:
869 		case DT_FINI:
870 		case DT_REL:
871 		case DT_JMPREL:
872 			fprintf(out, "\td_ptr: %#jx\n", ptr);
873 			break;
874 		case DT_NULL:
875 		case DT_SYMBOLIC:
876 		case DT_DEBUG:
877 		case DT_TEXTREL:
878 			break;
879 		}
880 	}
881 }
882 
883 static void
elf_print_rela(env_t * va,const void * sh)884 elf_print_rela(env_t *va, const void *sh)
885 {
886 	u_int64_t offset;
887 	u_int64_t entsize;
888 	u_int64_t size;
889 	u_int64_t info;
890 	int64_t addend;
891 	void *ra;
892 	void *v;
893 	int i;
894 
895 	Elf32_Ehdr *e = va->e;
896 	FILE *out = va->out;
897 
898 	offset = elf_get_off(e, sh, SH_OFFSET);
899 	entsize = elf_get_size(e, sh, SH_ENTSIZE);
900 	size = elf_get_size(e, sh, SH_SIZE);
901 	v = (char *)e + offset;
902 	fprintf(out, "\nrelocation with addend (%s):\n",
903 		elf_name(va, sh));
904 	for (i = 0; (u_int64_t)i < size / entsize; i++) {
905 		ra = (char *)v + i * entsize;
906 		offset = elf_get_addr(e, ra, RA_OFFSET);
907 		info = elf_get_word(e, ra, RA_INFO);
908 		addend = elf_get_off(e, ra, RA_ADDEND);
909 		fprintf(out, "\nentry: %d\n", i);
910 		fprintf(out, "\tr_offset: %#jx\n", offset);
911 		fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
912 		fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend);
913 	}
914 }
915 
916 static void
elf_print_rel(env_t * va,const void * sh)917 elf_print_rel(env_t *va, const void *sh)
918 {
919 	u_int64_t offset;
920 	u_int64_t entsize;
921 	u_int64_t size;
922 	u_int64_t info;
923 	const char *r;
924 	const char *v;
925 	int i;
926 
927 	Elf32_Ehdr *e = va->e;
928 	FILE *out = va->out;
929 
930 	entsize = elf_get_size(e, sh, SH_ENTSIZE);
931 	size = elf_get_size(e, sh, SH_SIZE);
932 	v = (const char *)e + elf_get_off(e, sh, SH_OFFSET);
933 	fprintf(out, "\nrelocation (%s):\n",
934 		elf_name(va, sh));
935 	for (i = 0; (u_int64_t)i < size / entsize; i++) {
936 		r = v + i * entsize;
937 		offset = elf_get_addr(e, r, R_OFFSET);
938 		info = elf_get_word(e, r, R_INFO);
939 		fprintf(out, "\nentry: %d\n", i);
940 		fprintf(out, "\tr_offset: %#jx\n", offset);
941 		fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
942 	}
943 }
944 
945 static void
elf_print_interp(env_t * va,const void * p)946 elf_print_interp(env_t *va, const void *p)
947 {
948 
949 	fprintf(va->out, "\ninterp:\n\t%s\n",
950 		(const char *)va->e + elf_get_off(va->e, p, P_OFFSET));
951 }
952 
953 static void
elf_print_got(env_t * va,const void * sh)954 elf_print_got(env_t *va, const void *sh)
955 {
956 	u_int64_t addralign;
957 	u_int64_t size;
958 	u_int64_t addr;
959 	const char *v;
960 	int i;
961 
962 	addralign = elf_get_size(va->e, sh, SH_ADDRALIGN);
963 	size = elf_get_size(va->e, sh, SH_SIZE);
964 	v = (char *)va->e + elf_get_off(va->e, sh, SH_OFFSET);
965 	fprintf(va->out, "\nglobal offset table:\n");
966 	for (i = 0; (u_int64_t)i < size / addralign; i++) {
967 		addr = elf_get_addr(va->e, v + i * addralign, 0);
968 		fprintf(va->out, "\nentry: %d\n\t%#jx\n", i, addr);
969 	}
970 }
971 
972 static void
elf_print_hash(env_t * va __unused,const void * sh __unused)973 elf_print_hash(env_t *va __unused, const void *sh __unused)
974 {
975 }
976 
977 static void
elf_print_note(env_t * va,const void * sh)978 elf_print_note(env_t *va, const void *sh)
979 {
980 	const char *n, *lim;
981 
982 	fprintf(va->out, "\nnote (%s):\n",
983 		elf_name(va, sh));
984 	n = (const char *)va->e + elf_get_off(va->e, sh, SH_OFFSET);
985 	lim = n + elf_get_size(va->e, sh, SH_SIZE);
986  	while (n < lim) {
987 		u_int32_t namesz = elf_get_word(va->e, n, N_NAMESZ);
988 		u_int32_t descsz = elf_get_word(va->e, n, N_DESCSZ);
989 		// u_int_32_t type = elf_get_word(va->e, n, N_TYPE);
990  		const char *s = n + sizeof(Elf_Note);
991  		u_int32_t desc = elf_get_word(va->e, s + namesz, 0);
992 		fprintf(va->out, "\t%s %d\n", s, desc);
993 		n += sizeof(Elf_Note) + namesz + descsz;
994 	}
995 }
996 
997 /*
998  * return entries from the elf header 1..8 bytes long.
999  * The value returned is always an u_int64_t
1000  */
1001 static u_int64_t
elf_get_byte(Elf32_Ehdr * e,const void * base,elf_member_t member)1002 elf_get_byte(Elf32_Ehdr *e, const void *base, elf_member_t member)
1003 {
1004 	u_int64_t val;
1005 
1006 	val = 0;
1007 	switch (e->e_ident[EI_CLASS]) {
1008 	case ELFCLASS32:
1009 		val = ((const char *)base)[elf32_offsets[member]];
1010 		break;
1011 	case ELFCLASS64:
1012 		val = ((const char *)base)[elf64_offsets[member]];
1013 		break;
1014 	case ELFCLASSNONE:
1015 		errx(1, "invalid class");
1016 	}
1017 
1018 	return val;
1019 }
1020 
1021 static u_int64_t
elf_get_quarter(Elf32_Ehdr * e,const void * base,elf_member_t member)1022 elf_get_quarter(Elf32_Ehdr *e, const void *base, elf_member_t member)
1023 {
1024 	u_int64_t val;
1025 
1026 	val = 0;
1027 	switch (e->e_ident[EI_CLASS]) {
1028 	case ELFCLASS32:
1029 		base = (const char *)base + elf32_offsets[member];
1030 		switch (e->e_ident[EI_DATA]) {
1031 		case ELFDATA2MSB:
1032 			val = be16dec(base);
1033 			break;
1034 		case ELFDATA2LSB:
1035 			val = le16dec(base);
1036 			break;
1037 		case ELFDATANONE:
1038 			errx(1, "invalid data format");
1039 		}
1040 		break;
1041 	case ELFCLASS64:
1042 		base = (const char *)base + elf64_offsets[member];
1043 		switch (e->e_ident[EI_DATA]) {
1044 		case ELFDATA2MSB:
1045 			val = be16dec(base);
1046 			break;
1047 		case ELFDATA2LSB:
1048 			val = le16dec(base);
1049 			break;
1050 		case ELFDATANONE:
1051 			errx(1, "invalid data format");
1052 		}
1053 		break;
1054 	case ELFCLASSNONE:
1055 		errx(1, "invalid class");
1056 	}
1057 
1058 	return val;
1059 }
1060 
1061 #if 0
1062 static u_int64_t
1063 elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member)
1064 {
1065 	u_int64_t val;
1066 
1067 	val = 0;
1068 	switch (e->e_ident[EI_CLASS]) {
1069 	case ELFCLASS32:
1070 		base = (char *)base + elf32_offsets[member];
1071 		switch (e->e_ident[EI_DATA]) {
1072 		case ELFDATA2MSB:
1073 			val = be16dec(base);
1074 			break;
1075 		case ELFDATA2LSB:
1076 			val = le16dec(base);
1077 			break;
1078 		case ELFDATANONE:
1079 			errx(1, "invalid data format");
1080 		}
1081 		break;
1082 	case ELFCLASS64:
1083 		base = (char *)base + elf64_offsets[member];
1084 		switch (e->e_ident[EI_DATA]) {
1085 		case ELFDATA2MSB:
1086 			val = be32dec(base);
1087 			break;
1088 		case ELFDATA2LSB:
1089 			val = le32dec(base);
1090 			break;
1091 		case ELFDATANONE:
1092 			errx(1, "invalid data format");
1093 		}
1094 		break;
1095 	case ELFCLASSNONE:
1096 		errx(1, "invalid class");
1097 	}
1098 
1099 	return val;
1100 }
1101 #endif
1102 
1103 static u_int64_t
elf_get_word(Elf32_Ehdr * e,const void * base,elf_member_t member)1104 elf_get_word(Elf32_Ehdr *e, const void *base, elf_member_t member)
1105 {
1106 	u_int64_t val;
1107 
1108 	val = 0;
1109 	switch (e->e_ident[EI_CLASS]) {
1110 	case ELFCLASS32:
1111 		base = (const char *)base + elf32_offsets[member];
1112 		switch (e->e_ident[EI_DATA]) {
1113 		case ELFDATA2MSB:
1114 			val = be32dec(base);
1115 			break;
1116 		case ELFDATA2LSB:
1117 			val = le32dec(base);
1118 			break;
1119 		case ELFDATANONE:
1120 			errx(1, "invalid data format");
1121 		}
1122 		break;
1123 	case ELFCLASS64:
1124 		base = (const char *)base + elf64_offsets[member];
1125 		switch (e->e_ident[EI_DATA]) {
1126 		case ELFDATA2MSB:
1127 			val = be32dec(base);
1128 			break;
1129 		case ELFDATA2LSB:
1130 			val = le32dec(base);
1131 			break;
1132 		case ELFDATANONE:
1133 			errx(1, "invalid data format");
1134 		}
1135 		break;
1136 	case ELFCLASSNONE:
1137 		errx(1, "invalid class");
1138 	}
1139 
1140 	return val;
1141 }
1142 
1143 static u_int64_t
elf_get_quad(Elf32_Ehdr * e,const void * base,elf_member_t member)1144 elf_get_quad(Elf32_Ehdr *e, const void *base, elf_member_t member)
1145 {
1146 	u_int64_t val;
1147 
1148 	val = 0;
1149 	switch (e->e_ident[EI_CLASS]) {
1150 	case ELFCLASS32:
1151 		base = (const char *)base + elf32_offsets[member];
1152 		switch (e->e_ident[EI_DATA]) {
1153 		case ELFDATA2MSB:
1154 			val = be32dec(base);
1155 			break;
1156 		case ELFDATA2LSB:
1157 			val = le32dec(base);
1158 			break;
1159 		case ELFDATANONE:
1160 			errx(1, "invalid data format");
1161 		}
1162 		break;
1163 	case ELFCLASS64:
1164 		base = (const char *)base + elf64_offsets[member];
1165 		switch (e->e_ident[EI_DATA]) {
1166 		case ELFDATA2MSB:
1167 			val = be64dec(base);
1168 			break;
1169 		case ELFDATA2LSB:
1170 			val = le64dec(base);
1171 			break;
1172 		case ELFDATANONE:
1173 			errx(1, "invalid data format");
1174 		}
1175 		break;
1176 	case ELFCLASSNONE:
1177 		errx(1, "invalid class");
1178 	}
1179 
1180 	return val;
1181 }
1182