elfdump.c revision 110252
1109313Sobrien/*-
2110252Sobrien * Copyright (c) 2003 David O'Brien.  All rights reserved.
3109313Sobrien * Copyright (c) 2001 Jake Burkholder
4109313Sobrien * All rights reserved.
5109313Sobrien *
6109313Sobrien * Redistribution and use in source and binary forms, with or without
7109313Sobrien * modification, are permitted provided that the following conditions
8109313Sobrien * are met:
9109313Sobrien * 1. Redistributions of source code must retain the above copyright
10109313Sobrien *    notice, this list of conditions and the following disclaimer.
11109313Sobrien * 2. Redistributions in binary form must reproduce the above copyright
12109313Sobrien *    notice, this list of conditions and the following disclaimer in the
13109313Sobrien *    documentation and/or other materials provided with the distribution.
14109313Sobrien *
15109313Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16109313Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17109313Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18109313Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19109313Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20109313Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21109313Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22109313Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23109313Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24109313Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25109313Sobrien * SUCH DAMAGE.
26109313Sobrien */
27109313Sobrien
28109313Sobrien#include <sys/cdefs.h>
29109313Sobrien__FBSDID("$FreeBSD: head/usr.bin/elfdump/elfdump.c 110252 2003-02-02 22:16:05Z obrien $");
30109313Sobrien
31109313Sobrien#include <sys/types.h>
32109313Sobrien#include <sys/elf32.h>
33109313Sobrien#include <sys/elf64.h>
34109313Sobrien#include <sys/mman.h>
35109313Sobrien#include <sys/stat.h>
36109313Sobrien#include <err.h>
37109313Sobrien#include <fcntl.h>
38109313Sobrien#include <stddef.h>
39109313Sobrien#include <stdio.h>
40109313Sobrien#include <stdlib.h>
41109313Sobrien#include <string.h>
42109313Sobrien#include <unistd.h>
43109313Sobrien
44109313Sobrien#define	ED_DYN		(1<<0)
45109313Sobrien#define	ED_EHDR		(1<<1)
46109313Sobrien#define	ED_GOT		(1<<2)
47109313Sobrien#define	ED_HASH		(1<<3)
48109313Sobrien#define	ED_INTERP	(1<<4)
49109313Sobrien#define	ED_NOTE		(1<<5)
50109313Sobrien#define	ED_PHDR		(1<<6)
51109313Sobrien#define	ED_REL		(1<<7)
52109313Sobrien#define	ED_SHDR		(1<<8)
53109313Sobrien#define	ED_SYMTAB	(1<<9)
54109313Sobrien#define	ED_ALL		((1<<10)-1)
55109313Sobrien
56109313Sobrien#define	elf_get_addr	elf_get_quad
57109313Sobrien#define	elf_get_off	elf_get_quad
58109313Sobrien#define	elf_get_size	elf_get_quad
59109313Sobrien
60109313Sobrienenum elf_member {
61109313Sobrien	D_TAG = 1, D_PTR, D_VAL,
62109313Sobrien
63109313Sobrien	E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY,
64109313Sobrien	E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE,
65109313Sobrien	E_SHNUM, E_SHSTRNDX,
66109313Sobrien
67109313Sobrien	N_NAMESZ, N_DESCSZ, N_TYPE,
68109313Sobrien
69109313Sobrien	P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS,
70109313Sobrien	P_ALIGN,
71109313Sobrien
72109313Sobrien	SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK,
73109313Sobrien	SH_INFO, SH_ADDRALIGN, SH_ENTSIZE,
74109313Sobrien
75109313Sobrien	ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX,
76109313Sobrien
77109313Sobrien	R_OFFSET, R_INFO,
78109313Sobrien
79109313Sobrien	RA_OFFSET, RA_INFO, RA_ADDEND
80109313Sobrien};
81109313Sobrien
82109313Sobrientypedef enum elf_member elf_member_t;
83109313Sobrien
84109313Sobrienint elf32_offsets[] = {
85109313Sobrien	0,
86109313Sobrien
87109313Sobrien	offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr),
88109313Sobrien	offsetof(Elf32_Dyn, d_un.d_val),
89109313Sobrien
90109313Sobrien	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
91109313Sobrien	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
92109313Sobrien	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
93109313Sobrien	offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine),
94109313Sobrien	offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry),
95109313Sobrien	offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff),
96109313Sobrien	offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize),
97109313Sobrien	offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum),
98109313Sobrien	offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum),
99109313Sobrien	offsetof(Elf32_Ehdr, e_shstrndx),
100109313Sobrien
101109313Sobrien	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
102109313Sobrien	offsetof(Elf_Note, n_type),
103109313Sobrien
104109313Sobrien	offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset),
105109313Sobrien	offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr),
106109313Sobrien	offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz),
107109313Sobrien	offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align),
108109313Sobrien
109109313Sobrien	offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type),
110109313Sobrien	offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr),
111109313Sobrien	offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size),
112109313Sobrien	offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info),
113109313Sobrien	offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize),
114109313Sobrien
115109313Sobrien	offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value),
116109313Sobrien	offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info),
117109313Sobrien	offsetof(Elf32_Sym, st_shndx),
118109313Sobrien
119109313Sobrien	offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info),
120109313Sobrien
121109313Sobrien	offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info),
122109313Sobrien	offsetof(Elf32_Rela, r_addend)
123109313Sobrien};
124109313Sobrien
125109313Sobrienint elf64_offsets[] = {
126109313Sobrien	0,
127109313Sobrien
128109313Sobrien	offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr),
129109313Sobrien	offsetof(Elf64_Dyn, d_un.d_val),
130109313Sobrien
131109313Sobrien	offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
132109313Sobrien	offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
133109313Sobrien	offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
134109313Sobrien	offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine),
135109313Sobrien	offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry),
136109313Sobrien	offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff),
137109313Sobrien	offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize),
138109313Sobrien	offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum),
139109313Sobrien	offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum),
140109313Sobrien	offsetof(Elf64_Ehdr, e_shstrndx),
141109313Sobrien
142109313Sobrien	offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
143109313Sobrien	offsetof(Elf_Note, n_type),
144109313Sobrien
145109313Sobrien	offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset),
146109313Sobrien	offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr),
147109313Sobrien	offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz),
148109313Sobrien	offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align),
149109313Sobrien
150109313Sobrien	offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type),
151109313Sobrien	offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr),
152109313Sobrien	offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size),
153109313Sobrien	offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info),
154109313Sobrien	offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize),
155109313Sobrien
156109313Sobrien	offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value),
157109313Sobrien	offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info),
158109313Sobrien	offsetof(Elf64_Sym, st_shndx),
159109313Sobrien
160109313Sobrien	offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info),
161109313Sobrien
162109313Sobrien	offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info),
163109313Sobrien	offsetof(Elf64_Rela, r_addend)
164109313Sobrien};
165109313Sobrien
166109332Sobrien/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
167109332Sobrienconst char *
168109332Sobriend_tags(u_int64_t tag) {
169109332Sobrien	switch (tag) {
170109332Sobrien	case 0: return "DT_NULL";
171109332Sobrien	case 1: return "DT_NEEDED";
172109332Sobrien	case 2: return "DT_PLTRELSZ";
173109332Sobrien	case 3: return "DT_PLTGOT";
174109332Sobrien	case 4: return "DT_HASH";
175109332Sobrien	case 5: return "DT_STRTAB";
176109332Sobrien	case 6: return "DT_SYMTAB";
177109332Sobrien	case 7: return "DT_RELA";
178109332Sobrien	case 8: return "DT_RELASZ";
179109332Sobrien	case 9: return "DT_RELAENT";
180109332Sobrien	case 10: return "DT_STRSZ";
181109332Sobrien	case 11: return "DT_SYMENT";
182109332Sobrien	case 12: return "DT_INIT";
183109332Sobrien	case 13: return "DT_FINI";
184109332Sobrien	case 14: return "DT_SONAME";
185109332Sobrien	case 15: return "DT_RPATH";
186109332Sobrien	case 16: return "DT_SYMBOLIC";
187109332Sobrien	case 17: return "DT_REL";
188109332Sobrien	case 18: return "DT_RELSZ";
189109332Sobrien	case 19: return "DT_RELENT";
190109332Sobrien	case 20: return "DT_PLTREL";
191109332Sobrien	case 21: return "DT_DEBUG";
192109332Sobrien	case 22: return "DT_TEXTREL";
193109332Sobrien	case 23: return "DT_JMPREL";
194109332Sobrien	case 24: return "DT_BIND_NOW";
195109332Sobrien	case 25: return "DT_INIT_ARRAY";
196109332Sobrien	case 26: return "DT_FINI_ARRAY";
197109332Sobrien	case 27: return "DT_INIT_ARRAYSZ";
198109332Sobrien	case 28: return "DT_FINI_ARRAYSZ";
199109332Sobrien	case 29: return "DT_RUNPATH";
200109332Sobrien	case 30: return "DT_FLAGS";
201109332Sobrien	case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */
202109332Sobrien	case 33: return "DT_PREINIT_ARRAYSZ";
203109332Sobrien	/* 0x6000000D - 0x6ffff000 operating system-specific semantics */
204109332Sobrien	case 0x6ffffdf5: return "DT_GNU_PRELINKED";
205109332Sobrien	case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
206109332Sobrien	case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
207109332Sobrien	case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
208109332Sobrien	case 0x6ffffdf9: return "DT_PLTPADSZ";
209109332Sobrien	case 0x6ffffdfa: return "DT_MOVEENT";
210109332Sobrien	case 0x6ffffdfb: return "DT_MOVESZ";
211109332Sobrien	case 0x6ffffdfc: return "DT_FEATURE";
212109332Sobrien	case 0x6ffffdfd: return "DT_POSFLAG_1";
213109332Sobrien	case 0x6ffffdfe: return "DT_SYMINSZ";
214109332Sobrien	case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)";
215109332Sobrien	case 0x6ffffe00: return "DT_ADDRRNGLO";
216109332Sobrien	case 0x6ffffef8: return "DT_GNU_CONFLICT";
217109332Sobrien	case 0x6ffffef9: return "DT_GNU_LIBLIST";
218109332Sobrien	case 0x6ffffefa: return "DT_SUNW_CONFIG";
219109332Sobrien	case 0x6ffffefb: return "DT_SUNW_DEPAUDIT";
220109332Sobrien	case 0x6ffffefc: return "DT_SUNW_AUDIT";
221109332Sobrien	case 0x6ffffefd: return "DT_SUNW_PLTPAD";
222109332Sobrien	case 0x6ffffefe: return "DT_SUNW_MOVETAB";
223109332Sobrien	case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)";
224109332Sobrien	case 0x6ffffff9: return "DT_RELACOUNT";
225109332Sobrien	case 0x6ffffffa: return "DT_RELCOUNT";
226109332Sobrien	case 0x6ffffffb: return "DT_FLAGS_1";
227109332Sobrien	case 0x6ffffffc: return "DT_VERDEF";
228109332Sobrien	case 0x6ffffffd: return "DT_VERDEFNUM";
229109332Sobrien	case 0x6ffffffe: return "DT_VERNEED";
230109332Sobrien	case 0x6fffffff: return "DT_VERNEEDNUM";
231109332Sobrien	case 0x6ffffff0: return "DT_GNU_VERSYM";
232109332Sobrien	/* 0x70000000 - 0x7fffffff processor-specific semantics */
233109457Smarcel	case 0x70000000: return "DT_IA64_PLT_RESERVE";
234109332Sobrien	case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
235109332Sobrien	case 0x7ffffffe: return "DT_SUNW_USED";
236109332Sobrien	case 0x7fffffff: return "DT_SUNW_FILTER";
237109332Sobrien	default: return "ERROR: TAG NOT DEFINED";
238109332Sobrien	}
239109313Sobrien};
240109313Sobrien
241109457Smarcelconst char *
242109457Smarcele_machines(u_int mach)
243109457Smarcel{
244109457Smarcel	switch (mach) {
245109457Smarcel	case EM_NONE:	return "EM_NONE";
246109457Smarcel	case EM_M32:	return "EM_M32";
247109457Smarcel	case EM_SPARC:	return "EM_SPARC";
248109457Smarcel	case EM_386:	return "EM_386";
249109457Smarcel	case EM_68K:	return "EM_68K";
250109457Smarcel	case EM_88K:	return "EM_88K";
251109457Smarcel	case EM_486:	return "EM_486";
252109457Smarcel	case EM_860:	return "EM_860";
253109457Smarcel	case EM_MIPS:	return "EM_MIPS";
254109457Smarcel	case EM_IA_64:	return "EM_IA_64";
255109457Smarcel	}
256109457Smarcel	return "(unknown machine)";
257109313Sobrien};
258109313Sobrien
259109313Sobrienchar *e_types[] = {
260109313Sobrien	"ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE"
261109313Sobrien};
262109313Sobrien
263109313Sobrienchar *ei_versions[] = {
264109313Sobrien	"EV_NONE", "EV_CURRENT"
265109313Sobrien};
266109313Sobrien
267109313Sobrienchar *ei_classes[] = {
268109313Sobrien	"ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64"
269109313Sobrien};
270109313Sobrien
271109313Sobrienchar *ei_data[] = {
272109313Sobrien	"ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB"
273109313Sobrien};
274109313Sobrien
275109313Sobrienchar *ei_abis[] = {
276109313Sobrien	"ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX",
277109313Sobrien	"ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS",
278109313Sobrien	"ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD",
279109313Sobrien	"ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD"
280109313Sobrien};
281109313Sobrien
282109313Sobrienchar *p_types[] = {
283109313Sobrien	"PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE",
284109313Sobrien	"PT_SHLIB", "PT_PHDR"
285109313Sobrien};
286109313Sobrien
287109313Sobrienchar *p_flags[] = {
288109313Sobrien	"", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R",
289109313Sobrien	"PF_X|PF_W|PF_R"
290109313Sobrien};
291109313Sobrien
292109329Sobrien/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
293109332Sobrienconst char *
294109332Sobriensh_types(u_int64_t sht) {
295109329Sobrien	switch (sht) {
296109329Sobrien	case 0:	return "SHT_NULL";
297109329Sobrien	case 1: return "SHT_PROGBITS";
298109329Sobrien	case 2: return "SHT_SYMTAB";
299109329Sobrien	case 3: return "SHT_STRTAB";
300109329Sobrien	case 4: return "SHT_RELA";
301109329Sobrien	case 5: return "SHT_HASH";
302109329Sobrien	case 6: return "SHT_DYNAMIC";
303109329Sobrien	case 7: return "SHT_NOTE";
304109329Sobrien	case 8: return "SHT_NOBITS";
305109329Sobrien	case 9: return "SHT_REL";
306109329Sobrien	case 10: return "SHT_SHLIB";
307109329Sobrien	case 11: return "SHT_DYNSYM";
308109329Sobrien	case 14: return "SHT_INIT_ARRAY";
309109329Sobrien	case 15: return "SHT_FINI_ARRAY";
310109329Sobrien	case 16: return "SHT_PREINIT_ARRAY";
311109329Sobrien	case 17: return "SHT_GROUP";
312109329Sobrien	case 18: return "SHT_SYMTAB_SHNDX";
313109332Sobrien	/* 0x60000000 - 0x6fffffff operating system-specific semantics */
314109329Sobrien	case 0x6ffffff0: return "XXX:VERSYM";
315109329Sobrien	case 0x6ffffff7: return "SHT_GNU_LIBLIST";
316109329Sobrien	case 0x6ffffffc: return "XXX:VERDEF";
317109329Sobrien	case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef";
318109329Sobrien	case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed";
319109329Sobrien	case 0x6fffffff: return "SHT_SUNW(GNU)_versym";
320109332Sobrien	/* 0x70000000 - 0x7fffffff processor-specific semantics */
321109457Smarcel	case 0x70000000: return "SHT_IA_64_EXT";
322109457Smarcel	case 0x70000001: return "SHT_IA_64_UNWIND";
323109329Sobrien	case 0x7ffffffd: return "XXX:AUXILIARY";
324109329Sobrien	case 0x7fffffff: return "XXX:FILTER";
325109332Sobrien	/* 0x80000000 - 0xffffffff application programs */
326109329Sobrien	default: return "ERROR: SHT NOT DEFINED";
327109329Sobrien	}
328109313Sobrien};
329109313Sobrien
330109313Sobrienchar *sh_flags[] = {
331109313Sobrien	"", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR",
332109313Sobrien	"SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR",
333109313Sobrien	"SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR"
334109313Sobrien};
335109313Sobrien
336109313Sobrienchar *st_types[] = {
337109313Sobrien	"STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE"
338109313Sobrien};
339109313Sobrien
340109313Sobrienchar *st_bindings[] = {
341109313Sobrien	"STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
342109313Sobrien};
343109313Sobrien
344109313Sobrienchar *dynstr;
345109313Sobrienchar *shstrtab;
346109313Sobrienchar *strtab;
347109313SobrienFILE *out;
348109313Sobrien
349109313Sobrienu_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member);
350109313Sobrienu_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member);
351109313Sobrienu_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member);
352109313Sobrienu_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member);
353109313Sobrienu_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member);
354109313Sobrien
355110252Sobrienvoid elf_print_ehdr(Elf32_Ehdr *e);
356110252Sobrienvoid elf_print_phdr(Elf32_Ehdr *e, void *p);
357110252Sobrienvoid elf_print_shdr(Elf32_Ehdr *e, void *sh);
358110252Sobrienvoid elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str);
359110252Sobrienvoid elf_print_dynamic(Elf32_Ehdr *e, void *sh);
360110252Sobrienvoid elf_print_rel(Elf32_Ehdr *e, void *r);
361110252Sobrienvoid elf_print_rela(Elf32_Ehdr *e, void *ra);
362110252Sobrienvoid elf_print_interp(Elf32_Ehdr *e, void *p);
363110252Sobrienvoid elf_print_got(Elf32_Ehdr *e, void *sh);
364110252Sobrienvoid elf_print_hash(Elf32_Ehdr *e, void *sh);
365110252Sobrienvoid elf_print_note(Elf32_Ehdr *e, void *sh);
366109313Sobrien
367109313Sobrienvoid usage(void);
368109313Sobrien
369109313Sobrienint
370109313Sobrienmain(int ac, char **av)
371109313Sobrien{
372109313Sobrien	u_int64_t phoff;
373109313Sobrien	u_int64_t shoff;
374109313Sobrien	u_int64_t phentsize;
375109313Sobrien	u_int64_t phnum;
376109313Sobrien	u_int64_t shentsize;
377109313Sobrien	u_int64_t shnum;
378109313Sobrien	u_int64_t shstrndx;
379109313Sobrien	u_int64_t offset;
380109313Sobrien	u_int64_t name;
381109313Sobrien	u_int64_t type;
382109313Sobrien	struct stat sb;
383109313Sobrien	u_int flags;
384110252Sobrien	Elf32_Ehdr *e;
385109313Sobrien	void *p;
386109313Sobrien	void *sh;
387109313Sobrien	void *v;
388109313Sobrien	int fd;
389109313Sobrien	int ch;
390109313Sobrien	int i;
391109313Sobrien
392109313Sobrien	out = stdout;
393109313Sobrien	flags = 0;
394109313Sobrien	while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1)
395109313Sobrien		switch (ch) {
396109313Sobrien		case 'a':
397109313Sobrien			flags = ED_ALL;
398109313Sobrien			break;
399109313Sobrien		case 'c':
400109313Sobrien			flags |= ED_SHDR;
401109313Sobrien			break;
402109313Sobrien		case 'd':
403109313Sobrien			flags |= ED_DYN;
404109313Sobrien			break;
405109313Sobrien		case 'e':
406109313Sobrien			flags |= ED_EHDR;
407109313Sobrien			break;
408109313Sobrien		case 'i':
409109313Sobrien			flags |= ED_INTERP;
410109313Sobrien			break;
411109313Sobrien		case 'G':
412109313Sobrien			flags |= ED_GOT;
413109313Sobrien			break;
414109313Sobrien		case 'h':
415109313Sobrien			flags |= ED_HASH;
416109313Sobrien			break;
417109313Sobrien		case 'n':
418109313Sobrien			flags |= ED_NOTE;
419109313Sobrien			break;
420109313Sobrien		case 'p':
421109313Sobrien			flags |= ED_PHDR;
422109313Sobrien			break;
423109313Sobrien		case 'r':
424109313Sobrien			flags |= ED_REL;
425109313Sobrien			break;
426109313Sobrien		case 's':
427109313Sobrien			flags |= ED_SYMTAB;
428109313Sobrien			break;
429109313Sobrien		case 'w':
430109313Sobrien			if ((out = fopen(optarg, "w")) == NULL)
431109313Sobrien				err(1, "%s", optarg);
432109313Sobrien			break;
433109313Sobrien		case '?':
434109313Sobrien		default:
435109313Sobrien			usage();
436109313Sobrien		}
437109313Sobrien	ac -= optind;
438109313Sobrien	av += optind;
439109313Sobrien	if (ac == 0 || flags == 0)
440109313Sobrien		usage();
441109313Sobrien	if ((fd = open(*av, O_RDONLY)) < 0 ||
442109313Sobrien	    fstat(fd, &sb) < 0)
443109313Sobrien		err(1, NULL);
444109313Sobrien	e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
445109313Sobrien	if (e == MAP_FAILED)
446109313Sobrien		err(1, NULL);
447109313Sobrien	if (!IS_ELF(*(Elf32_Ehdr *)e))
448109313Sobrien		errx(1, "not an elf file");
449109313Sobrien	phoff = elf_get_off(e, e, E_PHOFF);
450109313Sobrien	shoff = elf_get_off(e, e, E_SHOFF);
451109313Sobrien	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
452109313Sobrien	phnum = elf_get_quarter(e, e, E_PHNUM);
453109313Sobrien	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
454109313Sobrien	shnum = elf_get_quarter(e, e, E_SHNUM);
455109313Sobrien	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
456110252Sobrien	p = (void *)e + phoff;
457110252Sobrien	sh = (void *)e + shoff;
458109313Sobrien	offset = elf_get_off(e, sh + shstrndx * shentsize, SH_OFFSET);
459110252Sobrien	shstrtab = (char *)e + offset;
460109313Sobrien	for (i = 0; i < shnum; i++) {
461109313Sobrien		name = elf_get_word(e, sh + i * shentsize, SH_NAME);
462109313Sobrien		offset = elf_get_off(e, sh + i * shentsize, SH_OFFSET);
463109313Sobrien		if (strcmp(shstrtab + name, ".strtab") == 0)
464110252Sobrien			strtab = (char *)e + offset;
465109313Sobrien		if (strcmp(shstrtab + name, ".dynstr") == 0)
466110252Sobrien			dynstr = (char *)e + offset;
467109313Sobrien	}
468109313Sobrien	if (flags & ED_EHDR)
469109313Sobrien		elf_print_ehdr(e);
470109313Sobrien	if (flags & ED_PHDR)
471109313Sobrien		elf_print_phdr(e, p);
472109313Sobrien	if (flags & ED_SHDR)
473109313Sobrien		elf_print_shdr(e, sh);
474109313Sobrien	for (i = 0; i < phnum; i++) {
475109313Sobrien		v = p + i * phentsize;
476109313Sobrien		type = elf_get_word(e, v, P_TYPE);
477109313Sobrien		switch (type) {
478109313Sobrien		case PT_INTERP:
479109313Sobrien			if (flags & ED_INTERP)
480109313Sobrien				elf_print_interp(e, v);
481109313Sobrien			break;
482109313Sobrien		case PT_NULL:
483109313Sobrien		case PT_LOAD:
484109313Sobrien		case PT_DYNAMIC:
485109313Sobrien		case PT_NOTE:
486109313Sobrien		case PT_SHLIB:
487109313Sobrien		case PT_PHDR:
488109313Sobrien			break;
489109313Sobrien		}
490109313Sobrien	}
491109313Sobrien	for (i = 0; i < shnum; i++) {
492109313Sobrien		v = sh + i * shentsize;
493109313Sobrien		type = elf_get_word(e, v, SH_TYPE);
494109313Sobrien		switch (type) {
495109313Sobrien		case SHT_SYMTAB:
496109313Sobrien			if (flags & ED_SYMTAB)
497109313Sobrien				elf_print_symtab(e, v, strtab);
498109313Sobrien			break;
499109313Sobrien		case SHT_DYNAMIC:
500109313Sobrien			if (flags & ED_DYN)
501109313Sobrien				elf_print_dynamic(e, v);
502109313Sobrien			break;
503109313Sobrien		case SHT_RELA:
504109313Sobrien			if (flags & ED_REL)
505109313Sobrien				elf_print_rela(e, v);
506109313Sobrien			break;
507109313Sobrien		case SHT_REL:
508109313Sobrien			if (flags & ED_REL)
509109313Sobrien				elf_print_rel(e, v);
510109313Sobrien			break;
511109313Sobrien		case SHT_NOTE:
512109313Sobrien			name = elf_get_word(e, v, SH_NAME);
513109313Sobrien			if (flags & ED_NOTE &&
514109313Sobrien			    strcmp(shstrtab + name, ".note.ABI-tag") == 0)
515109313Sobrien				elf_print_note(e, v);
516109313Sobrien			break;
517109313Sobrien		case SHT_DYNSYM:
518109313Sobrien			if (flags & ED_SYMTAB)
519109313Sobrien				elf_print_symtab(e, v, dynstr);
520109313Sobrien			break;
521109313Sobrien		case SHT_PROGBITS:
522109313Sobrien			name = elf_get_word(e, v, SH_NAME);
523109313Sobrien			if (flags & ED_GOT &&
524109313Sobrien			    strcmp(shstrtab + name, ".got") == 0)
525109313Sobrien				elf_print_got(e, v);
526109313Sobrien			break;
527109313Sobrien		case SHT_HASH:
528109313Sobrien			if (flags & ED_HASH)
529109313Sobrien				elf_print_hash(e, v);
530109313Sobrien			break;
531109313Sobrien		case SHT_NULL:
532109313Sobrien		case SHT_STRTAB:
533109313Sobrien		case SHT_NOBITS:
534109313Sobrien		case SHT_SHLIB:
535109313Sobrien			break;
536109313Sobrien		}
537109313Sobrien	}
538109313Sobrien
539109313Sobrien	return 0;
540109313Sobrien}
541109313Sobrien
542109313Sobrienvoid
543110252Sobrienelf_print_ehdr(Elf32_Ehdr *e)
544109313Sobrien{
545109313Sobrien	u_int64_t class;
546109313Sobrien	u_int64_t data;
547109313Sobrien	u_int64_t osabi;
548109313Sobrien	u_int64_t type;
549109313Sobrien	u_int64_t machine;
550109313Sobrien	u_int64_t version;
551109313Sobrien	u_int64_t entry;
552109313Sobrien	u_int64_t phoff;
553109313Sobrien	u_int64_t shoff;
554109313Sobrien	u_int64_t flags;
555109313Sobrien	u_int64_t ehsize;
556109313Sobrien	u_int64_t phentsize;
557109313Sobrien	u_int64_t phnum;
558109313Sobrien	u_int64_t shentsize;
559109313Sobrien	u_int64_t shnum;
560109313Sobrien	u_int64_t shstrndx;
561109313Sobrien
562109313Sobrien	class = elf_get_byte(e, e, E_CLASS);
563109313Sobrien	data = elf_get_byte(e, e, E_DATA);
564109313Sobrien	osabi = elf_get_byte(e, e, E_OSABI);
565109313Sobrien	type = elf_get_quarter(e, e, E_TYPE);
566109313Sobrien	machine = elf_get_quarter(e, e, E_MACHINE);
567109313Sobrien	version = elf_get_word(e, e, E_VERSION);
568109313Sobrien	entry = elf_get_addr(e, e, E_ENTRY);
569109313Sobrien	phoff = elf_get_off(e, e, E_PHOFF);
570109313Sobrien	shoff = elf_get_off(e, e, E_SHOFF);
571109313Sobrien	flags = elf_get_word(e, e, E_FLAGS);
572109313Sobrien	ehsize = elf_get_quarter(e, e, E_EHSIZE);
573109313Sobrien	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
574109313Sobrien	phnum = elf_get_quarter(e, e, E_PHNUM);
575109313Sobrien	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
576109313Sobrien	shnum = elf_get_quarter(e, e, E_SHNUM);
577109313Sobrien	shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
578109313Sobrien	fprintf(out, "\nelf header:\n");
579109313Sobrien	fprintf(out, "\n");
580109313Sobrien	fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data],
581109313Sobrien	    ei_abis[osabi]);
582109313Sobrien	fprintf(out, "\te_type: %s\n", e_types[type]);
583109457Smarcel	fprintf(out, "\te_machine: %s\n", e_machines(machine));
584109313Sobrien	fprintf(out, "\te_version: %s\n", ei_versions[version]);
585109313Sobrien	fprintf(out, "\te_entry: %#llx\n", entry);
586109313Sobrien	fprintf(out, "\te_phoff: %lld\n", phoff);
587109313Sobrien	fprintf(out, "\te_shoff: %lld\n", shoff);
588109313Sobrien	fprintf(out, "\te_flags: %lld\n", flags);
589109313Sobrien	fprintf(out, "\te_ehsize: %lld\n", ehsize);
590109313Sobrien	fprintf(out, "\te_phentsize: %lld\n", phentsize);
591109313Sobrien	fprintf(out, "\te_phnum: %lld\n", phnum);
592109313Sobrien	fprintf(out, "\te_shentsize: %lld\n", shentsize);
593109313Sobrien	fprintf(out, "\te_shnum: %lld\n", shnum);
594109313Sobrien	fprintf(out, "\te_shstrndx: %lld\n", shstrndx);
595109313Sobrien}
596109313Sobrien
597109313Sobrienvoid
598110252Sobrienelf_print_phdr(Elf32_Ehdr *e, void *p)
599109313Sobrien{
600109313Sobrien	u_int64_t phentsize;
601109313Sobrien	u_int64_t phnum;
602109313Sobrien	u_int64_t type;
603109313Sobrien	u_int64_t offset;
604109313Sobrien	u_int64_t vaddr;
605109313Sobrien	u_int64_t paddr;
606109313Sobrien	u_int64_t filesz;
607109313Sobrien	u_int64_t memsz;
608109313Sobrien	u_int64_t flags;
609109313Sobrien	u_int64_t align;
610109313Sobrien	void *v;
611109313Sobrien	int i;
612109313Sobrien
613109313Sobrien	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
614109313Sobrien	phnum = elf_get_quarter(e, e, E_PHNUM);
615109313Sobrien	fprintf(out, "\nprogram header:\n");
616109313Sobrien	for (i = 0; i < phnum; i++) {
617109313Sobrien		v = p + i * phentsize;
618109313Sobrien		type = elf_get_word(e, v, P_TYPE);
619109313Sobrien		offset = elf_get_off(e, v, P_OFFSET);
620109313Sobrien		vaddr = elf_get_addr(e, v, P_VADDR);
621109313Sobrien		paddr = elf_get_addr(e, v, P_PADDR);
622109313Sobrien		filesz = elf_get_size(e, v, P_FILESZ);
623109313Sobrien		memsz = elf_get_size(e, v, P_MEMSZ);
624109313Sobrien		flags = elf_get_word(e, v, P_FLAGS);
625109313Sobrien		align = elf_get_size(e, v, P_ALIGN);
626109313Sobrien		fprintf(out, "\n");
627109313Sobrien		fprintf(out, "entry: %d\n", i);
628109313Sobrien		fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]);
629109313Sobrien		fprintf(out, "\tp_offset: %lld\n", offset);
630109313Sobrien		fprintf(out, "\tp_vaddr: %#llx\n", vaddr);
631109313Sobrien		fprintf(out, "\tp_paddr: %#llx\n", paddr);
632109313Sobrien		fprintf(out, "\tp_filesz: %lld\n", filesz);
633109313Sobrien		fprintf(out, "\tp_memsz: %lld\n", memsz);
634109313Sobrien		fprintf(out, "\tp_flags: %s\n", p_flags[flags]);
635109313Sobrien		fprintf(out, "\tp_align: %lld\n", align);
636109313Sobrien	}
637109313Sobrien}
638109313Sobrien
639109313Sobrienvoid
640110252Sobrienelf_print_shdr(Elf32_Ehdr *e, void *sh)
641109313Sobrien{
642109313Sobrien	u_int64_t shentsize;
643109313Sobrien	u_int64_t shnum;
644109313Sobrien	u_int64_t name;
645109313Sobrien	u_int64_t type;
646109313Sobrien	u_int64_t flags;
647109313Sobrien	u_int64_t addr;
648109313Sobrien	u_int64_t offset;
649109313Sobrien	u_int64_t size;
650109313Sobrien	u_int64_t link;
651109313Sobrien	u_int64_t info;
652109313Sobrien	u_int64_t addralign;
653109313Sobrien	u_int64_t entsize;
654109313Sobrien	void *v;
655109313Sobrien	int i;
656109313Sobrien
657109313Sobrien	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
658109313Sobrien	shnum = elf_get_quarter(e, e, E_SHNUM);
659109313Sobrien	fprintf(out, "\nsection header:\n");
660109313Sobrien	for (i = 0; i < shnum; i++) {
661109313Sobrien		v = sh + i * shentsize;
662109313Sobrien		name = elf_get_word(e, v, SH_NAME);
663109313Sobrien		type = elf_get_word(e, v, SH_TYPE);
664109313Sobrien		flags = elf_get_word(e, v, SH_FLAGS);
665109313Sobrien		addr = elf_get_addr(e, v, SH_ADDR);
666109313Sobrien		offset = elf_get_off(e, v, SH_OFFSET);
667109313Sobrien		size = elf_get_size(e, v, SH_SIZE);
668109313Sobrien		link = elf_get_word(e, v, SH_LINK);
669109313Sobrien		info = elf_get_word(e, v, SH_INFO);
670109313Sobrien		addralign = elf_get_size(e, v, SH_ADDRALIGN);
671109313Sobrien		entsize = elf_get_size(e, v, SH_ENTSIZE);
672109313Sobrien		fprintf(out, "\n");
673109313Sobrien		fprintf(out, "entry: %d\n", i);
674109313Sobrien		fprintf(out, "\tsh_name: %s\n", shstrtab + name);
675109329Sobrien		fprintf(out, "\tsh_type: %s\n", sh_types(type));
676109313Sobrien		fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]);
677109313Sobrien		fprintf(out, "\tsh_addr: %#llx\n", addr);
678109313Sobrien		fprintf(out, "\tsh_offset: %lld\n", offset);
679109313Sobrien		fprintf(out, "\tsh_size: %lld\n", size);
680109313Sobrien		fprintf(out, "\tsh_link: %lld\n", link);
681109313Sobrien		fprintf(out, "\tsh_info: %lld\n", info);
682109313Sobrien		fprintf(out, "\tsh_addralign: %lld\n", addralign);
683109313Sobrien		fprintf(out, "\tsh_entsize: %lld\n", entsize);
684109313Sobrien	}
685109313Sobrien}
686109313Sobrien
687109313Sobrienvoid
688110252Sobrienelf_print_symtab(Elf32_Ehdr *e, void *sh, char *str)
689109313Sobrien{
690109313Sobrien	u_int64_t offset;
691109313Sobrien	u_int64_t entsize;
692109313Sobrien	u_int64_t size;
693109313Sobrien	u_int64_t name;
694109313Sobrien	u_int64_t value;
695109313Sobrien	u_int64_t info;
696109313Sobrien	u_int64_t shndx;
697109313Sobrien	void *st;
698109313Sobrien	int len;
699109313Sobrien	int i;
700109313Sobrien
701109313Sobrien	offset = elf_get_off(e, sh, SH_OFFSET);
702109313Sobrien	entsize = elf_get_size(e, sh, SH_ENTSIZE);
703109313Sobrien	size = elf_get_size(e, sh, SH_SIZE);
704109313Sobrien	name = elf_get_word(e, sh, SH_NAME);
705109313Sobrien	len = size / entsize;
706109313Sobrien	fprintf(out, "\nsymbol table (%s):\n", shstrtab + name);
707109313Sobrien	for (i = 0; i < len; i++) {
708110252Sobrien		st = (void *)e + offset + i * entsize;
709109313Sobrien		name = elf_get_word(e, st, ST_NAME);
710109313Sobrien		value = elf_get_addr(e, st, ST_VALUE);
711109313Sobrien		size = elf_get_size(e, st, ST_SIZE);
712109313Sobrien		info = elf_get_byte(e, st, ST_INFO);
713109313Sobrien		shndx = elf_get_quarter(e, st, ST_SHNDX);
714109313Sobrien		fprintf(out, "\n");
715109313Sobrien		fprintf(out, "entry: %d\n", i);
716109313Sobrien		fprintf(out, "\tst_name: %s\n", str + name);
717109313Sobrien		fprintf(out, "\tst_value: %#llx\n", value);
718109313Sobrien		fprintf(out, "\tst_size: %lld\n", size);
719109313Sobrien		fprintf(out, "\tst_info: %s %s\n",
720109313Sobrien		    st_types[ELF32_ST_TYPE(info)],
721109313Sobrien		    st_bindings[ELF32_ST_BIND(info)]);
722109313Sobrien		fprintf(out, "\tst_shndx: %lld\n", shndx);
723109313Sobrien	}
724109313Sobrien}
725109313Sobrien
726109313Sobrienvoid
727110252Sobrienelf_print_dynamic(Elf32_Ehdr *e, void *sh)
728109313Sobrien{
729109313Sobrien	u_int64_t offset;
730109313Sobrien	u_int64_t entsize;
731109313Sobrien	u_int64_t size;
732109313Sobrien	int64_t tag;
733109313Sobrien	u_int64_t ptr;
734109313Sobrien	u_int64_t val;
735109313Sobrien	void *d;
736109313Sobrien	int i;
737109313Sobrien
738109313Sobrien	offset = elf_get_off(e, sh, SH_OFFSET);
739109313Sobrien	entsize = elf_get_size(e, sh, SH_ENTSIZE);
740109313Sobrien	size = elf_get_size(e, sh, SH_SIZE);
741109313Sobrien	fprintf(out, "\ndynamic:\n");
742109313Sobrien	for (i = 0; i < size / entsize; i++) {
743110252Sobrien		d = (void *)e + offset + i * entsize;
744109313Sobrien		tag = elf_get_size(e, d, D_TAG);
745109313Sobrien		ptr = elf_get_size(e, d, D_PTR);
746109313Sobrien		val = elf_get_addr(e, d, D_VAL);
747109313Sobrien		fprintf(out, "\n");
748109313Sobrien		fprintf(out, "entry: %d\n", i);
749109332Sobrien		fprintf(out, "\td_tag: %s\n", d_tags(tag));
750109313Sobrien		switch (tag) {
751109313Sobrien		case DT_NEEDED:
752109313Sobrien		case DT_SONAME:
753109313Sobrien		case DT_RPATH:
754109313Sobrien			fprintf(out, "\td_val: %s\n", dynstr + val);
755109313Sobrien			break;
756109313Sobrien		case DT_PLTRELSZ:
757109313Sobrien		case DT_RELA:
758109313Sobrien		case DT_RELASZ:
759109313Sobrien		case DT_RELAENT:
760109313Sobrien		case DT_STRSZ:
761109313Sobrien		case DT_SYMENT:
762109313Sobrien		case DT_RELSZ:
763109313Sobrien		case DT_RELENT:
764109313Sobrien		case DT_PLTREL:
765109313Sobrien			fprintf(out, "\td_val: %lld\n", val);
766109313Sobrien			break;
767109313Sobrien		case DT_PLTGOT:
768109313Sobrien		case DT_HASH:
769109313Sobrien		case DT_STRTAB:
770109313Sobrien		case DT_SYMTAB:
771109313Sobrien		case DT_INIT:
772109313Sobrien		case DT_FINI:
773109313Sobrien		case DT_REL:
774109313Sobrien		case DT_JMPREL:
775109313Sobrien			fprintf(out, "\td_ptr: %#llx\n", ptr);
776109313Sobrien			break;
777109313Sobrien		case DT_NULL:
778109313Sobrien		case DT_SYMBOLIC:
779109313Sobrien		case DT_DEBUG:
780109313Sobrien		case DT_TEXTREL:
781109313Sobrien			break;
782109313Sobrien		}
783109313Sobrien	}
784109313Sobrien}
785109313Sobrien
786109313Sobrienvoid
787110252Sobrienelf_print_rela(Elf32_Ehdr *e, void *sh)
788109313Sobrien{
789109313Sobrien	u_int64_t offset;
790109313Sobrien	u_int64_t entsize;
791109313Sobrien	u_int64_t size;
792109313Sobrien	u_int64_t name;
793109313Sobrien	u_int64_t info;
794109313Sobrien	int64_t addend;
795109313Sobrien	void *ra;
796109313Sobrien	void *v;
797109313Sobrien	int i;
798109313Sobrien
799109313Sobrien	offset = elf_get_off(e, sh, SH_OFFSET);
800109313Sobrien	entsize = elf_get_size(e, sh, SH_ENTSIZE);
801109313Sobrien	size = elf_get_size(e, sh, SH_SIZE);
802109313Sobrien	name = elf_get_word(e, sh, SH_NAME);
803110252Sobrien	v = (void *)e + offset;
804109313Sobrien	fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name);
805109313Sobrien	for (i = 0; i < size / entsize; i++) {
806109313Sobrien		ra = v + i * entsize;
807109313Sobrien		offset = elf_get_addr(e, ra, RA_OFFSET);
808109313Sobrien		info = elf_get_word(e, ra, RA_INFO);
809109313Sobrien		addend = elf_get_off(e, ra, RA_ADDEND);
810109313Sobrien		fprintf(out, "\n");
811109313Sobrien		fprintf(out, "entry: %d\n", i);
812109313Sobrien		fprintf(out, "\tr_offset: %#llx\n", offset);
813109313Sobrien		fprintf(out, "\tr_info: %lld\n", info);
814109313Sobrien		fprintf(out, "\tr_addend: %lld\n", addend);
815109313Sobrien	}
816109313Sobrien}
817109313Sobrien
818109313Sobrienvoid
819110252Sobrienelf_print_rel(Elf32_Ehdr *e, void *sh)
820109313Sobrien{
821109313Sobrien	u_int64_t offset;
822109313Sobrien	u_int64_t entsize;
823109313Sobrien	u_int64_t size;
824109313Sobrien	u_int64_t name;
825109313Sobrien	u_int64_t info;
826109313Sobrien	void *r;
827109313Sobrien	void *v;
828109313Sobrien	int i;
829109313Sobrien
830109313Sobrien	offset = elf_get_off(e, sh, SH_OFFSET);
831109313Sobrien	entsize = elf_get_size(e, sh, SH_ENTSIZE);
832109313Sobrien	size = elf_get_size(e, sh, SH_SIZE);
833109313Sobrien	name = elf_get_word(e, sh, SH_NAME);
834109313Sobrien	v = e + offset;
835109313Sobrien	fprintf(out, "\nrelocation (%s):\n", shstrtab + name);
836109313Sobrien	for (i = 0; i < size / entsize; i++) {
837109313Sobrien		r = v + i * entsize;
838109313Sobrien		offset = elf_get_addr(e, r, R_OFFSET);
839109313Sobrien		info = elf_get_word(e, r, R_INFO);
840109313Sobrien		fprintf(out, "\n");
841109313Sobrien		fprintf(out, "entry: %d\n", i);
842109313Sobrien		fprintf(out, "\tr_offset: %#llx\n", offset);
843109313Sobrien		fprintf(out, "\tr_info: %lld\n", info);
844109313Sobrien	}
845109313Sobrien}
846109313Sobrien
847109313Sobrienvoid
848110252Sobrienelf_print_interp(Elf32_Ehdr *e, void *p)
849109313Sobrien{
850109313Sobrien	u_int64_t offset;
851109313Sobrien	char *s;
852109313Sobrien
853109313Sobrien	offset = elf_get_off(e, p, P_OFFSET);
854110252Sobrien	s = (char *)e + offset;
855109313Sobrien	fprintf(out, "\ninterp:\n");
856109313Sobrien	fprintf(out, "\t%s\n", s);
857109313Sobrien}
858109313Sobrien
859109313Sobrienvoid
860110252Sobrienelf_print_got(Elf32_Ehdr *e, void *sh)
861109313Sobrien{
862109313Sobrien	u_int64_t offset;
863109313Sobrien	u_int64_t addralign;
864109313Sobrien	u_int64_t size;
865109313Sobrien	u_int64_t addr;
866109313Sobrien	void *v;
867109313Sobrien	int i;
868109313Sobrien
869109313Sobrien	offset = elf_get_off(e, sh, SH_OFFSET);
870109313Sobrien	addralign = elf_get_size(e, sh, SH_ADDRALIGN);
871109313Sobrien	size = elf_get_size(e, sh, SH_SIZE);
872110252Sobrien	v = (void *)e + offset;
873109313Sobrien	fprintf(out, "\nglobal offset table:\n");
874109313Sobrien	for (i = 0; i < size / addralign; i++) {
875109313Sobrien		addr = elf_get_addr(e, v + i * addralign, 0);
876109313Sobrien		fprintf(out, "\n");
877109313Sobrien		fprintf(out, "entry: %d\n", i);
878109313Sobrien		fprintf(out, "\t%#llx\n", addr);
879109313Sobrien	}
880109313Sobrien}
881109313Sobrien
882109313Sobrienvoid
883110252Sobrienelf_print_hash(Elf32_Ehdr *e, void *sh)
884109313Sobrien{
885109313Sobrien}
886109313Sobrien
887109313Sobrienvoid
888110252Sobrienelf_print_note(Elf32_Ehdr *e, void *sh)
889109313Sobrien{
890109313Sobrien	u_int64_t offset;
891109313Sobrien	u_int64_t size;
892109313Sobrien	u_int64_t name;
893109313Sobrien	u_int32_t namesz;
894109313Sobrien	u_int32_t descsz;
895109313Sobrien	u_int32_t type;
896109313Sobrien	u_int32_t desc;
897109313Sobrien	char *s;
898109313Sobrien	void *n;
899109313Sobrien
900109313Sobrien	offset = elf_get_off(e, sh, SH_OFFSET);
901109313Sobrien	size = elf_get_size(e, sh, SH_SIZE);
902109313Sobrien	name = elf_get_word(e, sh, SH_NAME);
903110252Sobrien	n = (void *)e + offset;
904109313Sobrien	fprintf(out, "\nnote (%s):\n", shstrtab + name);
905110252Sobrien	while (n < (void *)e + offset + size) {
906109313Sobrien		namesz = elf_get_word(e, n, N_NAMESZ);
907109313Sobrien		descsz = elf_get_word(e, n, N_DESCSZ);
908109313Sobrien		type = elf_get_word(e, n, N_TYPE);
909109313Sobrien		s = n + sizeof(Elf_Note);
910109313Sobrien		desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0);
911109313Sobrien		fprintf(out, "\t%s %d\n", s, desc);
912109313Sobrien		n += sizeof(Elf_Note) + namesz + descsz;
913109313Sobrien	}
914109313Sobrien}
915109313Sobrien
916109313Sobrienu_int64_t
917109313Sobrienelf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member)
918109313Sobrien{
919109313Sobrien	u_int64_t val;
920109313Sobrien	u_char *p;
921109313Sobrien
922109313Sobrien	val = 0;
923109313Sobrien	switch (e->e_ident[EI_CLASS]) {
924109313Sobrien	case ELFCLASS32:
925109313Sobrien		p = base + elf32_offsets[member];
926109313Sobrien		val = *p;
927109313Sobrien		break;
928109313Sobrien	case ELFCLASS64:
929109313Sobrien		p = base + elf64_offsets[member];
930109313Sobrien		val = *p;
931109313Sobrien		break;
932109313Sobrien	case ELFCLASSNONE:
933109313Sobrien		errx(1, "invalid class");
934109313Sobrien	}
935109313Sobrien
936109313Sobrien	return val;
937109313Sobrien}
938109313Sobrien
939109313Sobrienu_int64_t
940109313Sobrienelf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member)
941109313Sobrien{
942109313Sobrien	u_int64_t val;
943109313Sobrien	u_char *p;
944109313Sobrien
945109313Sobrien	val = 0;
946109313Sobrien	switch (e->e_ident[EI_CLASS]) {
947109313Sobrien	case ELFCLASS32:
948109313Sobrien		p = base + elf32_offsets[member];
949109313Sobrien		switch (e->e_ident[EI_DATA]) {
950109313Sobrien		case ELFDATA2MSB:
951109313Sobrien			val = p[0] << 8 | p[1];
952109313Sobrien			break;
953109313Sobrien		case ELFDATA2LSB:
954109313Sobrien			val = p[1] << 8 | p[0];
955109313Sobrien			break;
956109313Sobrien		case ELFDATANONE:
957109313Sobrien			errx(1, "invalid data format");
958109313Sobrien		}
959109313Sobrien		break;
960109313Sobrien	case ELFCLASS64:
961109313Sobrien		p = base + elf64_offsets[member];
962109313Sobrien		switch (e->e_ident[EI_DATA]) {
963109313Sobrien		case ELFDATA2MSB:
964109313Sobrien			val = p[0] << 8 | p[1];
965109313Sobrien			break;
966109313Sobrien		case ELFDATA2LSB:
967109313Sobrien			val = p[1] << 8 | p[0];
968109313Sobrien			break;
969109313Sobrien		case ELFDATANONE:
970109313Sobrien			errx(1, "invalid data format");
971109313Sobrien		}
972109313Sobrien		break;
973109313Sobrien	case ELFCLASSNONE:
974109313Sobrien		errx(1, "invalid class");
975109313Sobrien	}
976109313Sobrien
977109313Sobrien	return val;
978109313Sobrien}
979109313Sobrien
980109313Sobrienu_int64_t
981109313Sobrienelf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member)
982109313Sobrien{
983109313Sobrien	u_int64_t val;
984109313Sobrien	u_char *p;
985109313Sobrien
986109313Sobrien	val = 0;
987109313Sobrien	switch (e->e_ident[EI_CLASS]) {
988109313Sobrien	case ELFCLASS32:
989109313Sobrien		p = base + elf32_offsets[member];
990109313Sobrien		switch (e->e_ident[EI_DATA]) {
991109313Sobrien		case ELFDATA2MSB:
992109313Sobrien			val = p[0] << 8 | p[1];
993109313Sobrien			break;
994109313Sobrien		case ELFDATA2LSB:
995109313Sobrien			val = p[1] << 8 | p[0];
996109313Sobrien			break;
997109313Sobrien		case ELFDATANONE:
998109313Sobrien			errx(1, "invalid data format");
999109313Sobrien		}
1000109313Sobrien		break;
1001109313Sobrien	case ELFCLASS64:
1002109313Sobrien		p = base + elf64_offsets[member];
1003109313Sobrien		switch (e->e_ident[EI_DATA]) {
1004109313Sobrien		case ELFDATA2MSB:
1005109313Sobrien			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1006109313Sobrien			break;
1007109313Sobrien		case ELFDATA2LSB:
1008109313Sobrien			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1009109313Sobrien			break;
1010109313Sobrien		case ELFDATANONE:
1011109313Sobrien			errx(1, "invalid data format");
1012109313Sobrien		}
1013109313Sobrien		break;
1014109313Sobrien	case ELFCLASSNONE:
1015109313Sobrien		errx(1, "invalid class");
1016109313Sobrien	}
1017109313Sobrien
1018109313Sobrien	return val;
1019109313Sobrien}
1020109313Sobrien
1021109313Sobrienu_int64_t
1022109313Sobrienelf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member)
1023109313Sobrien{
1024109313Sobrien	u_int64_t val;
1025109313Sobrien	u_char *p;
1026109313Sobrien
1027109313Sobrien	val = 0;
1028109313Sobrien	switch (e->e_ident[EI_CLASS]) {
1029109313Sobrien	case ELFCLASS32:
1030109313Sobrien		p = base + elf32_offsets[member];
1031109313Sobrien		switch (e->e_ident[EI_DATA]) {
1032109313Sobrien		case ELFDATA2MSB:
1033109313Sobrien			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1034109313Sobrien			break;
1035109313Sobrien		case ELFDATA2LSB:
1036109313Sobrien			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1037109313Sobrien			break;
1038109313Sobrien		case ELFDATANONE:
1039109313Sobrien			errx(1, "invalid data format");
1040109313Sobrien		}
1041109313Sobrien		break;
1042109313Sobrien	case ELFCLASS64:
1043109313Sobrien		p = base + elf64_offsets[member];
1044109313Sobrien		switch (e->e_ident[EI_DATA]) {
1045109313Sobrien		case ELFDATA2MSB:
1046109313Sobrien			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1047109313Sobrien			break;
1048109313Sobrien		case ELFDATA2LSB:
1049109313Sobrien			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1050109313Sobrien			break;
1051109313Sobrien		case ELFDATANONE:
1052109313Sobrien			errx(1, "invalid data format");
1053109313Sobrien		}
1054109313Sobrien		break;
1055109313Sobrien	case ELFCLASSNONE:
1056109313Sobrien		errx(1, "invalid class");
1057109313Sobrien	}
1058109313Sobrien
1059109313Sobrien	return val;
1060109313Sobrien}
1061109313Sobrien
1062109313Sobrienu_int64_t
1063109313Sobrienelf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member)
1064109313Sobrien{
1065109313Sobrien	u_int64_t high;
1066109313Sobrien	u_int64_t low;
1067109313Sobrien	u_int64_t val;
1068109313Sobrien	u_char *p;
1069109313Sobrien
1070109313Sobrien	val = 0;
1071109313Sobrien	switch (e->e_ident[EI_CLASS]) {
1072109313Sobrien	case ELFCLASS32:
1073109313Sobrien		p = base + elf32_offsets[member];
1074109313Sobrien		switch (e->e_ident[EI_DATA]) {
1075109313Sobrien		case ELFDATA2MSB:
1076109313Sobrien			val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1077109313Sobrien			break;
1078109313Sobrien		case ELFDATA2LSB:
1079109313Sobrien			val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1080109313Sobrien			break;
1081109313Sobrien		case ELFDATANONE:
1082109313Sobrien			errx(1, "invalid data format");
1083109313Sobrien		}
1084109313Sobrien		break;
1085109313Sobrien	case ELFCLASS64:
1086109313Sobrien		p = base + elf64_offsets[member];
1087109313Sobrien		switch (e->e_ident[EI_DATA]) {
1088109313Sobrien		case ELFDATA2MSB:
1089109313Sobrien			high = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
1090109313Sobrien			low = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7];
1091109313Sobrien			val = high << 32 | low;
1092109313Sobrien			break;
1093109313Sobrien		case ELFDATA2LSB:
1094109313Sobrien			high = p[7] << 24 | p[6] << 16 | p[5] << 8 | p[4];
1095109313Sobrien			low = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
1096109313Sobrien			val = high << 32 | low;
1097109313Sobrien			break;
1098109313Sobrien		case ELFDATANONE:
1099109313Sobrien			errx(1, "invalid data format");
1100109313Sobrien		}
1101109313Sobrien		break;
1102109313Sobrien	case ELFCLASSNONE:
1103109313Sobrien		errx(1, "invalid class");
1104109313Sobrien	}
1105109313Sobrien
1106109313Sobrien	return val;
1107109313Sobrien}
1108109313Sobrien
1109109313Sobrienvoid
1110109313Sobrienusage(void)
1111109313Sobrien{
1112109313Sobrien	fprintf(stderr, "usage: elfdump [-acdeiGhnprs] [-w file] filename\n");
1113109313Sobrien	exit(1);
1114109313Sobrien}
1115