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