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