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