elfdump.c revision 110257
1233294Sstas/*-
2102644Snectar * Copyright (c) 2003 David O'Brien.  All rights reserved.
357416Smarkm * Copyright (c) 2001 Jake Burkholder
4142403Snectar * All rights reserved.
5233294Sstas *
6233294Sstas * Redistribution and use in source and binary forms, with or without
757416Smarkm * modification, are permitted provided that the following conditions
857416Smarkm * are met:
957416Smarkm * 1. Redistributions of source code must retain the above copyright
1057416Smarkm *    notice, this list of conditions and the following disclaimer.
1157416Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1257416Smarkm *    notice, this list of conditions and the following disclaimer in the
1357416Smarkm *    documentation and/or other materials provided with the distribution.
1457416Smarkm *
1557416Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1690926Snectar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1790926Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1990926Snectar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2190926Snectar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2357416Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2457416Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25233294Sstas * SUCH DAMAGE.
2657416Smarkm */
27233294Sstas
28102644Snectar#include <sys/cdefs.h>
29102644Snectar__FBSDID("$FreeBSD: head/usr.bin/elfdump/elfdump.c 110257 2003-02-03 01:30:47Z obrien $");
30102644Snectar
31127808Snectar#include <sys/types.h>
3290926Snectar#include <sys/elf32.h>
33127808Snectar#include <sys/elf64.h>
3457416Smarkm#include <sys/mman.h>
3557416Smarkm#include <sys/stat.h>
3657416Smarkm#include <err.h>
3757416Smarkm#include <fcntl.h>
3857416Smarkm#include <inttypes.h>
3957416Smarkm#include <stddef.h>
40178825Sdfr#include <stdio.h>
4157416Smarkm#include <stdlib.h>
42142403Snectar#include <string.h>
43142403Snectar#include <unistd.h>
44142403Snectar
45142403Snectar#define	ED_DYN		(1<<0)
46142403Snectar#define	ED_EHDR		(1<<1)
47142403Snectar#define	ED_GOT		(1<<2)
48233294Sstas#define	ED_HASH		(1<<3)
49142403Snectar#define	ED_INTERP	(1<<4)
50142403Snectar#define	ED_NOTE		(1<<5)
51142403Snectar#define	ED_PHDR		(1<<6)
52142403Snectar#define	ED_REL		(1<<7)
53142403Snectar#define	ED_SHDR		(1<<8)
54142403Snectar#define	ED_SYMTAB	(1<<9)
55142403Snectar#define	ED_ALL		((1<<10)-1)
56142403Snectar
57142403Snectar#define	elf_get_addr	elf_get_quad
58142403Snectar#define	elf_get_off	elf_get_quad
59142403Snectar#define	elf_get_size	elf_get_quad
60142403Snectar
61142403Snectarenum elf_member {
62142403Snectar	D_TAG = 1, D_PTR, D_VAL,
63233294Sstas
64142403Snectar	E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY,
65142403Snectar	E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE,
66142403Snectar	E_SHNUM, E_SHSTRNDX,
67142403Snectar
68178825Sdfr	N_NAMESZ, N_DESCSZ, N_TYPE,
69142403Snectar
70142403Snectar	P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS,
71142403Snectar	P_ALIGN,
72142403Snectar
73142403Snectar	SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK,
74142403Snectar	SH_INFO, SH_ADDRALIGN, SH_ENTSIZE,
75142403Snectar
76142403Snectar	ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX,
77233294Sstas
78233294Sstas	R_OFFSET, R_INFO,
79233294Sstas
80233294Sstas	RA_OFFSET, RA_INFO, RA_ADDEND
81233294Sstas};
82233294Sstas
83178825Sdfrtypedef enum elf_member elf_member_t;
84178825Sdfr
85178825Sdfrint elf32_offsets[] = {
86178825Sdfr	0,
87178825Sdfr
88178825Sdfr	offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr),
89178825Sdfr	offsetof(Elf32_Dyn, d_un.d_val),
90233294Sstas
91142403Snectar	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
92142403Snectar	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
93178825Sdfr	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
94142403Snectar	offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine),
95142403Snectar	offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry),
96233294Sstas	offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff),
97142403Snectar	offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize),
98142403Snectar	offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum),
99142403Snectar	offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum),
100142403Snectar	offsetof(Elf32_Ehdr, e_shstrndx),
101178825Sdfr
102178825Sdfr	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
103178825Sdfr	offsetof(Elf_Note, n_type),
104178825Sdfr
105178825Sdfr	offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset),
106178825Sdfr	offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr),
107178825Sdfr	offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz),
108233294Sstas	offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align),
109233294Sstas
110233294Sstas	offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type),
111142403Snectar	offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr),
112142403Snectar	offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size),
113142403Snectar	offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info),
114142403Snectar	offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize),
115233294Sstas
116233294Sstas	offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value),
117233294Sstas	offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info),
118233294Sstas	offsetof(Elf32_Sym, st_shndx),
119233294Sstas
120233294Sstas	offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info),
121233294Sstas
122233294Sstas	offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info),
123233294Sstas	offsetof(Elf32_Rela, r_addend)
124233294Sstas};
125233294Sstas
126233294Sstasint elf64_offsets[] = {
127233294Sstas	0,
128233294Sstas
129233294Sstas	offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr),
130233294Sstas	offsetof(Elf64_Dyn, d_un.d_val),
131233294Sstas
132233294Sstas	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
133233294Sstas	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
134233294Sstas	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
135233294Sstas	offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine),
136233294Sstas	offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry),
137233294Sstas	offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff),
138233294Sstas	offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize),
139233294Sstas	offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum),
140127808Snectar	offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum),
14157416Smarkm	offsetof(Elf64_Ehdr, e_shstrndx),
14272445Sassar
143127808Snectar	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
144233294Sstas	offsetof(Elf_Note, n_type),
145233294Sstas
146127808Snectar	offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset),
147127808Snectar	offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr),
148127808Snectar	offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz),
14957416Smarkm	offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align),
15057416Smarkm
151233294Sstas	offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type),
152233294Sstas	offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr),
15357416Smarkm	offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size),
15457416Smarkm	offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info),
15557416Smarkm	offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize),
156233294Sstas
157127808Snectar	offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value),
15890926Snectar	offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info),
15972445Sassar	offsetof(Elf64_Sym, st_shndx),
160127808Snectar
161127808Snectar	offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info),
162233294Sstas
16357416Smarkm	offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info),
164127808Snectar	offsetof(Elf64_Rela, r_addend)
165233294Sstas};
16690926Snectar
167178825Sdfr/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
168178825Sdfrstatic const char *
16972445Sassard_tags(u_int64_t tag) {
170233294Sstas	switch (tag) {
171233294Sstas	case 0: return "DT_NULL";
172233294Sstas	case 1: return "DT_NEEDED";
173127808Snectar	case 2: return "DT_PLTRELSZ";
174127808Snectar	case 3: return "DT_PLTGOT";
175127808Snectar	case 4: return "DT_HASH";
176127808Snectar	case 5: return "DT_STRTAB";
177127808Snectar	case 6: return "DT_SYMTAB";
178233294Sstas	case 7: return "DT_RELA";
179178825Sdfr	case 8: return "DT_RELASZ";
18057416Smarkm	case 9: return "DT_RELAENT";
18172445Sassar	case 10: return "DT_STRSZ";
182178825Sdfr	case 11: return "DT_SYMENT";
183127808Snectar	case 12: return "DT_INIT";
184127808Snectar	case 13: return "DT_FINI";
185233294Sstas	case 14: return "DT_SONAME";
186233294Sstas	case 15: return "DT_RPATH";
187127808Snectar	case 16: return "DT_SYMBOLIC";
188127808Snectar	case 17: return "DT_REL";
189233294Sstas	case 18: return "DT_RELSZ";
190178825Sdfr	case 19: return "DT_RELENT";
191127808Snectar	case 20: return "DT_PLTREL";
192127808Snectar	case 21: return "DT_DEBUG";
193127808Snectar	case 22: return "DT_TEXTREL";
19490926Snectar	case 23: return "DT_JMPREL";
195233294Sstas	case 24: return "DT_BIND_NOW";
196127808Snectar	case 25: return "DT_INIT_ARRAY";
197178825Sdfr	case 26: return "DT_FINI_ARRAY";
19857416Smarkm	case 27: return "DT_INIT_ARRAYSZ";
199102644Snectar	case 28: return "DT_FINI_ARRAYSZ";
200102644Snectar	case 29: return "DT_RUNPATH";
201178825Sdfr	case 30: return "DT_FLAGS";
202127808Snectar	case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */
203127808Snectar	case 33: return "DT_PREINIT_ARRAYSZ";
20457416Smarkm	/* 0x6000000D - 0x6ffff000 operating system-specific semantics */
20557416Smarkm	case 0x6ffffdf5: return "DT_GNU_PRELINKED";
20690926Snectar	case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
207127808Snectar	case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
208127808Snectar	case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
209127808Snectar	case 0x6ffffdf9: return "DT_PLTPADSZ";
210127808Snectar	case 0x6ffffdfa: return "DT_MOVEENT";
211127808Snectar	case 0x6ffffdfb: return "DT_MOVESZ";
21290926Snectar	case 0x6ffffdfc: return "DT_FEATURE";
21390926Snectar	case 0x6ffffdfd: return "DT_POSFLAG_1";
21490926Snectar	case 0x6ffffdfe: return "DT_SYMINSZ";
215127808Snectar	case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)";
216127808Snectar	case 0x6ffffe00: return "DT_ADDRRNGLO";
217127808Snectar	case 0x6ffffef8: return "DT_GNU_CONFLICT";
218127808Snectar	case 0x6ffffef9: return "DT_GNU_LIBLIST";
219233294Sstas	case 0x6ffffefa: return "DT_SUNW_CONFIG";
220127808Snectar	case 0x6ffffefb: return "DT_SUNW_DEPAUDIT";
221127808Snectar	case 0x6ffffefc: return "DT_SUNW_AUDIT";
222233294Sstas	case 0x6ffffefd: return "DT_SUNW_PLTPAD";
223178825Sdfr	case 0x6ffffefe: return "DT_SUNW_MOVETAB";
224127808Snectar	case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)";
225127808Snectar	case 0x6ffffff9: return "DT_RELACOUNT";
226127808Snectar	case 0x6ffffffa: return "DT_RELCOUNT";
227127808Snectar	case 0x6ffffffb: return "DT_FLAGS_1";
228127808Snectar	case 0x6ffffffc: return "DT_VERDEF";
229127808Snectar	case 0x6ffffffd: return "DT_VERDEFNUM";
230127808Snectar	case 0x6ffffffe: return "DT_VERNEED";
231127808Snectar	case 0x6fffffff: return "DT_VERNEEDNUM";
232178825Sdfr	case 0x6ffffff0: return "DT_GNU_VERSYM";
233178825Sdfr	/* 0x70000000 - 0x7fffffff processor-specific semantics */
234178825Sdfr	case 0x70000000: return "DT_IA64_PLT_RESERVE";
235178825Sdfr	case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
236127808Snectar	case 0x7ffffffe: return "DT_SUNW_USED";
237127808Snectar	case 0x7fffffff: return "DT_SUNW_FILTER";
23857416Smarkm	default: return "ERROR: TAG NOT DEFINED";
239127808Snectar	}
240233294Sstas};
241233294Sstas
242127808Snectarstatic const char *
243127808Snectare_machines(u_int mach)
244127808Snectar{
245127808Snectar	switch (mach) {
246127808Snectar	case EM_NONE:	return "EM_NONE";
24757416Smarkm	case EM_M32:	return "EM_M32";
248127808Snectar	case EM_SPARC:	return "EM_SPARC";
249127808Snectar	case EM_386:	return "EM_386";
250178825Sdfr	case EM_68K:	return "EM_68K";
251127808Snectar	case EM_88K:	return "EM_88K";
252127808Snectar	case EM_486:	return "EM_486";
25357416Smarkm	case EM_860:	return "EM_860";
25457416Smarkm	case EM_MIPS:	return "EM_MIPS";
255127808Snectar	case EM_IA_64:	return "EM_IA_64";
256127808Snectar	}
257233294Sstas	return "(unknown machine)";
258127808Snectar};
259127808Snectar
260233294Sstasconst char *e_types[] = {
26157416Smarkm	"ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE"
26257416Smarkm};
263120945Snectar
264127808Snectarconst char *ei_versions[] = {
265233294Sstas	"EV_NONE", "EV_CURRENT"
266178825Sdfr};
267233294Sstas
268233294Sstasconst char *ei_classes[] = {
269233294Sstas	"ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64"
27057416Smarkm};
271233294Sstas
272127808Snectarconst char *ei_data[] = {
273233294Sstas	"ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB"
274233294Sstas};
27557416Smarkm
276127808Snectarconst char *ei_abis[] = {
277127808Snectar	"ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX",
278127808Snectar	"ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS",
279127808Snectar	"ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD",
280233294Sstas	"ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD"
281127808Snectar};
282127808Snectar
283233294Sstasconst char *p_types[] = {
284233294Sstas	"PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE",
285233294Sstas	"PT_SHLIB", "PT_PHDR"
286233294Sstas};
28757416Smarkm
288233294Sstasconst char *p_flags[] = {
289127808Snectar	"", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R",
290127808Snectar	"PF_X|PF_W|PF_R"
291233294Sstas};
292233294Sstas
293102644Snectar/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
29457416Smarkmstatic const char *
295178825Sdfrsh_types(u_int64_t sht) {
29657416Smarkm	switch (sht) {
29757416Smarkm	case 0:	return "SHT_NULL";
29857416Smarkm	case 1: return "SHT_PROGBITS";
299178825Sdfr	case 2: return "SHT_SYMTAB";
30090926Snectar	case 3: return "SHT_STRTAB";
30190926Snectar	case 4: return "SHT_RELA";
30290926Snectar	case 5: return "SHT_HASH";
30390926Snectar	case 6: return "SHT_DYNAMIC";
30457416Smarkm	case 7: return "SHT_NOTE";
305178825Sdfr	case 8: return "SHT_NOBITS";
306178825Sdfr	case 9: return "SHT_REL";
307178825Sdfr	case 10: return "SHT_SHLIB";
308178825Sdfr	case 11: return "SHT_DYNSYM";
309178825Sdfr	case 14: return "SHT_INIT_ARRAY";
310233294Sstas	case 15: return "SHT_FINI_ARRAY";
311127808Snectar	case 16: return "SHT_PREINIT_ARRAY";
312233294Sstas	case 17: return "SHT_GROUP";
313233294Sstas	case 18: return "SHT_SYMTAB_SHNDX";
314127808Snectar	/* 0x60000000 - 0x6fffffff operating system-specific semantics */
315233294Sstas	case 0x6ffffff0: return "XXX:VERSYM";
316178825Sdfr	case 0x6ffffff7: return "SHT_GNU_LIBLIST";
317178825Sdfr	case 0x6ffffffc: return "XXX:VERDEF";
318127808Snectar	case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef";
319127808Snectar	case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed";
320127808Snectar	case 0x6fffffff: return "SHT_SUNW(GNU)_versym";
321127808Snectar	/* 0x70000000 - 0x7fffffff processor-specific semantics */
322127808Snectar	case 0x70000000: return "SHT_IA_64_EXT";
323127808Snectar	case 0x70000001: return "SHT_IA_64_UNWIND";
324178825Sdfr	case 0x7ffffffd: return "XXX:AUXILIARY";
325127808Snectar	case 0x7fffffff: return "XXX:FILTER";
326178825Sdfr	/* 0x80000000 - 0xffffffff application programs */
327178825Sdfr	default: return "ERROR: SHT NOT DEFINED";
328102644Snectar	}
329102644Snectar};
330102644Snectar
331178825Sdfrconst char *sh_flags[] = {
332127808Snectar	"", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR",
333127808Snectar	"SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR",
334127808Snectar	"SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR"
335127808Snectar};
336127808Snectar
337127808Snectarconst char *st_types[] = {
338178825Sdfr	"STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE"
339127808Snectar};
340127808Snectar
34172445Sassarconst char *st_bindings[] = {
342127808Snectar	"STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
343127808Snectar};
344178825Sdfr
345127808Snectarchar *dynstr;
346127808Snectarchar *shstrtab;
347142403Snectarchar *strtab;
348127808SnectarFILE *out;
349178825Sdfr
350127808Snectaru_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member);
351127808Snectaru_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member);
352178825Sdfru_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member);
353127808Snectaru_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member);
354127808Snectaru_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member);
355178825Sdfr
356233294Sstasvoid elf_print_ehdr(Elf32_Ehdr *e);
357127808Snectarvoid elf_print_phdr(Elf32_Ehdr *e, void *p);
358127808Snectarvoid elf_print_shdr(Elf32_Ehdr *e, void *sh);
359233294Sstasvoid elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str);
360178825Sdfrvoid elf_print_dynamic(Elf32_Ehdr *e, void *sh);
361178825Sdfrvoid elf_print_rel(Elf32_Ehdr *e, void *r);
362233294Sstasvoid elf_print_rela(Elf32_Ehdr *e, void *ra);
363233294Sstasvoid elf_print_interp(Elf32_Ehdr *e, void *p);
364233294Sstasvoid elf_print_got(Elf32_Ehdr *e, void *sh);
365102644Snectarvoid elf_print_hash(Elf32_Ehdr *e, void *sh);
36690926Snectarvoid elf_print_note(Elf32_Ehdr *e, void *sh);
36772445Sassar
36857416Smarkmvoid usage(void);
369233294Sstas
37057416Smarkmint
37157416Smarkmmain(int ac, char **av)
37257416Smarkm{
37357416Smarkm	u_int64_t phoff;
37457416Smarkm	u_int64_t shoff;
37557416Smarkm	u_int64_t phentsize;
376233294Sstas	u_int64_t phnum;
37757416Smarkm	u_int64_t shentsize;
378120945Snectar	u_int64_t shnum;
37990926Snectar	u_int64_t shstrndx;
38072445Sassar	u_int64_t offset;
38157416Smarkm	u_int64_t name;
38290926Snectar	u_int64_t type;
383233294Sstas	struct stat sb;
38490926Snectar	u_int flags;
38557416Smarkm	Elf32_Ehdr *e;
386233294Sstas	void *p;
38790926Snectar	void *sh;
38857416Smarkm	void *v;
38957416Smarkm	int fd;
390233294Sstas	int ch;
391142403Snectar	int i;
392142403Snectar
393142403Snectar	out = stdout;
394142403Snectar	flags = 0;
395233294Sstas	while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1)
396233294Sstas		switch (ch) {
397142403Snectar		case 'a':
398142403Snectar			flags = ED_ALL;
399142403Snectar			break;
400233294Sstas		case 'c':
401233294Sstas			flags |= ED_SHDR;
402233294Sstas			break;
403142403Snectar		case 'd':
404142403Snectar			flags |= ED_DYN;
405142403Snectar			break;
406142403Snectar		case 'e':
407142403Snectar			flags |= ED_EHDR;
408142403Snectar			break;
409142403Snectar		case 'i':
410142403Snectar			flags |= ED_INTERP;
411142403Snectar			break;
41257416Smarkm		case 'G':
413142403Snectar			flags |= ED_GOT;
414142403Snectar			break;
415142403Snectar		case 'h':
416142403Snectar			flags |= ED_HASH;
417142403Snectar			break;
418142403Snectar		case 'n':
419142403Snectar			flags |= ED_NOTE;
420233294Sstas			break;
421142403Snectar		case 'p':
42290926Snectar			flags |= ED_PHDR;
42390926Snectar			break;
42457416Smarkm		case 'r':
42590926Snectar			flags |= ED_REL;
42690926Snectar			break;
42757416Smarkm		case 's':
42857416Smarkm			flags |= ED_SYMTAB;
42957416Smarkm			break;
43057416Smarkm		case 'w':
43157416Smarkm			if ((out = fopen(optarg, "w")) == NULL)
43257416Smarkm				err(1, "%s", optarg);
43357416Smarkm			break;
43490926Snectar		case '?':
435233294Sstas		default:
436178825Sdfr			usage();
437178825Sdfr		}
438178825Sdfr	ac -= optind;
439178825Sdfr	av += optind;
440178825Sdfr	if (ac == 0 || flags == 0)
441178825Sdfr		usage();
44257416Smarkm	if ((fd = open(*av, O_RDONLY)) < 0 ||
44357416Smarkm	    fstat(fd, &sb) < 0)
44457416Smarkm		err(1, NULL);
44557416Smarkm	e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
44657416Smarkm	if (e == MAP_FAILED)
44757416Smarkm		err(1, NULL);
44857416Smarkm	if (!IS_ELF(*(Elf32_Ehdr *)e))
44957416Smarkm		errx(1, "not an elf file");
45057416Smarkm	phoff = elf_get_off(e, e, E_PHOFF);
45157416Smarkm	shoff = elf_get_off(e, e, E_SHOFF);
452233294Sstas	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
453178825Sdfr	phnum = elf_get_quarter(e, e, E_PHNUM);
45457416Smarkm	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
45557416Smarkm	shnum = elf_get_quarter(e, e, E_SHNUM);
45657416Smarkm	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
45757416Smarkm	p = (char *)e + phoff;
45857416Smarkm	sh = (char *)e + shoff;
459178825Sdfr	offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, SH_OFFSET);
460233294Sstas	shstrtab = (char *)e + offset;
461178825Sdfr	for (i = 0; (u_int64_t)i < shnum; i++) {
462178825Sdfr		name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME);
463178825Sdfr		offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET);
464178825Sdfr		if (strcmp(shstrtab + name, ".strtab") == 0)
465178825Sdfr			strtab = (char *)e + offset;
466178825Sdfr		if (strcmp(shstrtab + name, ".dynstr") == 0)
46757416Smarkm			dynstr = (char *)e + offset;
46878527Sassar	}
46978527Sassar	if (flags & ED_EHDR)
47078527Sassar		elf_print_ehdr(e);
47178527Sassar	if (flags & ED_PHDR)
47278527Sassar		elf_print_phdr(e, p);
47378527Sassar	if (flags & ED_SHDR)
47478527Sassar		elf_print_shdr(e, sh);
47578527Sassar	for (i = 0; (u_int64_t)i < phnum; i++) {
47657416Smarkm		v = (char *)p + i * phentsize;
47778527Sassar		type = elf_get_word(e, v, P_TYPE);
47857416Smarkm		switch (type) {
47957416Smarkm		case PT_INTERP:
48057416Smarkm			if (flags & ED_INTERP)
48157416Smarkm				elf_print_interp(e, v);
48257416Smarkm			break;
48357416Smarkm		case PT_NULL:
48457416Smarkm		case PT_LOAD:
48557416Smarkm		case PT_DYNAMIC:
486233294Sstas		case PT_NOTE:
487178825Sdfr		case PT_SHLIB:
48857416Smarkm		case PT_PHDR:
48957416Smarkm			break;
49057416Smarkm		}
491233294Sstas	}
49257416Smarkm	for (i = 0; (u_int64_t)i < shnum; i++) {
493127808Snectar		v = (char *)sh + i * shentsize;
494127808Snectar		type = elf_get_word(e, v, SH_TYPE);
495233294Sstas		switch (type) {
496127808Snectar		case SHT_SYMTAB:
49757416Smarkm			if (flags & ED_SYMTAB)
49872445Sassar				elf_print_symtab(e, v, strtab);
499102644Snectar			break;
50072445Sassar		case SHT_DYNAMIC:
50172445Sassar			if (flags & ED_DYN)
50272445Sassar				elf_print_dynamic(e, v);
503233294Sstas			break;
504233294Sstas		case SHT_RELA:
505102644Snectar			if (flags & ED_REL)
506142403Snectar				elf_print_rela(e, v);
50757416Smarkm			break;
50872445Sassar		case SHT_REL:
50972445Sassar			if (flags & ED_REL)
510233294Sstas				elf_print_rel(e, v);
51157416Smarkm			break;
512178825Sdfr		case SHT_NOTE:
513127808Snectar			name = elf_get_word(e, v, SH_NAME);
514178825Sdfr			if (flags & ED_NOTE &&
515127808Snectar			    strcmp(shstrtab + name, ".note.ABI-tag") == 0)
516127808Snectar				elf_print_note(e, v);
517178825Sdfr			break;
518127808Snectar		case SHT_DYNSYM:
51957416Smarkm			if (flags & ED_SYMTAB)
52090926Snectar				elf_print_symtab(e, v, dynstr);
521178825Sdfr			break;
522233294Sstas		case SHT_PROGBITS:
52390926Snectar			name = elf_get_word(e, v, SH_NAME);
52457416Smarkm			if (flags & ED_GOT &&
525102644Snectar			    strcmp(shstrtab + name, ".got") == 0)
52672445Sassar				elf_print_got(e, v);
52772445Sassar			break;
52872445Sassar		case SHT_HASH:
529233294Sstas			if (flags & ED_HASH)
530233294Sstas				elf_print_hash(e, v);
531233294Sstas			break;
532233294Sstas		case SHT_NULL:
533178825Sdfr		case SHT_STRTAB:
534233294Sstas		case SHT_NOBITS:
535233294Sstas		case SHT_SHLIB:
536233294Sstas			break;
537233294Sstas		}
538233294Sstas	}
539233294Sstas
540233294Sstas	return 0;
541178825Sdfr}
542127808Snectar
543127808Snectarvoid
544127808Snectarelf_print_ehdr(Elf32_Ehdr *e)
545127808Snectar{
546127808Snectar	u_int64_t class;
547127808Snectar	u_int64_t data;
548127808Snectar	u_int64_t osabi;
549233294Sstas	u_int64_t type;
550233294Sstas	u_int64_t machine;
551233294Sstas	u_int64_t version;
552127808Snectar	u_int64_t entry;
553233294Sstas	u_int64_t phoff;
554127808Snectar	u_int64_t shoff;
55578527Sassar	u_int64_t flags;
556102644Snectar	u_int64_t ehsize;
557233294Sstas	u_int64_t phentsize;
558233294Sstas	u_int64_t phnum;
55978527Sassar	u_int64_t shentsize;
56057416Smarkm	u_int64_t shnum;
561127808Snectar	u_int64_t shstrndx;
56257416Smarkm
56357416Smarkm	class = elf_get_byte(e, e, E_CLASS);
564178825Sdfr	data = elf_get_byte(e, e, E_DATA);
565178825Sdfr	osabi = elf_get_byte(e, e, E_OSABI);
566178825Sdfr	type = elf_get_quarter(e, e, E_TYPE);
567178825Sdfr	machine = elf_get_quarter(e, e, E_MACHINE);
568178825Sdfr	version = elf_get_word(e, e, E_VERSION);
569178825Sdfr	entry = elf_get_addr(e, e, E_ENTRY);
570178825Sdfr	phoff = elf_get_off(e, e, E_PHOFF);
571178825Sdfr	shoff = elf_get_off(e, e, E_SHOFF);
572178825Sdfr	flags = elf_get_word(e, e, E_FLAGS);
573178825Sdfr	ehsize = elf_get_quarter(e, e, E_EHSIZE);
574178825Sdfr	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
575178825Sdfr	phnum = elf_get_quarter(e, e, E_PHNUM);
576102644Snectar	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
57757416Smarkm	shnum = elf_get_quarter(e, e, E_SHNUM);
578178825Sdfr	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
579233294Sstas	fprintf(out, "\nelf header:\n");
580233294Sstas	fprintf(out, "\n");
581233294Sstas	fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data],
582102644Snectar	    ei_abis[osabi]);
583233294Sstas	fprintf(out, "\te_type: %s\n", e_types[type]);
584233294Sstas	fprintf(out, "\te_machine: %s\n", e_machines(machine));
585102644Snectar	fprintf(out, "\te_version: %s\n", ei_versions[version]);
586233294Sstas	fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry);
58757416Smarkm	fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff);
588233294Sstas	fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff);
589233294Sstas	fprintf(out, "\te_flags: %jd\n", (intmax_t)flags);
59072445Sassar	fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize);
59157416Smarkm	fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize);
59257416Smarkm	fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum);
593233294Sstas	fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize);
59457416Smarkm	fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum);
595142403Snectar	fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx);
596178825Sdfr}
59757416Smarkm
598233294Sstasvoid
599233294Sstaself_print_phdr(Elf32_Ehdr *e, void *p)
600233294Sstas{
601233294Sstas	u_int64_t phentsize;
602233294Sstas	u_int64_t phnum;
603233294Sstas	u_int64_t type;
604233294Sstas	u_int64_t offset;
605233294Sstas	u_int64_t vaddr;
606233294Sstas	u_int64_t paddr;
607233294Sstas	u_int64_t filesz;
608233294Sstas	u_int64_t memsz;
609233294Sstas	u_int64_t flags;
610233294Sstas	u_int64_t align;
61190926Snectar	void *v;
612233294Sstas	int i;
613233294Sstas
614178825Sdfr	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
615178825Sdfr	phnum = elf_get_quarter(e, e, E_PHNUM);
616233294Sstas	fprintf(out, "\nprogram header:\n");
61790926Snectar	for (i = 0; (u_int64_t)i < phnum; i++) {
61857416Smarkm		v = (char *)p + i * phentsize;
61957416Smarkm		type = elf_get_word(e, v, P_TYPE);
62057416Smarkm		offset = elf_get_off(e, v, P_OFFSET);
62190926Snectar		vaddr = elf_get_addr(e, v, P_VADDR);
622127808Snectar		paddr = elf_get_addr(e, v, P_PADDR);
62390926Snectar		filesz = elf_get_size(e, v, P_FILESZ);
62457416Smarkm		memsz = elf_get_size(e, v, P_MEMSZ);
62557416Smarkm		flags = elf_get_word(e, v, P_FLAGS);
62657416Smarkm		align = elf_get_size(e, v, P_ALIGN);
62790926Snectar		fprintf(out, "\n");
62890926Snectar		fprintf(out, "entry: %d\n", i);
62990926Snectar		fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]);
63090926Snectar		fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset);
63157416Smarkm		fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr);
63257416Smarkm		fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr);
63390926Snectar		fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz);
63457416Smarkm		fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz);
63557416Smarkm		fprintf(out, "\tp_flags: %s\n", p_flags[flags]);
63657416Smarkm		fprintf(out, "\tp_align: %jd\n", (intmax_t)align);
63790926Snectar	}
63890926Snectar}
63957416Smarkm
64090926Snectarvoid
641127808Snectarelf_print_shdr(Elf32_Ehdr *e, void *sh)
64290926Snectar{
64390926Snectar	u_int64_t shentsize;
64457416Smarkm	u_int64_t shnum;
64557416Smarkm	u_int64_t name;
64657416Smarkm	u_int64_t type;
64757416Smarkm	u_int64_t flags;
64857416Smarkm	u_int64_t addr;
649178825Sdfr	u_int64_t offset;
650233294Sstas	u_int64_t size;
65157416Smarkm	u_int64_t shlink;
65257416Smarkm	u_int64_t info;
65390926Snectar	u_int64_t addralign;
65490926Snectar	u_int64_t entsize;
65590926Snectar	void *v;
65657416Smarkm	int i;
65790926Snectar
65857416Smarkm	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
65990926Snectar	shnum = elf_get_quarter(e, e, E_SHNUM);
660127808Snectar	fprintf(out, "\nsection header:\n");
661178825Sdfr	for (i = 0; (u_int64_t)i < shnum; i++) {
66257416Smarkm		v = (char *)sh + i * shentsize;
66390926Snectar		name = elf_get_word(e, v, SH_NAME);
66457416Smarkm		type = elf_get_word(e, v, SH_TYPE);
66590926Snectar		flags = elf_get_word(e, v, SH_FLAGS);
66657416Smarkm		addr = elf_get_addr(e, v, SH_ADDR);
667142403Snectar		offset = elf_get_off(e, v, SH_OFFSET);
668142403Snectar		size = elf_get_size(e, v, SH_SIZE);
669233294Sstas		shlink = elf_get_word(e, v, SH_LINK);
670233294Sstas		info = elf_get_word(e, v, SH_INFO);
67190926Snectar		addralign = elf_get_size(e, v, SH_ADDRALIGN);
67257416Smarkm		entsize = elf_get_size(e, v, SH_ENTSIZE);
67390926Snectar		fprintf(out, "\n");
67490926Snectar		fprintf(out, "entry: %d\n", i);
675120945Snectar		fprintf(out, "\tsh_name: %s\n", shstrtab + name);
676120945Snectar		fprintf(out, "\tsh_type: %s\n", sh_types(type));
677120945Snectar		fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]);
678178825Sdfr		fprintf(out, "\tsh_addr: %#jx\n", addr);
679178825Sdfr		fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset);
680233294Sstas		fprintf(out, "\tsh_size: %jd\n", (intmax_t)size);
681233294Sstas		fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink);
68290926Snectar		fprintf(out, "\tsh_info: %jd\n", (intmax_t)info);
68390926Snectar		fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign);
68490926Snectar		fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize);
685178825Sdfr	}
686178825Sdfr}
687233294Sstas
688233294Sstasvoid
68990926Snectarelf_print_symtab(Elf32_Ehdr *e, void *sh, char *str)
69090926Snectar{
691233294Sstas	u_int64_t offset;
692233294Sstas	u_int64_t entsize;
69390926Snectar	u_int64_t size;
69490926Snectar	u_int64_t name;
695178825Sdfr	u_int64_t value;
696178825Sdfr	u_int64_t info;
697233294Sstas	u_int64_t shndx;
698233294Sstas	void *st;
699178825Sdfr	int len;
700178825Sdfr	int i;
701233294Sstas
702233294Sstas	offset = elf_get_off(e, sh, SH_OFFSET);
70390926Snectar	entsize = elf_get_size(e, sh, SH_ENTSIZE);
70490926Snectar	size = elf_get_size(e, sh, SH_SIZE);
70557416Smarkm	name = elf_get_word(e, sh, SH_NAME);
706127808Snectar	len = size / entsize;
70790926Snectar	fprintf(out, "\nsymbol table (%s):\n", shstrtab + name);
70857416Smarkm	for (i = 0; i < len; i++) {
70990926Snectar		st = (char *)e + offset + i * entsize;
71057416Smarkm		name = elf_get_word(e, st, ST_NAME);
71190926Snectar		value = elf_get_addr(e, st, ST_VALUE);
71290926Snectar		size = elf_get_size(e, st, ST_SIZE);
713127808Snectar		info = elf_get_byte(e, st, ST_INFO);
714127808Snectar		shndx = elf_get_quarter(e, st, ST_SHNDX);
715127808Snectar		fprintf(out, "\n");
716127808Snectar		fprintf(out, "entry: %d\n", i);
717127808Snectar		fprintf(out, "\tst_name: %s\n", str + name);
718127808Snectar		fprintf(out, "\tst_value: %#jx\n", value);
719127808Snectar		fprintf(out, "\tst_size: %jd\n", (intmax_t)size);
720127808Snectar		fprintf(out, "\tst_info: %s %s\n",
721178825Sdfr		    st_types[ELF32_ST_TYPE(info)],
722178825Sdfr		    st_bindings[ELF32_ST_BIND(info)]);
723178825Sdfr		fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx);
724233294Sstas	}
725233294Sstas}
726233294Sstas
72790926Snectarvoid
728178825Sdfrelf_print_dynamic(Elf32_Ehdr *e, void *sh)
729178825Sdfr{
730178825Sdfr	u_int64_t offset;
731178825Sdfr	u_int64_t entsize;
732178825Sdfr	u_int64_t size;
733178825Sdfr	int64_t tag;
734178825Sdfr	u_int64_t ptr;
735178825Sdfr	u_int64_t val;
736178825Sdfr	void *d;
737178825Sdfr	int i;
738178825Sdfr
739178825Sdfr	offset = elf_get_off(e, sh, SH_OFFSET);
740178825Sdfr	entsize = elf_get_size(e, sh, SH_ENTSIZE);
741178825Sdfr	size = elf_get_size(e, sh, SH_SIZE);
74290926Snectar	fprintf(out, "\ndynamic:\n");
74390926Snectar	for (i = 0; (u_int64_t)i < size / entsize; i++) {
74457416Smarkm		d = (char *)e + offset + i * entsize;
74557416Smarkm		tag = elf_get_size(e, d, D_TAG);
74657416Smarkm		ptr = elf_get_size(e, d, D_PTR);
74757416Smarkm		val = elf_get_addr(e, d, D_VAL);
74857416Smarkm		fprintf(out, "\n");
74972445Sassar		fprintf(out, "entry: %d\n", i);
75072445Sassar		fprintf(out, "\td_tag: %s\n", d_tags(tag));
75172445Sassar		switch (tag) {
75272445Sassar		case DT_NEEDED:
75357416Smarkm		case DT_SONAME:
75457416Smarkm		case DT_RPATH:
75557416Smarkm			fprintf(out, "\td_val: %s\n", dynstr + val);
756178825Sdfr			break;
757178825Sdfr		case DT_PLTRELSZ:
75857416Smarkm		case DT_RELA:
75957416Smarkm		case DT_RELASZ:
76057416Smarkm		case DT_RELAENT:
76157416Smarkm		case DT_STRSZ:
76257416Smarkm		case DT_SYMENT:
76357416Smarkm		case DT_RELSZ:
76472445Sassar		case DT_RELENT:
76572445Sassar		case DT_PLTREL:
76657416Smarkm			fprintf(out, "\td_val: %jd\n", (intmax_t)val);
767178825Sdfr			break;
768178825Sdfr		case DT_PLTGOT:
769178825Sdfr		case DT_HASH:
770178825Sdfr		case DT_STRTAB:
771178825Sdfr		case DT_SYMTAB:
772178825Sdfr		case DT_INIT:
773178825Sdfr		case DT_FINI:
774178825Sdfr		case DT_REL:
775178825Sdfr		case DT_JMPREL:
776178825Sdfr			fprintf(out, "\td_ptr: %#jx\n", ptr);
777178825Sdfr			break;
77857416Smarkm		case DT_NULL:
77957416Smarkm		case DT_SYMBOLIC:
78057416Smarkm		case DT_DEBUG:
781102644Snectar		case DT_TEXTREL:
782102644Snectar			break;
783178825Sdfr		}
784178825Sdfr	}
785102644Snectar}
786102644Snectar
787102644Snectarvoid
788102644Snectarelf_print_rela(Elf32_Ehdr *e, void *sh)
789102644Snectar{
790102644Snectar	u_int64_t offset;
791178825Sdfr	u_int64_t entsize;
792102644Snectar	u_int64_t size;
793102644Snectar	u_int64_t name;
794102644Snectar	u_int64_t info;
795102644Snectar	int64_t addend;
796102644Snectar	void *ra;
797102644Snectar	void *v;
798102644Snectar	int i;
799102644Snectar
800102644Snectar	offset = elf_get_off(e, sh, SH_OFFSET);
801102644Snectar	entsize = elf_get_size(e, sh, SH_ENTSIZE);
802102644Snectar	size = elf_get_size(e, sh, SH_SIZE);
803102644Snectar	name = elf_get_word(e, sh, SH_NAME);
804102644Snectar	v = (char *)e + offset;
805102644Snectar	fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name);
806102644Snectar	for (i = 0; (u_int64_t)i < size / entsize; i++) {
807178825Sdfr		ra = (char *)v + i * entsize;
808102644Snectar		offset = elf_get_addr(e, ra, RA_OFFSET);
809102644Snectar		info = elf_get_word(e, ra, RA_INFO);
810102644Snectar		addend = elf_get_off(e, ra, RA_ADDEND);
811102644Snectar		fprintf(out, "\n");
812233294Sstas		fprintf(out, "entry: %d\n", i);
813233294Sstas		fprintf(out, "\tr_offset: %#jx\n", offset);
814233294Sstas		fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
81557416Smarkm		fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend);
81657416Smarkm	}
81757416Smarkm}
81857416Smarkm
81957416Smarkmvoid
82057416Smarkmelf_print_rel(Elf32_Ehdr *e, void *sh)
82157416Smarkm{
82257416Smarkm	u_int64_t offset;
82357416Smarkm	u_int64_t entsize;
82457416Smarkm	u_int64_t size;
82557416Smarkm	u_int64_t name;
82657416Smarkm	u_int64_t info;
82757416Smarkm	void *r;
82857416Smarkm	void *v;
82957416Smarkm	int i;
83057416Smarkm
83157416Smarkm	offset = elf_get_off(e, sh, SH_OFFSET);
83257416Smarkm	entsize = elf_get_size(e, sh, SH_ENTSIZE);
83357416Smarkm	size = elf_get_size(e, sh, SH_SIZE);
83457416Smarkm	name = elf_get_word(e, sh, SH_NAME);
83557416Smarkm	v = (char *)e + offset;
83657416Smarkm	fprintf(out, "\nrelocation (%s):\n", shstrtab + name);
83757416Smarkm	for (i = 0; (u_int64_t)i < size / entsize; i++) {
83857416Smarkm		r = (char *)v + i * entsize;
83957416Smarkm		offset = elf_get_addr(e, r, R_OFFSET);
84057416Smarkm		info = elf_get_word(e, r, R_INFO);
84157416Smarkm		fprintf(out, "\n");
84257416Smarkm		fprintf(out, "entry: %d\n", i);
84357416Smarkm		fprintf(out, "\tr_offset: %#jx\n", offset);
84457416Smarkm		fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
84557416Smarkm	}
84657416Smarkm}
84757416Smarkm
84857416Smarkmvoid
84957416Smarkmelf_print_interp(Elf32_Ehdr *e, void *p)
85057416Smarkm{
85157416Smarkm	u_int64_t offset;
85257416Smarkm	char *s;
85357416Smarkm
85457416Smarkm	offset = elf_get_off(e, p, P_OFFSET);
85557416Smarkm	s = (char *)e + offset;
85657416Smarkm	fprintf(out, "\ninterp:\n");
85757416Smarkm	fprintf(out, "\t%s\n", s);
85857416Smarkm}
85957416Smarkm
86057416Smarkmvoid
86157416Smarkmelf_print_got(Elf32_Ehdr *e, void *sh)
86257416Smarkm{
86357416Smarkm	u_int64_t offset;
86457416Smarkm	u_int64_t addralign;
86557416Smarkm	u_int64_t size;
86657416Smarkm	u_int64_t addr;
86757416Smarkm	void *v;
86857416Smarkm	int i;
86957416Smarkm
87057416Smarkm	offset = elf_get_off(e, sh, SH_OFFSET);
87157416Smarkm	addralign = elf_get_size(e, sh, SH_ADDRALIGN);
87257416Smarkm	size = elf_get_size(e, sh, SH_SIZE);
87357416Smarkm	v = (char *)e + offset;
87457416Smarkm	fprintf(out, "\nglobal offset table:\n");
87557416Smarkm	for (i = 0; (u_int64_t)i < size / addralign; i++) {
87657416Smarkm		addr = elf_get_addr(e, (char *)v + i * addralign, 0);
87757416Smarkm		fprintf(out, "\n");
87857416Smarkm		fprintf(out, "entry: %d\n", i);
87972445Sassar		fprintf(out, "\t%#jx\n", addr);
880178825Sdfr	}
88157416Smarkm}
882178825Sdfr
883178825Sdfrvoid
884178825Sdfrelf_print_hash(Elf32_Ehdr *e __unused, void *sh __unused)
885120945Snectar{
886178825Sdfr}
88757416Smarkm
88857416Smarkmvoid
88957416Smarkmelf_print_note(Elf32_Ehdr *e, void *sh)
89057416Smarkm{
89157416Smarkm	u_int64_t offset;
89257416Smarkm	u_int64_t size;
893178825Sdfr	u_int64_t name;
894178825Sdfr	u_int32_t namesz;
895178825Sdfr	u_int32_t descsz;
896178825Sdfr	u_int32_t type;
897178825Sdfr	u_int32_t desc;
898178825Sdfr	char *n, *s;
899178825Sdfr
900233294Sstas	offset = elf_get_off(e, sh, SH_OFFSET);
901178825Sdfr	size = elf_get_size(e, sh, SH_SIZE);
902178825Sdfr	name = elf_get_word(e, sh, SH_NAME);
903178825Sdfr	n = (char *)e + offset;
904178825Sdfr	fprintf(out, "\nnote (%s):\n", shstrtab + name);
905178825Sdfr 	while (n < ((char *)e + offset + size)) {
906178825Sdfr		namesz = elf_get_word(e, n, N_NAMESZ);
907178825Sdfr		descsz = elf_get_word(e, n, N_DESCSZ);
908178825Sdfr		type = elf_get_word(e, n, N_TYPE);
909178825Sdfr 		s = n + sizeof(Elf_Note);
910178825Sdfr 		desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0);
911178825Sdfr		fprintf(out, "\t%s %d\n", s, desc);
912178825Sdfr		n += sizeof(Elf_Note) + namesz + descsz;
913178825Sdfr	}
91457416Smarkm}
91557416Smarkm
91657416Smarkmu_int64_t
917233294Sstaself_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member)
91857416Smarkm{
91957416Smarkm	u_int64_t val;
92057416Smarkm	u_char *p;
921
922	val = 0;
923	switch (e->e_ident[EI_CLASS]) {
924	case ELFCLASS32:
925		p = (char *)base + elf32_offsets[member];
926		val = *p;
927		break;
928	case ELFCLASS64:
929		p = (char *)base + elf64_offsets[member];
930		val = *p;
931		break;
932	case ELFCLASSNONE:
933		errx(1, "invalid class");
934	}
935
936	return val;
937}
938
939u_int64_t
940elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member)
941{
942	u_int64_t val;
943	u_char *p;
944
945	val = 0;
946	switch (e->e_ident[EI_CLASS]) {
947	case ELFCLASS32:
948		p = (char *)base + elf32_offsets[member];
949		switch (e->e_ident[EI_DATA]) {
950		case ELFDATA2MSB:
951			val = p[0] << 8 | p[1];
952			break;
953		case ELFDATA2LSB:
954			val = p[1] << 8 | p[0];
955			break;
956		case ELFDATANONE:
957			errx(1, "invalid data format");
958		}
959		break;
960	case ELFCLASS64:
961		p = (char *)base + elf64_offsets[member];
962		switch (e->e_ident[EI_DATA]) {
963		case ELFDATA2MSB:
964			val = p[0] << 8 | p[1];
965			break;
966		case ELFDATA2LSB:
967			val = p[1] << 8 | p[0];
968			break;
969		case ELFDATANONE:
970			errx(1, "invalid data format");
971		}
972		break;
973	case ELFCLASSNONE:
974		errx(1, "invalid class");
975	}
976
977	return val;
978}
979
980u_int64_t
981elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member)
982{
983	u_int64_t val;
984	u_char *p;
985
986	val = 0;
987	switch (e->e_ident[EI_CLASS]) {
988	case ELFCLASS32:
989		p = (char *)base + elf32_offsets[member];
990		switch (e->e_ident[EI_DATA]) {
991		case ELFDATA2MSB:
992			val = p[0] << 8 | p[1];
993			break;
994		case ELFDATA2LSB:
995			val = p[1] << 8 | p[0];
996			break;
997		case ELFDATANONE:
998			errx(1, "invalid data format");
999		}
1000		break;
1001	case ELFCLASS64:
1002		p = (char *)base + elf64_offsets[member];
1003		switch (e->e_ident[EI_DATA]) {
1004		case ELFDATA2MSB:
1005			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1006			break;
1007		case ELFDATA2LSB:
1008			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1009			break;
1010		case ELFDATANONE:
1011			errx(1, "invalid data format");
1012		}
1013		break;
1014	case ELFCLASSNONE:
1015		errx(1, "invalid class");
1016	}
1017
1018	return val;
1019}
1020
1021u_int64_t
1022elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member)
1023{
1024	u_int64_t val;
1025	u_char *p;
1026
1027	val = 0;
1028	switch (e->e_ident[EI_CLASS]) {
1029	case ELFCLASS32:
1030		p = (char *)base + elf32_offsets[member];
1031		switch (e->e_ident[EI_DATA]) {
1032		case ELFDATA2MSB:
1033			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1034			break;
1035		case ELFDATA2LSB:
1036			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1037			break;
1038		case ELFDATANONE:
1039			errx(1, "invalid data format");
1040		}
1041		break;
1042	case ELFCLASS64:
1043		p = (char *)base + elf64_offsets[member];
1044		switch (e->e_ident[EI_DATA]) {
1045		case ELFDATA2MSB:
1046			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1047			break;
1048		case ELFDATA2LSB:
1049			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1050			break;
1051		case ELFDATANONE:
1052			errx(1, "invalid data format");
1053		}
1054		break;
1055	case ELFCLASSNONE:
1056		errx(1, "invalid class");
1057	}
1058
1059	return val;
1060}
1061
1062u_int64_t
1063elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member)
1064{
1065	u_int64_t high;
1066	u_int64_t low;
1067	u_int64_t val;
1068	u_char *p;
1069
1070	val = 0;
1071	switch (e->e_ident[EI_CLASS]) {
1072	case ELFCLASS32:
1073		p = (char *)base + elf32_offsets[member];
1074		switch (e->e_ident[EI_DATA]) {
1075		case ELFDATA2MSB:
1076			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1077			break;
1078		case ELFDATA2LSB:
1079			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1080			break;
1081		case ELFDATANONE:
1082			errx(1, "invalid data format");
1083		}
1084		break;
1085	case ELFCLASS64:
1086		p = (char *)base + elf64_offsets[member];
1087		switch (e->e_ident[EI_DATA]) {
1088		case ELFDATA2MSB:
1089			high = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1090			low = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7];
1091			val = high << 32 | low;
1092			break;
1093		case ELFDATA2LSB:
1094			high = p[7] << 24 | p[6] << 16 | p[5] << 8 | p[4];
1095			low = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1096			val = high << 32 | low;
1097			break;
1098		case ELFDATANONE:
1099			errx(1, "invalid data format");
1100		}
1101		break;
1102	case ELFCLASSNONE:
1103		errx(1, "invalid class");
1104	}
1105
1106	return val;
1107}
1108
1109void
1110usage(void)
1111{
1112	fprintf(stderr, "usage: elfdump [-acdeiGhnprs] [-w file] filename\n");
1113	exit(1);
1114}
1115