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