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