1/*-
2 * Copyright (c) 2009-2015 Kai Wang
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/param.h>
28#include <sys/queue.h>
29
30#include <ar.h>
31#include <assert.h>
32#include <capsicum_helpers.h>
33#include <ctype.h>
34#include <dwarf.h>
35#include <err.h>
36#include <fcntl.h>
37#include <gelf.h>
38#include <getopt.h>
39#include <libdwarf.h>
40#include <libelftc.h>
41#include <libgen.h>
42#include <stdarg.h>
43#include <stdint.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <time.h>
48#include <unistd.h>
49
50#include <libcasper.h>
51#include <casper/cap_fileargs.h>
52
53#include "_elftc.h"
54
55ELFTC_VCSID("$Id: readelf.c 3769 2019-06-29 15:15:02Z emaste $");
56
57/* Backwards compatability for older FreeBSD releases. */
58#ifndef	STB_GNU_UNIQUE
59#define	STB_GNU_UNIQUE 10
60#endif
61#ifndef	STT_SPARC_REGISTER
62#define	STT_SPARC_REGISTER 13
63#endif
64
65
66/*
67 * readelf(1) options.
68 */
69#define	RE_AA	0x00000001
70#define	RE_C	0x00000002
71#define	RE_DD	0x00000004
72#define	RE_D	0x00000008
73#define	RE_G	0x00000010
74#define	RE_H	0x00000020
75#define	RE_II	0x00000040
76#define	RE_I	0x00000080
77#define	RE_L	0x00000100
78#define	RE_NN	0x00000200
79#define	RE_N	0x00000400
80#define	RE_P	0x00000800
81#define	RE_R	0x00001000
82#define	RE_SS	0x00002000
83#define	RE_S	0x00004000
84#define	RE_T	0x00008000
85#define	RE_U	0x00010000
86#define	RE_VV	0x00020000
87#define	RE_WW	0x00040000
88#define	RE_W	0x00080000
89#define	RE_X	0x00100000
90
91/*
92 * dwarf dump options.
93 */
94#define	DW_A	0x00000001
95#define	DW_FF	0x00000002
96#define	DW_F	0x00000004
97#define	DW_I	0x00000008
98#define	DW_LL	0x00000010
99#define	DW_L	0x00000020
100#define	DW_M	0x00000040
101#define	DW_O	0x00000080
102#define	DW_P	0x00000100
103#define	DW_RR	0x00000200
104#define	DW_R	0x00000400
105#define	DW_S	0x00000800
106
107#define	DW_DEFAULT_OPTIONS (DW_A | DW_F | DW_I | DW_L | DW_O | DW_P | \
108	    DW_R | DW_RR | DW_S)
109
110/*
111 * readelf(1) run control flags.
112 */
113#define	DISPLAY_FILENAME	0x0001
114
115/*
116 * Internal data structure for sections.
117 */
118struct section {
119	const char	*name;		/* section name */
120	Elf_Scn		*scn;		/* section scn */
121	uint64_t	 off;		/* section offset */
122	uint64_t	 sz;		/* section size */
123	uint64_t	 entsize;	/* section entsize */
124	uint64_t	 align;		/* section alignment */
125	uint64_t	 type;		/* section type */
126	uint64_t	 flags;		/* section flags */
127	uint64_t	 addr;		/* section virtual addr */
128	uint32_t	 link;		/* section link ndx */
129	uint32_t	 info;		/* section info ndx */
130};
131
132struct dumpop {
133	union {
134		size_t si;		/* section index */
135		const char *sn;		/* section name */
136	} u;
137	enum {
138		DUMP_BY_INDEX = 0,
139		DUMP_BY_NAME
140	} type;				/* dump type */
141#define HEX_DUMP	0x0001
142#define STR_DUMP	0x0002
143	int op;				/* dump operation */
144	STAILQ_ENTRY(dumpop) dumpop_list;
145};
146
147struct symver {
148	const char *name;
149	int type;
150};
151
152/*
153 * Structure encapsulates the global data for readelf(1).
154 */
155struct readelf {
156	const char	 *filename;	/* current processing file. */
157	int		  options;	/* command line options. */
158	int		  flags;	/* run control flags. */
159	int		  dop;		/* dwarf dump options. */
160	Elf		 *elf;		/* underlying ELF descriptor. */
161	Elf		 *ar;		/* archive ELF descriptor. */
162	Dwarf_Debug	  dbg;		/* DWARF handle. */
163	Dwarf_Half	  cu_psize;	/* DWARF CU pointer size. */
164	Dwarf_Half	  cu_osize;	/* DWARF CU offset size. */
165	Dwarf_Half	  cu_ver;	/* DWARF CU version. */
166	GElf_Ehdr	  ehdr;		/* ELF header. */
167	int		  ec;		/* ELF class. */
168	size_t		  shnum;	/* #sections. */
169	struct section	 *vd_s;		/* Verdef section. */
170	struct section	 *vn_s;		/* Verneed section. */
171	struct section	 *vs_s;		/* Versym section. */
172	uint16_t	 *vs;		/* Versym array. */
173	int		  vs_sz;	/* Versym array size. */
174	struct symver	 *ver;		/* Version array. */
175	int		  ver_sz;	/* Size of version array. */
176	struct section	 *sl;		/* list of sections. */
177	STAILQ_HEAD(, dumpop) v_dumpop; /* list of dump ops. */
178	uint64_t	(*dw_read)(Elf_Data *, uint64_t *, int);
179	uint64_t	(*dw_decode)(uint8_t **, int);
180};
181
182enum options
183{
184	OPTION_DEBUG_DUMP
185};
186
187static struct option longopts[] = {
188	{"all", no_argument, NULL, 'a'},
189	{"arch-specific", no_argument, NULL, 'A'},
190	{"archive-index", no_argument, NULL, 'c'},
191	{"debug-dump", optional_argument, NULL, OPTION_DEBUG_DUMP},
192	{"dynamic", no_argument, NULL, 'd'},
193	{"file-header", no_argument, NULL, 'h'},
194	{"full-section-name", no_argument, NULL, 'N'},
195	{"headers", no_argument, NULL, 'e'},
196	{"help", no_argument, 0, 'H'},
197	{"hex-dump", required_argument, NULL, 'x'},
198	{"histogram", no_argument, NULL, 'I'},
199	{"notes", no_argument, NULL, 'n'},
200	{"program-headers", no_argument, NULL, 'l'},
201	{"relocs", no_argument, NULL, 'r'},
202	{"sections", no_argument, NULL, 'S'},
203	{"section-headers", no_argument, NULL, 'S'},
204	{"section-groups", no_argument, NULL, 'g'},
205	{"section-details", no_argument, NULL, 't'},
206	{"segments", no_argument, NULL, 'l'},
207	{"string-dump", required_argument, NULL, 'p'},
208	{"symbols", no_argument, NULL, 's'},
209	{"syms", no_argument, NULL, 's'},
210	{"unwind", no_argument, NULL, 'u'},
211	{"use-dynamic", no_argument, NULL, 'D'},
212	{"version-info", no_argument, 0, 'V'},
213	{"version", no_argument, 0, 'v'},
214	{"wide", no_argument, 0, 'W'},
215	{NULL, 0, NULL, 0}
216};
217
218struct eflags_desc {
219	uint64_t flag;
220	const char *desc;
221};
222
223struct flag_desc {
224	uint64_t flag;
225	const char *desc;
226};
227
228struct mips_option {
229	uint64_t flag;
230	const char *desc;
231};
232
233struct loc_at {
234	Dwarf_Attribute la_at;
235	Dwarf_Unsigned la_off;
236	Dwarf_Unsigned la_lowpc;
237	Dwarf_Half la_cu_psize;
238	Dwarf_Half la_cu_osize;
239	Dwarf_Half la_cu_ver;
240};
241
242static void add_dumpop(struct readelf *re, size_t si, const char *sn, int op,
243    int t);
244static const char *aeabi_adv_simd_arch(uint64_t simd);
245static const char *aeabi_align_needed(uint64_t an);
246static const char *aeabi_align_preserved(uint64_t ap);
247static const char *aeabi_arm_isa(uint64_t ai);
248static const char *aeabi_cpu_arch(uint64_t arch);
249static const char *aeabi_cpu_arch_profile(uint64_t pf);
250static const char *aeabi_div(uint64_t du);
251static const char *aeabi_enum_size(uint64_t es);
252static const char *aeabi_fp_16bit_format(uint64_t fp16);
253static const char *aeabi_fp_arch(uint64_t fp);
254static const char *aeabi_fp_denormal(uint64_t fd);
255static const char *aeabi_fp_exceptions(uint64_t fe);
256static const char *aeabi_fp_hpext(uint64_t fh);
257static const char *aeabi_fp_number_model(uint64_t fn);
258static const char *aeabi_fp_optm_goal(uint64_t fog);
259static const char *aeabi_fp_rounding(uint64_t fr);
260static const char *aeabi_hardfp(uint64_t hfp);
261static const char *aeabi_mpext(uint64_t mp);
262static const char *aeabi_optm_goal(uint64_t og);
263static const char *aeabi_pcs_config(uint64_t pcs);
264static const char *aeabi_pcs_got(uint64_t got);
265static const char *aeabi_pcs_r9(uint64_t r9);
266static const char *aeabi_pcs_ro(uint64_t ro);
267static const char *aeabi_pcs_rw(uint64_t rw);
268static const char *aeabi_pcs_wchar_t(uint64_t wt);
269static const char *aeabi_t2ee(uint64_t t2ee);
270static const char *aeabi_thumb_isa(uint64_t ti);
271static const char *aeabi_fp_user_exceptions(uint64_t fu);
272static const char *aeabi_unaligned_access(uint64_t ua);
273static const char *aeabi_vfp_args(uint64_t va);
274static const char *aeabi_virtual(uint64_t vt);
275static const char *aeabi_wmmx_arch(uint64_t wmmx);
276static const char *aeabi_wmmx_args(uint64_t wa);
277static const char *elf_class(unsigned int class);
278static const char *elf_endian(unsigned int endian);
279static const char *elf_machine(unsigned int mach);
280static const char *elf_osabi(unsigned int abi);
281static const char *elf_type(unsigned int type);
282static const char *elf_ver(unsigned int ver);
283static const char *dt_type(unsigned int mach, unsigned int dtype);
284static void dump_ar(struct readelf *re, int);
285static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe);
286static void dump_attributes(struct readelf *re);
287static uint8_t *dump_compatibility_tag(uint8_t *p, uint8_t *pe);
288static void dump_dwarf(struct readelf *re);
289static void dump_dwarf_abbrev(struct readelf *re);
290static void dump_dwarf_aranges(struct readelf *re);
291static void dump_dwarf_block(struct readelf *re, uint8_t *b,
292    Dwarf_Unsigned len);
293static void dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level);
294static void dump_dwarf_frame(struct readelf *re, int alt);
295static void dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie,
296    uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf,
297    Dwarf_Addr pc, Dwarf_Debug dbg);
298static int dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde,
299    Dwarf_Addr pc, Dwarf_Unsigned func_len, Dwarf_Half cie_ra);
300static void dump_dwarf_frame_section(struct readelf *re, struct section *s,
301    int alt);
302static void dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info);
303static void dump_dwarf_macinfo(struct readelf *re);
304static void dump_dwarf_line(struct readelf *re);
305static void dump_dwarf_line_decoded(struct readelf *re);
306static void dump_dwarf_loc(struct readelf *re, Dwarf_Loc *lr);
307static void dump_dwarf_loclist(struct readelf *re);
308static void dump_dwarf_pubnames(struct readelf *re);
309static void dump_dwarf_ranges(struct readelf *re);
310static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die,
311    Dwarf_Addr base);
312static void dump_dwarf_str(struct readelf *re);
313static void dump_eflags(struct readelf *re, uint64_t e_flags);
314static void dump_elf(struct readelf *re);
315static void dump_flags(struct flag_desc *fd, uint64_t flags);
316static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab);
317static void dump_dynamic(struct readelf *re);
318static void dump_liblist(struct readelf *re);
319static void dump_mips_abiflags(struct readelf *re, struct section *s);
320static void dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe);
321static void dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz);
322static void dump_mips_options(struct readelf *re, struct section *s);
323static void dump_mips_option_flags(const char *name, struct mips_option *opt,
324    uint64_t info);
325static void dump_mips_reginfo(struct readelf *re, struct section *s);
326static void dump_mips_specific_info(struct readelf *re);
327static void dump_notes(struct readelf *re);
328static void dump_notes_content(struct readelf *re, const char *buf, size_t sz,
329    off_t off);
330static void dump_notes_data(struct readelf *re, const char *name,
331    uint32_t type, const char *buf, size_t sz);
332static void dump_svr4_hash(struct section *s);
333static void dump_svr4_hash64(struct readelf *re, struct section *s);
334static void dump_gnu_hash(struct readelf *re, struct section *s);
335static void dump_gnu_property_type_0(struct readelf *re, const char *buf,
336    size_t sz);
337static void dump_hash(struct readelf *re);
338static void dump_phdr(struct readelf *re);
339static void dump_ppc_attributes(uint8_t *p, uint8_t *pe);
340static void dump_section_groups(struct readelf *re);
341static void dump_symtab(struct readelf *re, int i);
342static void dump_symtabs(struct readelf *re);
343static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe);
344static void dump_ver(struct readelf *re);
345static void dump_verdef(struct readelf *re, int dump);
346static void dump_verneed(struct readelf *re, int dump);
347static void dump_versym(struct readelf *re);
348static const char *dwarf_reg(unsigned int mach, unsigned int reg);
349static const char *dwarf_regname(struct readelf *re, unsigned int num);
350static struct dumpop *find_dumpop(struct readelf *re, size_t si,
351    const char *sn, int op, int t);
352static int get_ent_count(struct section *s, int *ent_count);
353static int get_mips_register_size(uint8_t flag);
354static char *get_regoff_str(struct readelf *re, Dwarf_Half reg,
355    Dwarf_Addr off);
356static const char *get_string(struct readelf *re, int strtab, size_t off);
357static const char *get_symbol_name(struct readelf *re, int symtab, int i);
358static uint64_t get_symbol_value(struct readelf *re, int symtab, int i);
359static void load_sections(struct readelf *re);
360static int loc_at_comparator(const void *la1, const void *la2);
361static const char *mips_abi_fp(uint64_t fp);
362static const char *note_type(const char *note_name, unsigned int et,
363    unsigned int nt);
364static const char *note_type_freebsd(unsigned int nt);
365static const char *note_type_freebsd_core(unsigned int nt);
366static const char *note_type_linux_core(unsigned int nt);
367static const char *note_type_gnu(unsigned int nt);
368static const char *note_type_netbsd(unsigned int nt);
369static const char *note_type_openbsd(unsigned int nt);
370static const char *note_type_unknown(unsigned int nt);
371static const char *note_type_xen(unsigned int nt);
372static const char *option_kind(uint8_t kind);
373static const char *phdr_type(unsigned int mach, unsigned int ptype);
374static const char *ppc_abi_fp(uint64_t fp);
375static const char *ppc_abi_vector(uint64_t vec);
376static void readelf_usage(int status);
377static void readelf_version(void);
378static void search_loclist_at(struct readelf *re, Dwarf_Die die,
379    Dwarf_Unsigned lowpc, struct loc_at **la_list,
380    size_t *la_list_len, size_t *la_list_cap);
381static void search_ver(struct readelf *re);
382static const char *section_type(unsigned int mach, unsigned int stype);
383static void set_cu_context(struct readelf *re, Dwarf_Half psize,
384    Dwarf_Half osize, Dwarf_Half ver);
385static const char *st_bind(unsigned int sbind);
386static const char *st_shndx(unsigned int shndx);
387static const char *st_type(unsigned int mach, unsigned int os,
388    unsigned int stype);
389static const char *st_vis(unsigned int svis);
390static const char *top_tag(unsigned int tag);
391static void unload_sections(struct readelf *re);
392static uint64_t _read_lsb(Elf_Data *d, uint64_t *offsetp,
393    int bytes_to_read);
394static uint64_t _read_msb(Elf_Data *d, uint64_t *offsetp,
395    int bytes_to_read);
396static uint64_t _decode_lsb(uint8_t **data, int bytes_to_read);
397static uint64_t _decode_msb(uint8_t **data, int bytes_to_read);
398static int64_t _decode_sleb128(uint8_t **dp, uint8_t *dpe);
399static uint64_t _decode_uleb128(uint8_t **dp, uint8_t *dpe);
400
401static struct eflags_desc arm_eflags_desc[] = {
402	{EF_ARM_RELEXEC, "relocatable executable"},
403	{EF_ARM_HASENTRY, "has entry point"},
404	{EF_ARM_SYMSARESORTED, "sorted symbol tables"},
405	{EF_ARM_DYNSYMSUSESEGIDX, "dynamic symbols use segment index"},
406	{EF_ARM_MAPSYMSFIRST, "mapping symbols precede others"},
407	{EF_ARM_BE8, "BE8"},
408	{EF_ARM_LE8, "LE8"},
409	{EF_ARM_INTERWORK, "interworking enabled"},
410	{EF_ARM_APCS_26, "uses APCS/26"},
411	{EF_ARM_APCS_FLOAT, "uses APCS/float"},
412	{EF_ARM_PIC, "position independent"},
413	{EF_ARM_ALIGN8, "8 bit structure alignment"},
414	{EF_ARM_NEW_ABI, "uses new ABI"},
415	{EF_ARM_OLD_ABI, "uses old ABI"},
416	{EF_ARM_SOFT_FLOAT, "software FP"},
417	{EF_ARM_VFP_FLOAT, "VFP"},
418	{EF_ARM_MAVERICK_FLOAT, "Maverick FP"},
419	{0, NULL}
420};
421
422static struct eflags_desc mips_eflags_desc[] = {
423	{EF_MIPS_NOREORDER, "noreorder"},
424	{EF_MIPS_PIC, "pic"},
425	{EF_MIPS_CPIC, "cpic"},
426	{EF_MIPS_UCODE, "ugen_reserved"},
427	{EF_MIPS_ABI2, "abi2"},
428	{EF_MIPS_OPTIONS_FIRST, "odk first"},
429	{EF_MIPS_ARCH_ASE_MDMX, "mdmx"},
430	{EF_MIPS_ARCH_ASE_M16, "mips16"},
431	{0, NULL}
432};
433
434static struct eflags_desc powerpc_eflags_desc[] = {
435	{EF_PPC_EMB, "emb"},
436	{EF_PPC_RELOCATABLE, "relocatable"},
437	{EF_PPC_RELOCATABLE_LIB, "relocatable-lib"},
438	{0, NULL}
439};
440
441static struct eflags_desc riscv_eflags_desc[] = {
442	{EF_RISCV_RVC, "RVC"},
443	{EF_RISCV_RVE, "RVE"},
444	{EF_RISCV_TSO, "TSO"},
445	{0, NULL}
446};
447
448static struct eflags_desc sparc_eflags_desc[] = {
449	{EF_SPARC_32PLUS, "v8+"},
450	{EF_SPARC_SUN_US1, "ultrasparcI"},
451	{EF_SPARC_HAL_R1, "halr1"},
452	{EF_SPARC_SUN_US3, "ultrasparcIII"},
453	{0, NULL}
454};
455
456static const char *
457elf_osabi(unsigned int abi)
458{
459	static char s_abi[32];
460
461	switch(abi) {
462	case ELFOSABI_NONE: return "NONE";
463	case ELFOSABI_HPUX: return "HPUX";
464	case ELFOSABI_NETBSD: return "NetBSD";
465	case ELFOSABI_GNU: return "GNU";
466	case ELFOSABI_HURD: return "HURD";
467	case ELFOSABI_86OPEN: return "86OPEN";
468	case ELFOSABI_SOLARIS: return "Solaris";
469	case ELFOSABI_AIX: return "AIX";
470	case ELFOSABI_IRIX: return "IRIX";
471	case ELFOSABI_FREEBSD: return "FreeBSD";
472	case ELFOSABI_TRU64: return "TRU64";
473	case ELFOSABI_MODESTO: return "MODESTO";
474	case ELFOSABI_OPENBSD: return "OpenBSD";
475	case ELFOSABI_OPENVMS: return "OpenVMS";
476	case ELFOSABI_NSK: return "NSK";
477	case ELFOSABI_CLOUDABI: return "CloudABI";
478	case ELFOSABI_ARM_AEABI: return "ARM EABI";
479	case ELFOSABI_ARM: return "ARM";
480	case ELFOSABI_STANDALONE: return "StandAlone";
481	default:
482		snprintf(s_abi, sizeof(s_abi), "<unknown: %#x>", abi);
483		return (s_abi);
484	}
485};
486
487static const char *
488elf_machine(unsigned int mach)
489{
490	static char s_mach[32];
491
492	switch (mach) {
493	case EM_NONE: return "Unknown machine";
494	case EM_M32: return "AT&T WE32100";
495	case EM_SPARC: return "Sun SPARC";
496	case EM_386: return "Intel i386";
497	case EM_68K: return "Motorola 68000";
498	case EM_IAMCU: return "Intel MCU";
499	case EM_88K: return "Motorola 88000";
500	case EM_860: return "Intel i860";
501	case EM_MIPS: return "MIPS R3000 Big-Endian only";
502	case EM_S370: return "IBM System/370";
503	case EM_MIPS_RS3_LE: return "MIPS R3000 Little-Endian";
504	case EM_PARISC: return "HP PA-RISC";
505	case EM_VPP500: return "Fujitsu VPP500";
506	case EM_SPARC32PLUS: return "SPARC v8plus";
507	case EM_960: return "Intel 80960";
508	case EM_PPC: return "PowerPC 32-bit";
509	case EM_PPC64: return "PowerPC 64-bit";
510	case EM_S390: return "IBM System/390";
511	case EM_V800: return "NEC V800";
512	case EM_FR20: return "Fujitsu FR20";
513	case EM_RH32: return "TRW RH-32";
514	case EM_RCE: return "Motorola RCE";
515	case EM_ARM: return "ARM";
516	case EM_SH: return "Hitachi SH";
517	case EM_SPARCV9: return "SPARC v9 64-bit";
518	case EM_TRICORE: return "Siemens TriCore embedded processor";
519	case EM_ARC: return "Argonaut RISC Core";
520	case EM_H8_300: return "Hitachi H8/300";
521	case EM_H8_300H: return "Hitachi H8/300H";
522	case EM_H8S: return "Hitachi H8S";
523	case EM_H8_500: return "Hitachi H8/500";
524	case EM_IA_64: return "Intel IA-64 Processor";
525	case EM_MIPS_X: return "Stanford MIPS-X";
526	case EM_COLDFIRE: return "Motorola ColdFire";
527	case EM_68HC12: return "Motorola M68HC12";
528	case EM_MMA: return "Fujitsu MMA";
529	case EM_PCP: return "Siemens PCP";
530	case EM_NCPU: return "Sony nCPU";
531	case EM_NDR1: return "Denso NDR1 microprocessor";
532	case EM_STARCORE: return "Motorola Star*Core processor";
533	case EM_ME16: return "Toyota ME16 processor";
534	case EM_ST100: return "STMicroelectronics ST100 processor";
535	case EM_TINYJ: return "Advanced Logic Corp. TinyJ processor";
536	case EM_X86_64: return "Advanced Micro Devices x86-64";
537	case EM_PDSP: return "Sony DSP Processor";
538	case EM_FX66: return "Siemens FX66 microcontroller";
539	case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 microcontroller";
540	case EM_ST7: return "STmicroelectronics ST7 8-bit microcontroller";
541	case EM_68HC16: return "Motorola MC68HC16 microcontroller";
542	case EM_68HC11: return "Motorola MC68HC11 microcontroller";
543	case EM_68HC08: return "Motorola MC68HC08 microcontroller";
544	case EM_68HC05: return "Motorola MC68HC05 microcontroller";
545	case EM_SVX: return "Silicon Graphics SVx";
546	case EM_ST19: return "STMicroelectronics ST19 8-bit mc";
547	case EM_VAX: return "Digital VAX";
548	case EM_CRIS: return "Axis Communications 32-bit embedded processor";
549	case EM_JAVELIN: return "Infineon Tech. 32bit embedded processor";
550	case EM_FIREPATH: return "Element 14 64-bit DSP Processor";
551	case EM_ZSP: return "LSI Logic 16-bit DSP Processor";
552	case EM_MMIX: return "Donald Knuth's educational 64-bit proc";
553	case EM_HUANY: return "Harvard University MI object files";
554	case EM_PRISM: return "SiTera Prism";
555	case EM_AVR: return "Atmel AVR 8-bit microcontroller";
556	case EM_FR30: return "Fujitsu FR30";
557	case EM_D10V: return "Mitsubishi D10V";
558	case EM_D30V: return "Mitsubishi D30V";
559	case EM_V850: return "NEC v850";
560	case EM_M32R: return "Mitsubishi M32R";
561	case EM_MN10300: return "Matsushita MN10300";
562	case EM_MN10200: return "Matsushita MN10200";
563	case EM_PJ: return "picoJava";
564	case EM_OPENRISC: return "OpenRISC 32-bit embedded processor";
565	case EM_ARC_A5: return "ARC Cores Tangent-A5";
566	case EM_XTENSA: return "Tensilica Xtensa Architecture";
567	case EM_VIDEOCORE: return "Alphamosaic VideoCore processor";
568	case EM_TMM_GPP: return "Thompson Multimedia General Purpose Processor";
569	case EM_NS32K: return "National Semiconductor 32000 series";
570	case EM_TPC: return "Tenor Network TPC processor";
571	case EM_SNP1K: return "Trebia SNP 1000 processor";
572	case EM_ST200: return "STMicroelectronics ST200 microcontroller";
573	case EM_IP2K: return "Ubicom IP2xxx microcontroller family";
574	case EM_MAX: return "MAX Processor";
575	case EM_CR: return "National Semiconductor CompactRISC microprocessor";
576	case EM_F2MC16: return "Fujitsu F2MC16";
577	case EM_MSP430: return "TI embedded microcontroller msp430";
578	case EM_BLACKFIN: return "Analog Devices Blackfin (DSP) processor";
579	case EM_SE_C33: return "S1C33 Family of Seiko Epson processors";
580	case EM_SEP: return "Sharp embedded microprocessor";
581	case EM_ARCA: return "Arca RISC Microprocessor";
582	case EM_UNICORE: return "Microprocessor series from PKU-Unity Ltd";
583	case EM_AARCH64: return "AArch64";
584	case EM_RISCV: return "RISC-V";
585	default:
586		snprintf(s_mach, sizeof(s_mach), "<unknown: %#x>", mach);
587		return (s_mach);
588	}
589
590}
591
592static const char *
593elf_class(unsigned int class)
594{
595	static char s_class[32];
596
597	switch (class) {
598	case ELFCLASSNONE: return "none";
599	case ELFCLASS32: return "ELF32";
600	case ELFCLASS64: return "ELF64";
601	default:
602		snprintf(s_class, sizeof(s_class), "<unknown: %#x>", class);
603		return (s_class);
604	}
605}
606
607static const char *
608elf_endian(unsigned int endian)
609{
610	static char s_endian[32];
611
612	switch (endian) {
613	case ELFDATANONE: return "none";
614	case ELFDATA2LSB: return "2's complement, little endian";
615	case ELFDATA2MSB: return "2's complement, big endian";
616	default:
617		snprintf(s_endian, sizeof(s_endian), "<unknown: %#x>", endian);
618		return (s_endian);
619	}
620}
621
622static const char *
623elf_type(unsigned int type)
624{
625	static char s_type[32];
626
627	switch (type) {
628	case ET_NONE: return "NONE (None)";
629	case ET_REL: return "REL (Relocatable file)";
630	case ET_EXEC: return "EXEC (Executable file)";
631	case ET_DYN: return "DYN (Shared object file)";
632	case ET_CORE: return "CORE (Core file)";
633	default:
634		if (type >= ET_LOPROC)
635			snprintf(s_type, sizeof(s_type), "<proc: %#x>", type);
636		else if (type >= ET_LOOS && type <= ET_HIOS)
637			snprintf(s_type, sizeof(s_type), "<os: %#x>", type);
638		else
639			snprintf(s_type, sizeof(s_type), "<unknown: %#x>",
640			    type);
641		return (s_type);
642	}
643}
644
645static const char *
646elf_ver(unsigned int ver)
647{
648	static char s_ver[32];
649
650	switch (ver) {
651	case EV_CURRENT: return "(current)";
652	case EV_NONE: return "(none)";
653	default:
654		snprintf(s_ver, sizeof(s_ver), "<unknown: %#x>",
655		    ver);
656		return (s_ver);
657	}
658}
659
660static const char *
661phdr_type(unsigned int mach, unsigned int ptype)
662{
663	static char s_ptype[32];
664
665	if (ptype >= PT_LOPROC && ptype <= PT_HIPROC) {
666		switch (mach) {
667		case EM_ARM:
668			switch (ptype) {
669			case PT_ARM_ARCHEXT: return "ARM_ARCHEXT";
670			case PT_ARM_EXIDX: return "ARM_EXIDX";
671			}
672			break;
673		}
674		snprintf(s_ptype, sizeof(s_ptype), "LOPROC+%#x",
675		    ptype - PT_LOPROC);
676		return (s_ptype);
677	}
678
679	switch (ptype) {
680	case PT_NULL: return "NULL";
681	case PT_LOAD: return "LOAD";
682	case PT_DYNAMIC: return "DYNAMIC";
683	case PT_INTERP: return "INTERP";
684	case PT_NOTE: return "NOTE";
685	case PT_SHLIB: return "SHLIB";
686	case PT_PHDR: return "PHDR";
687	case PT_TLS: return "TLS";
688	case PT_GNU_EH_FRAME: return "GNU_EH_FRAME";
689	case PT_GNU_STACK: return "GNU_STACK";
690	case PT_GNU_RELRO: return "GNU_RELRO";
691	case PT_OPENBSD_RANDOMIZE: return "OPENBSD_RANDOMIZE";
692	case PT_OPENBSD_WXNEEDED: return "OPENBSD_WXNEEDED";
693	case PT_OPENBSD_BOOTDATA: return "OPENBSD_BOOTDATA";
694	default:
695		if (ptype >= PT_LOOS && ptype <= PT_HIOS)
696			snprintf(s_ptype, sizeof(s_ptype), "LOOS+%#x",
697			    ptype - PT_LOOS);
698		else
699			snprintf(s_ptype, sizeof(s_ptype), "<unknown: %#x>",
700			    ptype);
701		return (s_ptype);
702	}
703}
704
705static const char *
706section_type(unsigned int mach, unsigned int stype)
707{
708	static char s_stype[32];
709
710	if (stype >= SHT_LOPROC && stype <= SHT_HIPROC) {
711		switch (mach) {
712		case EM_ARM:
713			switch (stype) {
714			case SHT_ARM_EXIDX: return "ARM_EXIDX";
715			case SHT_ARM_PREEMPTMAP: return "ARM_PREEMPTMAP";
716			case SHT_ARM_ATTRIBUTES: return "ARM_ATTRIBUTES";
717			case SHT_ARM_DEBUGOVERLAY: return "ARM_DEBUGOVERLAY";
718			case SHT_ARM_OVERLAYSECTION: return "ARM_OVERLAYSECTION";
719			}
720			break;
721		case EM_X86_64:
722			switch (stype) {
723			case SHT_X86_64_UNWIND: return "X86_64_UNWIND";
724			default:
725				break;
726			}
727			break;
728		case EM_MIPS:
729		case EM_MIPS_RS3_LE:
730			switch (stype) {
731			case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST";
732			case SHT_MIPS_MSYM: return "MIPS_MSYM";
733			case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT";
734			case SHT_MIPS_GPTAB: return "MIPS_GPTAB";
735			case SHT_MIPS_UCODE: return "MIPS_UCODE";
736			case SHT_MIPS_DEBUG: return "MIPS_DEBUG";
737			case SHT_MIPS_REGINFO: return "MIPS_REGINFO";
738			case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE";
739			case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM";
740			case SHT_MIPS_RELD: return "MIPS_RELD";
741			case SHT_MIPS_IFACE: return "MIPS_IFACE";
742			case SHT_MIPS_CONTENT: return "MIPS_CONTENT";
743			case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS";
744			case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM";
745			case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST";
746			case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS";
747			case SHT_MIPS_DWARF: return "MIPS_DWARF";
748			case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL";
749			case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
750			case SHT_MIPS_EVENTS: return "MIPS_EVENTS";
751			case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE";
752			case SHT_MIPS_PIXIE: return "MIPS_PIXIE";
753			case SHT_MIPS_XLATE: return "MIPS_XLATE";
754			case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG";
755			case SHT_MIPS_WHIRL: return "MIPS_WHIRL";
756			case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION";
757			case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD";
758			case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION";
759			case SHT_MIPS_ABIFLAGS: return "MIPS_ABIFLAGS";
760			default:
761				break;
762			}
763			break;
764		default:
765			break;
766		}
767
768		snprintf(s_stype, sizeof(s_stype), "LOPROC+%#x",
769		    stype - SHT_LOPROC);
770		return (s_stype);
771	}
772
773	switch (stype) {
774	case SHT_NULL: return "NULL";
775	case SHT_PROGBITS: return "PROGBITS";
776	case SHT_SYMTAB: return "SYMTAB";
777	case SHT_STRTAB: return "STRTAB";
778	case SHT_RELA: return "RELA";
779	case SHT_HASH: return "HASH";
780	case SHT_DYNAMIC: return "DYNAMIC";
781	case SHT_NOTE: return "NOTE";
782	case SHT_NOBITS: return "NOBITS";
783	case SHT_REL: return "REL";
784	case SHT_SHLIB: return "SHLIB";
785	case SHT_DYNSYM: return "DYNSYM";
786	case SHT_INIT_ARRAY: return "INIT_ARRAY";
787	case SHT_FINI_ARRAY: return "FINI_ARRAY";
788	case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY";
789	case SHT_GROUP: return "GROUP";
790	case SHT_SYMTAB_SHNDX: return "SYMTAB_SHNDX";
791	case SHT_SUNW_dof: return "SUNW_dof";
792	case SHT_SUNW_cap: return "SUNW_cap";
793	case SHT_GNU_HASH: return "GNU_HASH";
794	case SHT_SUNW_ANNOTATE: return "SUNW_ANNOTATE";
795	case SHT_SUNW_DEBUGSTR: return "SUNW_DEBUGSTR";
796	case SHT_SUNW_DEBUG: return "SUNW_DEBUG";
797	case SHT_SUNW_move: return "SUNW_move";
798	case SHT_SUNW_COMDAT: return "SUNW_COMDAT";
799	case SHT_SUNW_syminfo: return "SUNW_syminfo";
800	case SHT_SUNW_verdef: return "SUNW_verdef";
801	case SHT_SUNW_verneed: return "SUNW_verneed";
802	case SHT_SUNW_versym: return "SUNW_versym";
803	default:
804		if (stype >= SHT_LOOS && stype <= SHT_HIOS)
805			snprintf(s_stype, sizeof(s_stype), "LOOS+%#x",
806			    stype - SHT_LOOS);
807		else if (stype >= SHT_LOUSER)
808			snprintf(s_stype, sizeof(s_stype), "LOUSER+%#x",
809			    stype - SHT_LOUSER);
810		else
811			snprintf(s_stype, sizeof(s_stype), "<unknown: %#x>",
812			    stype);
813		return (s_stype);
814	}
815}
816
817static const char *
818dt_type(unsigned int mach, unsigned int dtype)
819{
820	static char s_dtype[32];
821
822	switch (dtype) {
823	case DT_NULL: return "NULL";
824	case DT_NEEDED: return "NEEDED";
825	case DT_PLTRELSZ: return "PLTRELSZ";
826	case DT_PLTGOT: return "PLTGOT";
827	case DT_HASH: return "HASH";
828	case DT_STRTAB: return "STRTAB";
829	case DT_SYMTAB: return "SYMTAB";
830	case DT_RELA: return "RELA";
831	case DT_RELASZ: return "RELASZ";
832	case DT_RELAENT: return "RELAENT";
833	case DT_STRSZ: return "STRSZ";
834	case DT_SYMENT: return "SYMENT";
835	case DT_INIT: return "INIT";
836	case DT_FINI: return "FINI";
837	case DT_SONAME: return "SONAME";
838	case DT_RPATH: return "RPATH";
839	case DT_SYMBOLIC: return "SYMBOLIC";
840	case DT_REL: return "REL";
841	case DT_RELSZ: return "RELSZ";
842	case DT_RELENT: return "RELENT";
843	case DT_PLTREL: return "PLTREL";
844	case DT_DEBUG: return "DEBUG";
845	case DT_TEXTREL: return "TEXTREL";
846	case DT_JMPREL: return "JMPREL";
847	case DT_BIND_NOW: return "BIND_NOW";
848	case DT_INIT_ARRAY: return "INIT_ARRAY";
849	case DT_FINI_ARRAY: return "FINI_ARRAY";
850	case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
851	case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
852	case DT_RUNPATH: return "RUNPATH";
853	case DT_FLAGS: return "FLAGS";
854	case DT_PREINIT_ARRAY: return "PREINIT_ARRAY";
855	case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ";
856	case DT_MAXPOSTAGS: return "MAXPOSTAGS";
857	case DT_SUNW_AUXILIARY: return "SUNW_AUXILIARY";
858	case DT_SUNW_RTLDINF: return "SUNW_RTLDINF";
859	case DT_SUNW_FILTER: return "SUNW_FILTER";
860	case DT_SUNW_CAP: return "SUNW_CAP";
861	case DT_SUNW_ASLR: return "SUNW_ASLR";
862	case DT_CHECKSUM: return "CHECKSUM";
863	case DT_PLTPADSZ: return "PLTPADSZ";
864	case DT_MOVEENT: return "MOVEENT";
865	case DT_MOVESZ: return "MOVESZ";
866	case DT_FEATURE: return "FEATURE";
867	case DT_POSFLAG_1: return "POSFLAG_1";
868	case DT_SYMINSZ: return "SYMINSZ";
869	case DT_SYMINENT: return "SYMINENT";
870	case DT_GNU_HASH: return "GNU_HASH";
871	case DT_TLSDESC_PLT: return "DT_TLSDESC_PLT";
872	case DT_TLSDESC_GOT: return "DT_TLSDESC_GOT";
873	case DT_GNU_CONFLICT: return "GNU_CONFLICT";
874	case DT_GNU_LIBLIST: return "GNU_LIBLIST";
875	case DT_CONFIG: return "CONFIG";
876	case DT_DEPAUDIT: return "DEPAUDIT";
877	case DT_AUDIT: return "AUDIT";
878	case DT_PLTPAD: return "PLTPAD";
879	case DT_MOVETAB: return "MOVETAB";
880	case DT_SYMINFO: return "SYMINFO";
881	case DT_VERSYM: return "VERSYM";
882	case DT_RELACOUNT: return "RELACOUNT";
883	case DT_RELCOUNT: return "RELCOUNT";
884	case DT_FLAGS_1: return "FLAGS_1";
885	case DT_VERDEF: return "VERDEF";
886	case DT_VERDEFNUM: return "VERDEFNUM";
887	case DT_VERNEED: return "VERNEED";
888	case DT_VERNEEDNUM: return "VERNEEDNUM";
889	case DT_AUXILIARY: return "AUXILIARY";
890	case DT_USED: return "USED";
891	case DT_FILTER: return "FILTER";
892	case DT_GNU_PRELINKED: return "GNU_PRELINKED";
893	case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ";
894	case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ";
895	}
896
897	if (dtype >= DT_LOPROC && dtype <= DT_HIPROC) {
898		switch (mach) {
899		case EM_ARM:
900			switch (dtype) {
901			case DT_ARM_SYMTABSZ:
902				return "ARM_SYMTABSZ";
903			default:
904				break;
905			}
906			break;
907		case EM_MIPS:
908		case EM_MIPS_RS3_LE:
909			switch (dtype) {
910			case DT_MIPS_RLD_VERSION:
911				return "MIPS_RLD_VERSION";
912			case DT_MIPS_TIME_STAMP:
913				return "MIPS_TIME_STAMP";
914			case DT_MIPS_ICHECKSUM:
915				return "MIPS_ICHECKSUM";
916			case DT_MIPS_IVERSION:
917				return "MIPS_IVERSION";
918			case DT_MIPS_FLAGS:
919				return "MIPS_FLAGS";
920			case DT_MIPS_BASE_ADDRESS:
921				return "MIPS_BASE_ADDRESS";
922			case DT_MIPS_CONFLICT:
923				return "MIPS_CONFLICT";
924			case DT_MIPS_LIBLIST:
925				return "MIPS_LIBLIST";
926			case DT_MIPS_LOCAL_GOTNO:
927				return "MIPS_LOCAL_GOTNO";
928			case DT_MIPS_CONFLICTNO:
929				return "MIPS_CONFLICTNO";
930			case DT_MIPS_LIBLISTNO:
931				return "MIPS_LIBLISTNO";
932			case DT_MIPS_SYMTABNO:
933				return "MIPS_SYMTABNO";
934			case DT_MIPS_UNREFEXTNO:
935				return "MIPS_UNREFEXTNO";
936			case DT_MIPS_GOTSYM:
937				return "MIPS_GOTSYM";
938			case DT_MIPS_HIPAGENO:
939				return "MIPS_HIPAGENO";
940			case DT_MIPS_RLD_MAP:
941				return "MIPS_RLD_MAP";
942			case DT_MIPS_DELTA_CLASS:
943				return "MIPS_DELTA_CLASS";
944			case DT_MIPS_DELTA_CLASS_NO:
945				return "MIPS_DELTA_CLASS_NO";
946			case DT_MIPS_DELTA_INSTANCE:
947				return "MIPS_DELTA_INSTANCE";
948			case DT_MIPS_DELTA_INSTANCE_NO:
949				return "MIPS_DELTA_INSTANCE_NO";
950			case DT_MIPS_DELTA_RELOC:
951				return "MIPS_DELTA_RELOC";
952			case DT_MIPS_DELTA_RELOC_NO:
953				return "MIPS_DELTA_RELOC_NO";
954			case DT_MIPS_DELTA_SYM:
955				return "MIPS_DELTA_SYM";
956			case DT_MIPS_DELTA_SYM_NO:
957				return "MIPS_DELTA_SYM_NO";
958			case DT_MIPS_DELTA_CLASSSYM:
959				return "MIPS_DELTA_CLASSSYM";
960			case DT_MIPS_DELTA_CLASSSYM_NO:
961				return "MIPS_DELTA_CLASSSYM_NO";
962			case DT_MIPS_CXX_FLAGS:
963				return "MIPS_CXX_FLAGS";
964			case DT_MIPS_PIXIE_INIT:
965				return "MIPS_PIXIE_INIT";
966			case DT_MIPS_SYMBOL_LIB:
967				return "MIPS_SYMBOL_LIB";
968			case DT_MIPS_LOCALPAGE_GOTIDX:
969				return "MIPS_LOCALPAGE_GOTIDX";
970			case DT_MIPS_LOCAL_GOTIDX:
971				return "MIPS_LOCAL_GOTIDX";
972			case DT_MIPS_HIDDEN_GOTIDX:
973				return "MIPS_HIDDEN_GOTIDX";
974			case DT_MIPS_PROTECTED_GOTIDX:
975				return "MIPS_PROTECTED_GOTIDX";
976			case DT_MIPS_OPTIONS:
977				return "MIPS_OPTIONS";
978			case DT_MIPS_INTERFACE:
979				return "MIPS_INTERFACE";
980			case DT_MIPS_DYNSTR_ALIGN:
981				return "MIPS_DYNSTR_ALIGN";
982			case DT_MIPS_INTERFACE_SIZE:
983				return "MIPS_INTERFACE_SIZE";
984			case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
985				return "MIPS_RLD_TEXT_RESOLVE_ADDR";
986			case DT_MIPS_PERF_SUFFIX:
987				return "MIPS_PERF_SUFFIX";
988			case DT_MIPS_COMPACT_SIZE:
989				return "MIPS_COMPACT_SIZE";
990			case DT_MIPS_GP_VALUE:
991				return "MIPS_GP_VALUE";
992			case DT_MIPS_AUX_DYNAMIC:
993				return "MIPS_AUX_DYNAMIC";
994			case DT_MIPS_PLTGOT:
995				return "MIPS_PLTGOT";
996			case DT_MIPS_RLD_OBJ_UPDATE:
997				return "MIPS_RLD_OBJ_UPDATE";
998			case DT_MIPS_RWPLT:
999				return "MIPS_RWPLT";
1000			default:
1001				break;
1002			}
1003			break;
1004		case EM_SPARC:
1005		case EM_SPARC32PLUS:
1006		case EM_SPARCV9:
1007			switch (dtype) {
1008			case DT_SPARC_REGISTER:
1009				return "DT_SPARC_REGISTER";
1010			default:
1011				break;
1012			}
1013			break;
1014		default:
1015			break;
1016		}
1017	}
1018
1019	snprintf(s_dtype, sizeof(s_dtype), "<unknown: %#x>", dtype);
1020	return (s_dtype);
1021}
1022
1023static const char *
1024st_bind(unsigned int sbind)
1025{
1026	static char s_sbind[32];
1027
1028	switch (sbind) {
1029	case STB_LOCAL: return "LOCAL";
1030	case STB_GLOBAL: return "GLOBAL";
1031	case STB_WEAK: return "WEAK";
1032	case STB_GNU_UNIQUE: return "UNIQUE";
1033	default:
1034		if (sbind >= STB_LOOS && sbind <= STB_HIOS)
1035			return "OS";
1036		else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
1037			return "PROC";
1038		else
1039			snprintf(s_sbind, sizeof(s_sbind), "<unknown: %#x>",
1040			    sbind);
1041		return (s_sbind);
1042	}
1043}
1044
1045static const char *
1046st_type(unsigned int mach, unsigned int os, unsigned int stype)
1047{
1048	static char s_stype[32];
1049
1050	switch (stype) {
1051	case STT_NOTYPE: return "NOTYPE";
1052	case STT_OBJECT: return "OBJECT";
1053	case STT_FUNC: return "FUNC";
1054	case STT_SECTION: return "SECTION";
1055	case STT_FILE: return "FILE";
1056	case STT_COMMON: return "COMMON";
1057	case STT_TLS: return "TLS";
1058	default:
1059		if (stype >= STT_LOOS && stype <= STT_HIOS) {
1060			if ((os == ELFOSABI_GNU || os == ELFOSABI_FREEBSD) &&
1061			    stype == STT_GNU_IFUNC)
1062				return "IFUNC";
1063			snprintf(s_stype, sizeof(s_stype), "OS+%#x",
1064			    stype - STT_LOOS);
1065		} else if (stype >= STT_LOPROC && stype <= STT_HIPROC) {
1066			if (mach == EM_SPARCV9 && stype == STT_SPARC_REGISTER)
1067				return "REGISTER";
1068			snprintf(s_stype, sizeof(s_stype), "PROC+%#x",
1069			    stype - STT_LOPROC);
1070		} else
1071			snprintf(s_stype, sizeof(s_stype), "<unknown: %#x>",
1072			    stype);
1073		return (s_stype);
1074	}
1075}
1076
1077static const char *
1078st_vis(unsigned int svis)
1079{
1080	static char s_svis[32];
1081
1082	switch(svis) {
1083	case STV_DEFAULT: return "DEFAULT";
1084	case STV_INTERNAL: return "INTERNAL";
1085	case STV_HIDDEN: return "HIDDEN";
1086	case STV_PROTECTED: return "PROTECTED";
1087	default:
1088		snprintf(s_svis, sizeof(s_svis), "<unknown: %#x>", svis);
1089		return (s_svis);
1090	}
1091}
1092
1093static const char *
1094st_shndx(unsigned int shndx)
1095{
1096	static char s_shndx[32];
1097
1098	switch (shndx) {
1099	case SHN_UNDEF: return "UND";
1100	case SHN_ABS: return "ABS";
1101	case SHN_COMMON: return "COM";
1102	default:
1103		if (shndx >= SHN_LOPROC && shndx <= SHN_HIPROC)
1104			return "PRC";
1105		else if (shndx >= SHN_LOOS && shndx <= SHN_HIOS)
1106			return "OS";
1107		else
1108			snprintf(s_shndx, sizeof(s_shndx), "%u", shndx);
1109		return (s_shndx);
1110	}
1111}
1112
1113static struct {
1114	const char *ln;
1115	char sn;
1116	int value;
1117} section_flag[] = {
1118	{"WRITE", 'W', SHF_WRITE},
1119	{"ALLOC", 'A', SHF_ALLOC},
1120	{"EXEC", 'X', SHF_EXECINSTR},
1121	{"MERGE", 'M', SHF_MERGE},
1122	{"STRINGS", 'S', SHF_STRINGS},
1123	{"INFO LINK", 'I', SHF_INFO_LINK},
1124	{"OS NONCONF", 'O', SHF_OS_NONCONFORMING},
1125	{"GROUP", 'G', SHF_GROUP},
1126	{"TLS", 'T', SHF_TLS},
1127	{"COMPRESSED", 'C', SHF_COMPRESSED},
1128	{NULL, 0, 0}
1129};
1130
1131static const char *
1132note_type(const char *name, unsigned int et, unsigned int nt)
1133{
1134	if ((strcmp(name, "CORE") == 0 || strcmp(name, "LINUX") == 0) &&
1135	    et == ET_CORE)
1136		return note_type_linux_core(nt);
1137	else if (strcmp(name, "FreeBSD") == 0)
1138		if (et == ET_CORE)
1139			return note_type_freebsd_core(nt);
1140		else
1141			return note_type_freebsd(nt);
1142	else if (strcmp(name, "GNU") == 0 && et != ET_CORE)
1143		return note_type_gnu(nt);
1144	else if (strcmp(name, "NetBSD") == 0 && et != ET_CORE)
1145		return note_type_netbsd(nt);
1146	else if (strcmp(name, "OpenBSD") == 0 && et != ET_CORE)
1147		return note_type_openbsd(nt);
1148	else if (strcmp(name, "Xen") == 0 && et != ET_CORE)
1149		return note_type_xen(nt);
1150	return note_type_unknown(nt);
1151}
1152
1153static const char *
1154note_type_freebsd(unsigned int nt)
1155{
1156	switch (nt) {
1157	case 1: return "NT_FREEBSD_ABI_TAG";
1158	case 2: return "NT_FREEBSD_NOINIT_TAG";
1159	case 3: return "NT_FREEBSD_ARCH_TAG";
1160	case 4: return "NT_FREEBSD_FEATURE_CTL";
1161	default: return (note_type_unknown(nt));
1162	}
1163}
1164
1165static const char *
1166note_type_freebsd_core(unsigned int nt)
1167{
1168	switch (nt) {
1169	case 1: return "NT_PRSTATUS";
1170	case 2: return "NT_FPREGSET";
1171	case 3: return "NT_PRPSINFO";
1172	case 7: return "NT_THRMISC";
1173	case 8: return "NT_PROCSTAT_PROC";
1174	case 9: return "NT_PROCSTAT_FILES";
1175	case 10: return "NT_PROCSTAT_VMMAP";
1176	case 11: return "NT_PROCSTAT_GROUPS";
1177	case 12: return "NT_PROCSTAT_UMASK";
1178	case 13: return "NT_PROCSTAT_RLIMIT";
1179	case 14: return "NT_PROCSTAT_OSREL";
1180	case 15: return "NT_PROCSTAT_PSSTRINGS";
1181	case 16: return "NT_PROCSTAT_AUXV";
1182	case 17: return "NT_PTLWPINFO";
1183	case 0x100: return "NT_PPC_VMX (ppc Altivec registers)";
1184	case 0x102: return "NT_PPC_VSX (ppc VSX registers)";
1185	case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)";
1186	case 0x400: return "NT_ARM_VFP (arm VFP registers)";
1187	default: return (note_type_unknown(nt));
1188	}
1189}
1190
1191static const char *
1192note_type_linux_core(unsigned int nt)
1193{
1194	switch (nt) {
1195	case 1: return "NT_PRSTATUS (Process status)";
1196	case 2: return "NT_FPREGSET (Floating point information)";
1197	case 3: return "NT_PRPSINFO (Process information)";
1198	case 4: return "NT_TASKSTRUCT (Task structure)";
1199	case 6: return "NT_AUXV (Auxiliary vector)";
1200	case 10: return "NT_PSTATUS (Linux process status)";
1201	case 12: return "NT_FPREGS (Linux floating point regset)";
1202	case 13: return "NT_PSINFO (Linux process information)";
1203	case 16: return "NT_LWPSTATUS (Linux lwpstatus_t type)";
1204	case 17: return "NT_LWPSINFO (Linux lwpinfo_t type)";
1205	case 18: return "NT_WIN32PSTATUS (win32_pstatus structure)";
1206	case 0x100: return "NT_PPC_VMX (ppc Altivec registers)";
1207	case 0x102: return "NT_PPC_VSX (ppc VSX registers)";
1208	case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)";
1209	case 0x300: return "NT_S390_HIGH_GPRS (s390 upper register halves)";
1210	case 0x301: return "NT_S390_TIMER (s390 timer register)";
1211	case 0x302: return "NT_S390_TODCMP (s390 TOD comparator register)";
1212	case 0x303: return "NT_S390_TODPREG (s390 TOD programmable register)";
1213	case 0x304: return "NT_S390_CTRS (s390 control registers)";
1214	case 0x305: return "NT_S390_PREFIX (s390 prefix register)";
1215	case 0x400: return "NT_ARM_VFP (arm VFP registers)";
1216	case 0x46494c45UL: return "NT_FILE (mapped files)";
1217	case 0x46E62B7FUL: return "NT_PRXFPREG (Linux user_xfpregs structure)";
1218	case 0x53494749UL: return "NT_SIGINFO (siginfo_t data)";
1219	default: return (note_type_unknown(nt));
1220	}
1221}
1222
1223static const char *
1224note_type_gnu(unsigned int nt)
1225{
1226	switch (nt) {
1227	case 1: return "NT_GNU_ABI_TAG";
1228	case 2: return "NT_GNU_HWCAP (Hardware capabilities)";
1229	case 3: return "NT_GNU_BUILD_ID (Build id set by ld(1))";
1230	case 4: return "NT_GNU_GOLD_VERSION (GNU gold version)";
1231	case 5: return "NT_GNU_PROPERTY_TYPE_0";
1232	default: return (note_type_unknown(nt));
1233	}
1234}
1235
1236static const char *
1237note_type_netbsd(unsigned int nt)
1238{
1239	switch (nt) {
1240	case 1: return "NT_NETBSD_IDENT";
1241	default: return (note_type_unknown(nt));
1242	}
1243}
1244
1245static const char *
1246note_type_openbsd(unsigned int nt)
1247{
1248	switch (nt) {
1249	case 1: return "NT_OPENBSD_IDENT";
1250	default: return (note_type_unknown(nt));
1251	}
1252}
1253
1254static const char *
1255note_type_unknown(unsigned int nt)
1256{
1257	static char s_nt[32];
1258
1259	snprintf(s_nt, sizeof(s_nt),
1260	    nt >= 0x100 ? "<unknown: 0x%x>" : "<unknown: %u>", nt);
1261	return (s_nt);
1262}
1263
1264static const char *
1265note_type_xen(unsigned int nt)
1266{
1267	switch (nt) {
1268	case 0: return "XEN_ELFNOTE_INFO";
1269	case 1: return "XEN_ELFNOTE_ENTRY";
1270	case 2: return "XEN_ELFNOTE_HYPERCALL_PAGE";
1271	case 3: return "XEN_ELFNOTE_VIRT_BASE";
1272	case 4: return "XEN_ELFNOTE_PADDR_OFFSET";
1273	case 5: return "XEN_ELFNOTE_XEN_VERSION";
1274	case 6: return "XEN_ELFNOTE_GUEST_OS";
1275	case 7: return "XEN_ELFNOTE_GUEST_VERSION";
1276	case 8: return "XEN_ELFNOTE_LOADER";
1277	case 9: return "XEN_ELFNOTE_PAE_MODE";
1278	case 10: return "XEN_ELFNOTE_FEATURES";
1279	case 11: return "XEN_ELFNOTE_BSD_SYMTAB";
1280	case 12: return "XEN_ELFNOTE_HV_START_LOW";
1281	case 13: return "XEN_ELFNOTE_L1_MFN_VALID";
1282	case 14: return "XEN_ELFNOTE_SUSPEND_CANCEL";
1283	case 15: return "XEN_ELFNOTE_INIT_P2M";
1284	case 16: return "XEN_ELFNOTE_MOD_START_PFN";
1285	case 17: return "XEN_ELFNOTE_SUPPORTED_FEATURES";
1286	case 18: return "XEN_ELFNOTE_PHYS32_ENTRY";
1287	default: return (note_type_unknown(nt));
1288	}
1289}
1290
1291static struct {
1292	const char *name;
1293	int value;
1294} l_flag[] = {
1295	{"EXACT_MATCH", LL_EXACT_MATCH},
1296	{"IGNORE_INT_VER", LL_IGNORE_INT_VER},
1297	{"REQUIRE_MINOR", LL_REQUIRE_MINOR},
1298	{"EXPORTS", LL_EXPORTS},
1299	{"DELAY_LOAD", LL_DELAY_LOAD},
1300	{"DELTA", LL_DELTA},
1301	{NULL, 0}
1302};
1303
1304static struct mips_option mips_exceptions_option[] = {
1305	{OEX_PAGE0, "PAGE0"},
1306	{OEX_SMM, "SMM"},
1307	{OEX_PRECISEFP, "PRECISEFP"},
1308	{OEX_DISMISS, "DISMISS"},
1309	{0, NULL}
1310};
1311
1312static struct mips_option mips_pad_option[] = {
1313	{OPAD_PREFIX, "PREFIX"},
1314	{OPAD_POSTFIX, "POSTFIX"},
1315	{OPAD_SYMBOL, "SYMBOL"},
1316	{0, NULL}
1317};
1318
1319static struct mips_option mips_hwpatch_option[] = {
1320	{OHW_R4KEOP, "R4KEOP"},
1321	{OHW_R8KPFETCH, "R8KPFETCH"},
1322	{OHW_R5KEOP, "R5KEOP"},
1323	{OHW_R5KCVTL, "R5KCVTL"},
1324	{0, NULL}
1325};
1326
1327static struct mips_option mips_hwa_option[] = {
1328	{OHWA0_R4KEOP_CHECKED, "R4KEOP_CHECKED"},
1329	{OHWA0_R4KEOP_CLEAN, "R4KEOP_CLEAN"},
1330	{0, NULL}
1331};
1332
1333static struct mips_option mips_hwo_option[] = {
1334	{OHWO0_FIXADE, "FIXADE"},
1335	{0, NULL}
1336};
1337
1338static const char *
1339option_kind(uint8_t kind)
1340{
1341	static char s_kind[32];
1342
1343	switch (kind) {
1344	case ODK_NULL: return "NULL";
1345	case ODK_REGINFO: return "REGINFO";
1346	case ODK_EXCEPTIONS: return "EXCEPTIONS";
1347	case ODK_PAD: return "PAD";
1348	case ODK_HWPATCH: return "HWPATCH";
1349	case ODK_FILL: return "FILL";
1350	case ODK_TAGS: return "TAGS";
1351	case ODK_HWAND: return "HWAND";
1352	case ODK_HWOR: return "HWOR";
1353	case ODK_GP_GROUP: return "GP_GROUP";
1354	case ODK_IDENT: return "IDENT";
1355	default:
1356		snprintf(s_kind, sizeof(s_kind), "<unknown: %u>", kind);
1357		return (s_kind);
1358	}
1359}
1360
1361static const char *
1362top_tag(unsigned int tag)
1363{
1364	static char s_top_tag[32];
1365
1366	switch (tag) {
1367	case 1: return "File Attributes";
1368	case 2: return "Section Attributes";
1369	case 3: return "Symbol Attributes";
1370	default:
1371		snprintf(s_top_tag, sizeof(s_top_tag), "Unknown tag: %u", tag);
1372		return (s_top_tag);
1373	}
1374}
1375
1376static const char *
1377aeabi_cpu_arch(uint64_t arch)
1378{
1379	static char s_cpu_arch[32];
1380
1381	switch (arch) {
1382	case 0: return "Pre-V4";
1383	case 1: return "ARM v4";
1384	case 2: return "ARM v4T";
1385	case 3: return "ARM v5T";
1386	case 4: return "ARM v5TE";
1387	case 5: return "ARM v5TEJ";
1388	case 6: return "ARM v6";
1389	case 7: return "ARM v6KZ";
1390	case 8: return "ARM v6T2";
1391	case 9: return "ARM v6K";
1392	case 10: return "ARM v7";
1393	case 11: return "ARM v6-M";
1394	case 12: return "ARM v6S-M";
1395	case 13: return "ARM v7E-M";
1396	default:
1397		snprintf(s_cpu_arch, sizeof(s_cpu_arch),
1398		    "Unknown (%ju)", (uintmax_t) arch);
1399		return (s_cpu_arch);
1400	}
1401}
1402
1403static const char *
1404aeabi_cpu_arch_profile(uint64_t pf)
1405{
1406	static char s_arch_profile[32];
1407
1408	switch (pf) {
1409	case 0:
1410		return "Not applicable";
1411	case 0x41:		/* 'A' */
1412		return "Application Profile";
1413	case 0x52:		/* 'R' */
1414		return "Real-Time Profile";
1415	case 0x4D:		/* 'M' */
1416		return "Microcontroller Profile";
1417	case 0x53:		/* 'S' */
1418		return "Application or Real-Time Profile";
1419	default:
1420		snprintf(s_arch_profile, sizeof(s_arch_profile),
1421		    "Unknown (%ju)\n", (uintmax_t) pf);
1422		return (s_arch_profile);
1423	}
1424}
1425
1426static const char *
1427aeabi_arm_isa(uint64_t ai)
1428{
1429	static char s_ai[32];
1430
1431	switch (ai) {
1432	case 0: return "No";
1433	case 1: return "Yes";
1434	default:
1435		snprintf(s_ai, sizeof(s_ai), "Unknown (%ju)\n",
1436		    (uintmax_t) ai);
1437		return (s_ai);
1438	}
1439}
1440
1441static const char *
1442aeabi_thumb_isa(uint64_t ti)
1443{
1444	static char s_ti[32];
1445
1446	switch (ti) {
1447	case 0: return "No";
1448	case 1: return "16-bit Thumb";
1449	case 2: return "32-bit Thumb";
1450	default:
1451		snprintf(s_ti, sizeof(s_ti), "Unknown (%ju)\n",
1452		    (uintmax_t) ti);
1453		return (s_ti);
1454	}
1455}
1456
1457static const char *
1458aeabi_fp_arch(uint64_t fp)
1459{
1460	static char s_fp_arch[32];
1461
1462	switch (fp) {
1463	case 0: return "No";
1464	case 1: return "VFPv1";
1465	case 2: return "VFPv2";
1466	case 3: return "VFPv3";
1467	case 4: return "VFPv3-D16";
1468	case 5: return "VFPv4";
1469	case 6: return "VFPv4-D16";
1470	default:
1471		snprintf(s_fp_arch, sizeof(s_fp_arch), "Unknown (%ju)",
1472		    (uintmax_t) fp);
1473		return (s_fp_arch);
1474	}
1475}
1476
1477static const char *
1478aeabi_wmmx_arch(uint64_t wmmx)
1479{
1480	static char s_wmmx[32];
1481
1482	switch (wmmx) {
1483	case 0: return "No";
1484	case 1: return "WMMXv1";
1485	case 2: return "WMMXv2";
1486	default:
1487		snprintf(s_wmmx, sizeof(s_wmmx), "Unknown (%ju)",
1488		    (uintmax_t) wmmx);
1489		return (s_wmmx);
1490	}
1491}
1492
1493static const char *
1494aeabi_adv_simd_arch(uint64_t simd)
1495{
1496	static char s_simd[32];
1497
1498	switch (simd) {
1499	case 0: return "No";
1500	case 1: return "NEONv1";
1501	case 2: return "NEONv2";
1502	default:
1503		snprintf(s_simd, sizeof(s_simd), "Unknown (%ju)",
1504		    (uintmax_t) simd);
1505		return (s_simd);
1506	}
1507}
1508
1509static const char *
1510aeabi_pcs_config(uint64_t pcs)
1511{
1512	static char s_pcs[32];
1513
1514	switch (pcs) {
1515	case 0: return "None";
1516	case 1: return "Bare platform";
1517	case 2: return "Linux";
1518	case 3: return "Linux DSO";
1519	case 4: return "Palm OS 2004";
1520	case 5: return "Palm OS (future)";
1521	case 6: return "Symbian OS 2004";
1522	case 7: return "Symbian OS (future)";
1523	default:
1524		snprintf(s_pcs, sizeof(s_pcs), "Unknown (%ju)",
1525		    (uintmax_t) pcs);
1526		return (s_pcs);
1527	}
1528}
1529
1530static const char *
1531aeabi_pcs_r9(uint64_t r9)
1532{
1533	static char s_r9[32];
1534
1535	switch (r9) {
1536	case 0: return "V6";
1537	case 1: return "SB";
1538	case 2: return "TLS pointer";
1539	case 3: return "Unused";
1540	default:
1541		snprintf(s_r9, sizeof(s_r9), "Unknown (%ju)", (uintmax_t) r9);
1542		return (s_r9);
1543	}
1544}
1545
1546static const char *
1547aeabi_pcs_rw(uint64_t rw)
1548{
1549	static char s_rw[32];
1550
1551	switch (rw) {
1552	case 0: return "Absolute";
1553	case 1: return "PC-relative";
1554	case 2: return "SB-relative";
1555	case 3: return "None";
1556	default:
1557		snprintf(s_rw, sizeof(s_rw), "Unknown (%ju)", (uintmax_t) rw);
1558		return (s_rw);
1559	}
1560}
1561
1562static const char *
1563aeabi_pcs_ro(uint64_t ro)
1564{
1565	static char s_ro[32];
1566
1567	switch (ro) {
1568	case 0: return "Absolute";
1569	case 1: return "PC-relative";
1570	case 2: return "None";
1571	default:
1572		snprintf(s_ro, sizeof(s_ro), "Unknown (%ju)", (uintmax_t) ro);
1573		return (s_ro);
1574	}
1575}
1576
1577static const char *
1578aeabi_pcs_got(uint64_t got)
1579{
1580	static char s_got[32];
1581
1582	switch (got) {
1583	case 0: return "None";
1584	case 1: return "direct";
1585	case 2: return "indirect via GOT";
1586	default:
1587		snprintf(s_got, sizeof(s_got), "Unknown (%ju)",
1588		    (uintmax_t) got);
1589		return (s_got);
1590	}
1591}
1592
1593static const char *
1594aeabi_pcs_wchar_t(uint64_t wt)
1595{
1596	static char s_wt[32];
1597
1598	switch (wt) {
1599	case 0: return "None";
1600	case 2: return "wchar_t size 2";
1601	case 4: return "wchar_t size 4";
1602	default:
1603		snprintf(s_wt, sizeof(s_wt), "Unknown (%ju)", (uintmax_t) wt);
1604		return (s_wt);
1605	}
1606}
1607
1608static const char *
1609aeabi_enum_size(uint64_t es)
1610{
1611	static char s_es[32];
1612
1613	switch (es) {
1614	case 0: return "None";
1615	case 1: return "smallest";
1616	case 2: return "32-bit";
1617	case 3: return "visible 32-bit";
1618	default:
1619		snprintf(s_es, sizeof(s_es), "Unknown (%ju)", (uintmax_t) es);
1620		return (s_es);
1621	}
1622}
1623
1624static const char *
1625aeabi_align_needed(uint64_t an)
1626{
1627	static char s_align_n[64];
1628
1629	switch (an) {
1630	case 0: return "No";
1631	case 1: return "8-byte align";
1632	case 2: return "4-byte align";
1633	case 3: return "Reserved";
1634	default:
1635		if (an >= 4 && an <= 12)
1636			snprintf(s_align_n, sizeof(s_align_n), "8-byte align"
1637			    " and up to 2^%ju-byte extended align",
1638			    (uintmax_t) an);
1639		else
1640			snprintf(s_align_n, sizeof(s_align_n), "Unknown (%ju)",
1641			    (uintmax_t) an);
1642		return (s_align_n);
1643	}
1644}
1645
1646static const char *
1647aeabi_align_preserved(uint64_t ap)
1648{
1649	static char s_align_p[128];
1650
1651	switch (ap) {
1652	case 0: return "No";
1653	case 1: return "8-byte align";
1654	case 2: return "8-byte align and SP % 8 == 0";
1655	case 3: return "Reserved";
1656	default:
1657		if (ap >= 4 && ap <= 12)
1658			snprintf(s_align_p, sizeof(s_align_p), "8-byte align"
1659			    " and SP %% 8 == 0 and up to 2^%ju-byte extended"
1660			    " align", (uintmax_t) ap);
1661		else
1662			snprintf(s_align_p, sizeof(s_align_p), "Unknown (%ju)",
1663			    (uintmax_t) ap);
1664		return (s_align_p);
1665	}
1666}
1667
1668static const char *
1669aeabi_fp_rounding(uint64_t fr)
1670{
1671	static char s_fp_r[32];
1672
1673	switch (fr) {
1674	case 0: return "Unused";
1675	case 1: return "Needed";
1676	default:
1677		snprintf(s_fp_r, sizeof(s_fp_r), "Unknown (%ju)",
1678		    (uintmax_t) fr);
1679		return (s_fp_r);
1680	}
1681}
1682
1683static const char *
1684aeabi_fp_denormal(uint64_t fd)
1685{
1686	static char s_fp_d[32];
1687
1688	switch (fd) {
1689	case 0: return "Unused";
1690	case 1: return "Needed";
1691	case 2: return "Sign Only";
1692	default:
1693		snprintf(s_fp_d, sizeof(s_fp_d), "Unknown (%ju)",
1694		    (uintmax_t) fd);
1695		return (s_fp_d);
1696	}
1697}
1698
1699static const char *
1700aeabi_fp_exceptions(uint64_t fe)
1701{
1702	static char s_fp_e[32];
1703
1704	switch (fe) {
1705	case 0: return "Unused";
1706	case 1: return "Needed";
1707	default:
1708		snprintf(s_fp_e, sizeof(s_fp_e), "Unknown (%ju)",
1709		    (uintmax_t) fe);
1710		return (s_fp_e);
1711	}
1712}
1713
1714static const char *
1715aeabi_fp_user_exceptions(uint64_t fu)
1716{
1717	static char s_fp_u[32];
1718
1719	switch (fu) {
1720	case 0: return "Unused";
1721	case 1: return "Needed";
1722	default:
1723		snprintf(s_fp_u, sizeof(s_fp_u), "Unknown (%ju)",
1724		    (uintmax_t) fu);
1725		return (s_fp_u);
1726	}
1727}
1728
1729static const char *
1730aeabi_fp_number_model(uint64_t fn)
1731{
1732	static char s_fp_n[32];
1733
1734	switch (fn) {
1735	case 0: return "Unused";
1736	case 1: return "IEEE 754 normal";
1737	case 2: return "RTABI";
1738	case 3: return "IEEE 754";
1739	default:
1740		snprintf(s_fp_n, sizeof(s_fp_n), "Unknown (%ju)",
1741		    (uintmax_t) fn);
1742		return (s_fp_n);
1743	}
1744}
1745
1746static const char *
1747aeabi_fp_16bit_format(uint64_t fp16)
1748{
1749	static char s_fp_16[64];
1750
1751	switch (fp16) {
1752	case 0: return "None";
1753	case 1: return "IEEE 754";
1754	case 2: return "VFPv3/Advanced SIMD (alternative format)";
1755	default:
1756		snprintf(s_fp_16, sizeof(s_fp_16), "Unknown (%ju)",
1757		    (uintmax_t) fp16);
1758		return (s_fp_16);
1759	}
1760}
1761
1762static const char *
1763aeabi_mpext(uint64_t mp)
1764{
1765	static char s_mp[32];
1766
1767	switch (mp) {
1768	case 0: return "Not allowed";
1769	case 1: return "Allowed";
1770	default:
1771		snprintf(s_mp, sizeof(s_mp), "Unknown (%ju)",
1772		    (uintmax_t) mp);
1773		return (s_mp);
1774	}
1775}
1776
1777static const char *
1778aeabi_div(uint64_t du)
1779{
1780	static char s_du[32];
1781
1782	switch (du) {
1783	case 0: return "Yes (V7-R/V7-M)";
1784	case 1: return "No";
1785	case 2: return "Yes (V7-A)";
1786	default:
1787		snprintf(s_du, sizeof(s_du), "Unknown (%ju)",
1788		    (uintmax_t) du);
1789		return (s_du);
1790	}
1791}
1792
1793static const char *
1794aeabi_t2ee(uint64_t t2ee)
1795{
1796	static char s_t2ee[32];
1797
1798	switch (t2ee) {
1799	case 0: return "Not allowed";
1800	case 1: return "Allowed";
1801	default:
1802		snprintf(s_t2ee, sizeof(s_t2ee), "Unknown(%ju)",
1803		    (uintmax_t) t2ee);
1804		return (s_t2ee);
1805	}
1806
1807}
1808
1809static const char *
1810aeabi_hardfp(uint64_t hfp)
1811{
1812	static char s_hfp[32];
1813
1814	switch (hfp) {
1815	case 0: return "Tag_FP_arch";
1816	case 1: return "only SP";
1817	case 2: return "only DP";
1818	case 3: return "both SP and DP";
1819	default:
1820		snprintf(s_hfp, sizeof(s_hfp), "Unknown (%ju)",
1821		    (uintmax_t) hfp);
1822		return (s_hfp);
1823	}
1824}
1825
1826static const char *
1827aeabi_vfp_args(uint64_t va)
1828{
1829	static char s_va[32];
1830
1831	switch (va) {
1832	case 0: return "AAPCS (base variant)";
1833	case 1: return "AAPCS (VFP variant)";
1834	case 2: return "toolchain-specific";
1835	default:
1836		snprintf(s_va, sizeof(s_va), "Unknown (%ju)", (uintmax_t) va);
1837		return (s_va);
1838	}
1839}
1840
1841static const char *
1842aeabi_wmmx_args(uint64_t wa)
1843{
1844	static char s_wa[32];
1845
1846	switch (wa) {
1847	case 0: return "AAPCS (base variant)";
1848	case 1: return "Intel WMMX";
1849	case 2: return "toolchain-specific";
1850	default:
1851		snprintf(s_wa, sizeof(s_wa), "Unknown(%ju)", (uintmax_t) wa);
1852		return (s_wa);
1853	}
1854}
1855
1856static const char *
1857aeabi_unaligned_access(uint64_t ua)
1858{
1859	static char s_ua[32];
1860
1861	switch (ua) {
1862	case 0: return "Not allowed";
1863	case 1: return "Allowed";
1864	default:
1865		snprintf(s_ua, sizeof(s_ua), "Unknown(%ju)", (uintmax_t) ua);
1866		return (s_ua);
1867	}
1868}
1869
1870static const char *
1871aeabi_fp_hpext(uint64_t fh)
1872{
1873	static char s_fh[32];
1874
1875	switch (fh) {
1876	case 0: return "Not allowed";
1877	case 1: return "Allowed";
1878	default:
1879		snprintf(s_fh, sizeof(s_fh), "Unknown(%ju)", (uintmax_t) fh);
1880		return (s_fh);
1881	}
1882}
1883
1884static const char *
1885aeabi_optm_goal(uint64_t og)
1886{
1887	static char s_og[32];
1888
1889	switch (og) {
1890	case 0: return "None";
1891	case 1: return "Speed";
1892	case 2: return "Speed aggressive";
1893	case 3: return "Space";
1894	case 4: return "Space aggressive";
1895	case 5: return "Debugging";
1896	case 6: return "Best Debugging";
1897	default:
1898		snprintf(s_og, sizeof(s_og), "Unknown(%ju)", (uintmax_t) og);
1899		return (s_og);
1900	}
1901}
1902
1903static const char *
1904aeabi_fp_optm_goal(uint64_t fog)
1905{
1906	static char s_fog[32];
1907
1908	switch (fog) {
1909	case 0: return "None";
1910	case 1: return "Speed";
1911	case 2: return "Speed aggressive";
1912	case 3: return "Space";
1913	case 4: return "Space aggressive";
1914	case 5: return "Accurary";
1915	case 6: return "Best Accurary";
1916	default:
1917		snprintf(s_fog, sizeof(s_fog), "Unknown(%ju)",
1918		    (uintmax_t) fog);
1919		return (s_fog);
1920	}
1921}
1922
1923static const char *
1924aeabi_virtual(uint64_t vt)
1925{
1926	static char s_virtual[64];
1927
1928	switch (vt) {
1929	case 0: return "No";
1930	case 1: return "TrustZone";
1931	case 2: return "Virtualization extension";
1932	case 3: return "TrustZone and virtualization extension";
1933	default:
1934		snprintf(s_virtual, sizeof(s_virtual), "Unknown(%ju)",
1935		    (uintmax_t) vt);
1936		return (s_virtual);
1937	}
1938}
1939
1940static struct {
1941	uint64_t tag;
1942	const char *s_tag;
1943	const char *(*get_desc)(uint64_t val);
1944} aeabi_tags[] = {
1945	{4, "Tag_CPU_raw_name", NULL},
1946	{5, "Tag_CPU_name", NULL},
1947	{6, "Tag_CPU_arch", aeabi_cpu_arch},
1948	{7, "Tag_CPU_arch_profile", aeabi_cpu_arch_profile},
1949	{8, "Tag_ARM_ISA_use", aeabi_arm_isa},
1950	{9, "Tag_THUMB_ISA_use", aeabi_thumb_isa},
1951	{10, "Tag_FP_arch", aeabi_fp_arch},
1952	{11, "Tag_WMMX_arch", aeabi_wmmx_arch},
1953	{12, "Tag_Advanced_SIMD_arch", aeabi_adv_simd_arch},
1954	{13, "Tag_PCS_config", aeabi_pcs_config},
1955	{14, "Tag_ABI_PCS_R9_use", aeabi_pcs_r9},
1956	{15, "Tag_ABI_PCS_RW_data", aeabi_pcs_rw},
1957	{16, "Tag_ABI_PCS_RO_data", aeabi_pcs_ro},
1958	{17, "Tag_ABI_PCS_GOT_use", aeabi_pcs_got},
1959	{18, "Tag_ABI_PCS_wchar_t", aeabi_pcs_wchar_t},
1960	{19, "Tag_ABI_FP_rounding", aeabi_fp_rounding},
1961	{20, "Tag_ABI_FP_denormal", aeabi_fp_denormal},
1962	{21, "Tag_ABI_FP_exceptions", aeabi_fp_exceptions},
1963	{22, "Tag_ABI_FP_user_exceptions", aeabi_fp_user_exceptions},
1964	{23, "Tag_ABI_FP_number_model", aeabi_fp_number_model},
1965	{24, "Tag_ABI_align_needed", aeabi_align_needed},
1966	{25, "Tag_ABI_align_preserved", aeabi_align_preserved},
1967	{26, "Tag_ABI_enum_size", aeabi_enum_size},
1968	{27, "Tag_ABI_HardFP_use", aeabi_hardfp},
1969	{28, "Tag_ABI_VFP_args", aeabi_vfp_args},
1970	{29, "Tag_ABI_WMMX_args", aeabi_wmmx_args},
1971	{30, "Tag_ABI_optimization_goals", aeabi_optm_goal},
1972	{31, "Tag_ABI_FP_optimization_goals", aeabi_fp_optm_goal},
1973	{32, "Tag_compatibility", NULL},
1974	{34, "Tag_CPU_unaligned_access", aeabi_unaligned_access},
1975	{36, "Tag_FP_HP_extension", aeabi_fp_hpext},
1976	{38, "Tag_ABI_FP_16bit_format", aeabi_fp_16bit_format},
1977	{42, "Tag_MPextension_use", aeabi_mpext},
1978	{44, "Tag_DIV_use", aeabi_div},
1979	{64, "Tag_nodefaults", NULL},
1980	{65, "Tag_also_compatible_with", NULL},
1981	{66, "Tag_T2EE_use", aeabi_t2ee},
1982	{67, "Tag_conformance", NULL},
1983	{68, "Tag_Virtualization_use", aeabi_virtual},
1984	{70, "Tag_MPextension_use", aeabi_mpext},
1985};
1986
1987static const char *
1988mips_abi_fp(uint64_t fp)
1989{
1990	static char s_mips_abi_fp[64];
1991
1992	switch (fp) {
1993	case 0: return "N/A";
1994	case 1: return "Hard float (double precision)";
1995	case 2: return "Hard float (single precision)";
1996	case 3: return "Soft float";
1997	case 4: return "64-bit float (-mips32r2 -mfp64)";
1998	default:
1999		snprintf(s_mips_abi_fp, sizeof(s_mips_abi_fp), "Unknown(%ju)",
2000		    (uintmax_t) fp);
2001		return (s_mips_abi_fp);
2002	}
2003}
2004
2005static const char *
2006ppc_abi_fp(uint64_t fp)
2007{
2008	static char s_ppc_abi_fp[64];
2009
2010	switch (fp) {
2011	case 0: return "N/A";
2012	case 1: return "Hard float (double precision)";
2013	case 2: return "Soft float";
2014	case 3: return "Hard float (single precision)";
2015	default:
2016		snprintf(s_ppc_abi_fp, sizeof(s_ppc_abi_fp), "Unknown(%ju)",
2017		    (uintmax_t) fp);
2018		return (s_ppc_abi_fp);
2019	}
2020}
2021
2022static const char *
2023ppc_abi_vector(uint64_t vec)
2024{
2025	static char s_vec[64];
2026
2027	switch (vec) {
2028	case 0: return "N/A";
2029	case 1: return "Generic purpose registers";
2030	case 2: return "AltiVec registers";
2031	case 3: return "SPE registers";
2032	default:
2033		snprintf(s_vec, sizeof(s_vec), "Unknown(%ju)", (uintmax_t) vec);
2034		return (s_vec);
2035	}
2036}
2037
2038static const char *
2039dwarf_reg(unsigned int mach, unsigned int reg)
2040{
2041
2042	switch (mach) {
2043	case EM_386:
2044	case EM_IAMCU:
2045		switch (reg) {
2046		case 0: return "eax";
2047		case 1: return "ecx";
2048		case 2: return "edx";
2049		case 3: return "ebx";
2050		case 4: return "esp";
2051		case 5: return "ebp";
2052		case 6: return "esi";
2053		case 7: return "edi";
2054		case 8: return "eip";
2055		case 9: return "eflags";
2056		case 11: return "st0";
2057		case 12: return "st1";
2058		case 13: return "st2";
2059		case 14: return "st3";
2060		case 15: return "st4";
2061		case 16: return "st5";
2062		case 17: return "st6";
2063		case 18: return "st7";
2064		case 21: return "xmm0";
2065		case 22: return "xmm1";
2066		case 23: return "xmm2";
2067		case 24: return "xmm3";
2068		case 25: return "xmm4";
2069		case 26: return "xmm5";
2070		case 27: return "xmm6";
2071		case 28: return "xmm7";
2072		case 29: return "mm0";
2073		case 30: return "mm1";
2074		case 31: return "mm2";
2075		case 32: return "mm3";
2076		case 33: return "mm4";
2077		case 34: return "mm5";
2078		case 35: return "mm6";
2079		case 36: return "mm7";
2080		case 37: return "fcw";
2081		case 38: return "fsw";
2082		case 39: return "mxcsr";
2083		case 40: return "es";
2084		case 41: return "cs";
2085		case 42: return "ss";
2086		case 43: return "ds";
2087		case 44: return "fs";
2088		case 45: return "gs";
2089		case 48: return "tr";
2090		case 49: return "ldtr";
2091		default: return (NULL);
2092		}
2093	case EM_RISCV:
2094		switch (reg) {
2095		case 0: return "zero";
2096		case 1: return "ra";
2097		case 2: return "sp";
2098		case 3: return "gp";
2099		case 4: return "tp";
2100		case 5: return "t0";
2101		case 6: return "t1";
2102		case 7: return "t2";
2103		case 8: return "s0";
2104		case 9: return "s1";
2105		case 10: return "a0";
2106		case 11: return "a1";
2107		case 12: return "a2";
2108		case 13: return "a3";
2109		case 14: return "a4";
2110		case 15: return "a5";
2111		case 16: return "a6";
2112		case 17: return "a7";
2113		case 18: return "s2";
2114		case 19: return "s3";
2115		case 20: return "s4";
2116		case 21: return "s5";
2117		case 22: return "s6";
2118		case 23: return "s7";
2119		case 24: return "s8";
2120		case 25: return "s9";
2121		case 26: return "s10";
2122		case 27: return "s11";
2123		case 28: return "t3";
2124		case 29: return "t4";
2125		case 30: return "t5";
2126		case 31: return "t6";
2127		case 32: return "ft0";
2128		case 33: return "ft1";
2129		case 34: return "ft2";
2130		case 35: return "ft3";
2131		case 36: return "ft4";
2132		case 37: return "ft5";
2133		case 38: return "ft6";
2134		case 39: return "ft7";
2135		case 40: return "fs0";
2136		case 41: return "fs1";
2137		case 42: return "fa0";
2138		case 43: return "fa1";
2139		case 44: return "fa2";
2140		case 45: return "fa3";
2141		case 46: return "fa4";
2142		case 47: return "fa5";
2143		case 48: return "fa6";
2144		case 49: return "fa7";
2145		case 50: return "fs2";
2146		case 51: return "fs3";
2147		case 52: return "fs4";
2148		case 53: return "fs5";
2149		case 54: return "fs6";
2150		case 55: return "fs7";
2151		case 56: return "fs8";
2152		case 57: return "fs9";
2153		case 58: return "fs10";
2154		case 59: return "fs11";
2155		case 60: return "ft8";
2156		case 61: return "ft9";
2157		case 62: return "ft10";
2158		case 63: return "ft11";
2159		default: return (NULL);
2160		}
2161	case EM_X86_64:
2162		switch (reg) {
2163		case 0: return "rax";
2164		case 1: return "rdx";
2165		case 2: return "rcx";
2166		case 3: return "rbx";
2167		case 4: return "rsi";
2168		case 5: return "rdi";
2169		case 6: return "rbp";
2170		case 7: return "rsp";
2171		case 16: return "rip";
2172		case 17: return "xmm0";
2173		case 18: return "xmm1";
2174		case 19: return "xmm2";
2175		case 20: return "xmm3";
2176		case 21: return "xmm4";
2177		case 22: return "xmm5";
2178		case 23: return "xmm6";
2179		case 24: return "xmm7";
2180		case 25: return "xmm8";
2181		case 26: return "xmm9";
2182		case 27: return "xmm10";
2183		case 28: return "xmm11";
2184		case 29: return "xmm12";
2185		case 30: return "xmm13";
2186		case 31: return "xmm14";
2187		case 32: return "xmm15";
2188		case 33: return "st0";
2189		case 34: return "st1";
2190		case 35: return "st2";
2191		case 36: return "st3";
2192		case 37: return "st4";
2193		case 38: return "st5";
2194		case 39: return "st6";
2195		case 40: return "st7";
2196		case 41: return "mm0";
2197		case 42: return "mm1";
2198		case 43: return "mm2";
2199		case 44: return "mm3";
2200		case 45: return "mm4";
2201		case 46: return "mm5";
2202		case 47: return "mm6";
2203		case 48: return "mm7";
2204		case 49: return "rflags";
2205		case 50: return "es";
2206		case 51: return "cs";
2207		case 52: return "ss";
2208		case 53: return "ds";
2209		case 54: return "fs";
2210		case 55: return "gs";
2211		case 58: return "fs.base";
2212		case 59: return "gs.base";
2213		case 62: return "tr";
2214		case 63: return "ldtr";
2215		case 64: return "mxcsr";
2216		case 65: return "fcw";
2217		case 66: return "fsw";
2218		default: return (NULL);
2219		}
2220	default:
2221		return (NULL);
2222	}
2223}
2224
2225static void
2226dump_ehdr(struct readelf *re)
2227{
2228	size_t		 phnum, shnum, shstrndx;
2229	int		 i;
2230
2231	printf("ELF Header:\n");
2232
2233	/* e_ident[]. */
2234	printf("  Magic:   ");
2235	for (i = 0; i < EI_NIDENT; i++)
2236		printf("%.2x ", re->ehdr.e_ident[i]);
2237	putchar('\n');
2238
2239	/* EI_CLASS. */
2240	printf("%-37s%s\n", "  Class:", elf_class(re->ehdr.e_ident[EI_CLASS]));
2241
2242	/* EI_DATA. */
2243	printf("%-37s%s\n", "  Data:", elf_endian(re->ehdr.e_ident[EI_DATA]));
2244
2245	/* EI_VERSION. */
2246	printf("%-37s%d %s\n", "  Version:", re->ehdr.e_ident[EI_VERSION],
2247	    elf_ver(re->ehdr.e_ident[EI_VERSION]));
2248
2249	/* EI_OSABI. */
2250	printf("%-37s%s\n", "  OS/ABI:", elf_osabi(re->ehdr.e_ident[EI_OSABI]));
2251
2252	/* EI_ABIVERSION. */
2253	printf("%-37s%d\n", "  ABI Version:", re->ehdr.e_ident[EI_ABIVERSION]);
2254
2255	/* e_type. */
2256	printf("%-37s%s\n", "  Type:", elf_type(re->ehdr.e_type));
2257
2258	/* e_machine. */
2259	printf("%-37s%s\n", "  Machine:", elf_machine(re->ehdr.e_machine));
2260
2261	/* e_version. */
2262	printf("%-37s%#x\n", "  Version:", re->ehdr.e_version);
2263
2264	/* e_entry. */
2265	printf("%-37s%#jx\n", "  Entry point address:",
2266	    (uintmax_t)re->ehdr.e_entry);
2267
2268	/* e_phoff. */
2269	printf("%-37s%ju (bytes into file)\n", "  Start of program headers:",
2270	    (uintmax_t)re->ehdr.e_phoff);
2271
2272	/* e_shoff. */
2273	printf("%-37s%ju (bytes into file)\n", "  Start of section headers:",
2274	    (uintmax_t)re->ehdr.e_shoff);
2275
2276	/* e_flags. */
2277	printf("%-37s%#x", "  Flags:", re->ehdr.e_flags);
2278	dump_eflags(re, re->ehdr.e_flags);
2279	putchar('\n');
2280
2281	/* e_ehsize. */
2282	printf("%-37s%u (bytes)\n", "  Size of this header:",
2283	    re->ehdr.e_ehsize);
2284
2285	/* e_phentsize. */
2286	printf("%-37s%u (bytes)\n", "  Size of program headers:",
2287	    re->ehdr.e_phentsize);
2288
2289	/* e_phnum. */
2290	printf("%-37s%u", "  Number of program headers:", re->ehdr.e_phnum);
2291	if (re->ehdr.e_phnum == PN_XNUM) {
2292		/* Extended program header numbering is in use. */
2293		if (elf_getphnum(re->elf, &phnum))
2294			printf(" (%zu)", phnum);
2295	}
2296	putchar('\n');
2297
2298	/* e_shentsize. */
2299	printf("%-37s%u (bytes)\n", "  Size of section headers:",
2300	    re->ehdr.e_shentsize);
2301
2302	/* e_shnum. */
2303	printf("%-37s%u", "  Number of section headers:", re->ehdr.e_shnum);
2304	if (re->ehdr.e_shnum == SHN_UNDEF) {
2305		/* Extended section numbering is in use. */
2306		if (elf_getshnum(re->elf, &shnum))
2307			printf(" (%ju)", (uintmax_t)shnum);
2308	}
2309	putchar('\n');
2310
2311	/* e_shstrndx. */
2312	printf("%-37s%u", "  Section header string table index:",
2313	    re->ehdr.e_shstrndx);
2314	if (re->ehdr.e_shstrndx == SHN_XINDEX) {
2315		/* Extended section numbering is in use. */
2316		if (elf_getshstrndx(re->elf, &shstrndx))
2317			printf(" (%ju)", (uintmax_t)shstrndx);
2318	}
2319	putchar('\n');
2320}
2321
2322static void
2323dump_eflags(struct readelf *re, uint64_t e_flags)
2324{
2325	struct eflags_desc *edesc;
2326	int arm_eabi;
2327
2328	edesc = NULL;
2329	switch (re->ehdr.e_machine) {
2330	case EM_ARM:
2331		arm_eabi = (e_flags & EF_ARM_EABIMASK) >> 24;
2332		if (arm_eabi == 0)
2333			printf(", GNU EABI");
2334		else if (arm_eabi <= 5)
2335			printf(", Version%d EABI", arm_eabi);
2336		edesc = arm_eflags_desc;
2337		break;
2338	case EM_MIPS:
2339	case EM_MIPS_RS3_LE:
2340		switch ((e_flags & EF_MIPS_ARCH) >> 28) {
2341		case 0:	printf(", mips1"); break;
2342		case 1: printf(", mips2"); break;
2343		case 2: printf(", mips3"); break;
2344		case 3: printf(", mips4"); break;
2345		case 4: printf(", mips5"); break;
2346		case 5: printf(", mips32"); break;
2347		case 6: printf(", mips64"); break;
2348		case 7: printf(", mips32r2"); break;
2349		case 8: printf(", mips64r2"); break;
2350		default: break;
2351		}
2352		switch ((e_flags & 0x00FF0000) >> 16) {
2353		case 0x81: printf(", 3900"); break;
2354		case 0x82: printf(", 4010"); break;
2355		case 0x83: printf(", 4100"); break;
2356		case 0x85: printf(", 4650"); break;
2357		case 0x87: printf(", 4120"); break;
2358		case 0x88: printf(", 4111"); break;
2359		case 0x8a: printf(", sb1"); break;
2360		case 0x8b: printf(", octeon"); break;
2361		case 0x8c: printf(", xlr"); break;
2362		case 0x91: printf(", 5400"); break;
2363		case 0x98: printf(", 5500"); break;
2364		case 0x99: printf(", 9000"); break;
2365		case 0xa0: printf(", loongson-2e"); break;
2366		case 0xa1: printf(", loongson-2f"); break;
2367		default: break;
2368		}
2369		switch ((e_flags & 0x0000F000) >> 12) {
2370		case 1: printf(", o32"); break;
2371		case 2: printf(", o64"); break;
2372		case 3: printf(", eabi32"); break;
2373		case 4: printf(", eabi64"); break;
2374		default: break;
2375		}
2376		edesc = mips_eflags_desc;
2377		break;
2378	case EM_PPC64:
2379		switch (e_flags) {
2380		case 0: printf(", Unspecified or Power ELF V1 ABI"); break;
2381		case 1: printf(", Power ELF V1 ABI"); break;
2382		case 2: printf(", OpenPOWER ELF V2 ABI"); break;
2383		default: break;
2384		}
2385		/* FALLTHROUGH */
2386	case EM_PPC:
2387		edesc = powerpc_eflags_desc;
2388		break;
2389	case EM_RISCV:
2390		switch (e_flags & EF_RISCV_FLOAT_ABI_MASK) {
2391		case EF_RISCV_FLOAT_ABI_SOFT:
2392			printf(", soft-float ABI");
2393			break;
2394		case EF_RISCV_FLOAT_ABI_SINGLE:
2395			printf(", single-float ABI");
2396			break;
2397		case EF_RISCV_FLOAT_ABI_DOUBLE:
2398			printf(", double-float ABI");
2399			break;
2400		case EF_RISCV_FLOAT_ABI_QUAD:
2401			printf(", quad-float ABI");
2402			break;
2403		}
2404		edesc = riscv_eflags_desc;
2405		break;
2406	case EM_SPARC:
2407	case EM_SPARC32PLUS:
2408	case EM_SPARCV9:
2409		switch ((e_flags & EF_SPARCV9_MM)) {
2410		case EF_SPARCV9_TSO: printf(", tso"); break;
2411		case EF_SPARCV9_PSO: printf(", pso"); break;
2412		case EF_SPARCV9_MM: printf(", rmo"); break;
2413		default: break;
2414		}
2415		edesc = sparc_eflags_desc;
2416		break;
2417	default:
2418		break;
2419	}
2420
2421	if (edesc != NULL) {
2422		while (edesc->desc != NULL) {
2423			if (e_flags & edesc->flag)
2424				printf(", %s", edesc->desc);
2425			edesc++;
2426		}
2427	}
2428}
2429
2430static void
2431dump_phdr(struct readelf *re)
2432{
2433	const char	*rawfile;
2434	GElf_Phdr	 phdr;
2435	size_t		 phnum, size;
2436	int		 i, j;
2437
2438#define	PH_HDR	"Type", "Offset", "VirtAddr", "PhysAddr", "FileSiz",	\
2439		"MemSiz", "Flg", "Align"
2440#define	PH_CT	phdr_type(re->ehdr.e_machine, phdr.p_type),		\
2441		(uintmax_t)phdr.p_offset, (uintmax_t)phdr.p_vaddr,	\
2442		(uintmax_t)phdr.p_paddr, (uintmax_t)phdr.p_filesz,	\
2443		(uintmax_t)phdr.p_memsz,				\
2444		phdr.p_flags & PF_R ? 'R' : ' ',			\
2445		phdr.p_flags & PF_W ? 'W' : ' ',			\
2446		phdr.p_flags & PF_X ? 'E' : ' ',			\
2447		(uintmax_t)phdr.p_align
2448
2449	if (elf_getphnum(re->elf, &phnum) == 0) {
2450		warnx("elf_getphnum failed: %s", elf_errmsg(-1));
2451		return;
2452	}
2453	if (phnum == 0) {
2454		printf("\nThere are no program headers in this file.\n");
2455		return;
2456	}
2457
2458	printf("\nElf file type is %s", elf_type(re->ehdr.e_type));
2459	printf("\nEntry point 0x%jx\n", (uintmax_t)re->ehdr.e_entry);
2460	printf("There are %ju program headers, starting at offset %ju\n",
2461	    (uintmax_t)phnum, (uintmax_t)re->ehdr.e_phoff);
2462
2463	/* Dump program headers. */
2464	printf("\nProgram Headers:\n");
2465	if (re->ec == ELFCLASS32)
2466		printf("  %-15s%-9s%-11s%-11s%-8s%-8s%-4s%s\n", PH_HDR);
2467	else if (re->options & RE_WW)
2468		printf("  %-15s%-9s%-19s%-19s%-9s%-9s%-4s%s\n", PH_HDR);
2469	else
2470		printf("  %-15s%-19s%-19s%s\n                 %-19s%-20s"
2471		    "%-7s%s\n", PH_HDR);
2472	for (i = 0; (size_t) i < phnum; i++) {
2473		if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
2474			warnx("gelf_getphdr failed: %s", elf_errmsg(-1));
2475			continue;
2476		}
2477		/* TODO: Add arch-specific segment type dump. */
2478		if (re->ec == ELFCLASS32)
2479			printf("  %-14.14s 0x%6.6jx 0x%8.8jx 0x%8.8jx "
2480			    "0x%5.5jx 0x%5.5jx %c%c%c %#jx\n", PH_CT);
2481		else if (re->options & RE_WW)
2482			printf("  %-14.14s 0x%6.6jx 0x%16.16jx 0x%16.16jx "
2483			    "0x%6.6jx 0x%6.6jx %c%c%c %#jx\n", PH_CT);
2484		else
2485			printf("  %-14.14s 0x%16.16jx 0x%16.16jx 0x%16.16jx\n"
2486			    "                 0x%16.16jx 0x%16.16jx  %c%c%c"
2487			    "    %#jx\n", PH_CT);
2488		if (phdr.p_type == PT_INTERP) {
2489			if ((rawfile = elf_rawfile(re->elf, &size)) == NULL) {
2490				warnx("elf_rawfile failed: %s", elf_errmsg(-1));
2491				continue;
2492			}
2493			if (phdr.p_offset >= size) {
2494				warnx("invalid program header offset");
2495				continue;
2496			}
2497			printf("      [Requesting program interpreter: %s]\n",
2498				rawfile + phdr.p_offset);
2499		}
2500	}
2501
2502	/* Dump section to segment mapping. */
2503	if (re->shnum == 0)
2504		return;
2505	printf("\n Section to Segment mapping:\n");
2506	printf("  Segment Sections...\n");
2507	for (i = 0; (size_t)i < phnum; i++) {
2508		if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
2509			warnx("gelf_getphdr failed: %s", elf_errmsg(-1));
2510			continue;
2511		}
2512		printf("   %2.2d     ", i);
2513		/* skip NULL section. */
2514		for (j = 1; (size_t)j < re->shnum; j++) {
2515			if (re->sl[j].off < phdr.p_offset)
2516				continue;
2517			if (re->sl[j].off + re->sl[j].sz >
2518			    phdr.p_offset + phdr.p_filesz &&
2519			    re->sl[j].type != SHT_NOBITS)
2520				continue;
2521			if (re->sl[j].addr < phdr.p_vaddr ||
2522			    re->sl[j].addr + re->sl[j].sz >
2523			    phdr.p_vaddr + phdr.p_memsz)
2524				continue;
2525			if (phdr.p_type == PT_TLS &&
2526			    (re->sl[j].flags & SHF_TLS) == 0)
2527				continue;
2528			printf("%s ", re->sl[j].name);
2529		}
2530		printf("\n");
2531	}
2532#undef	PH_HDR
2533#undef	PH_CT
2534}
2535
2536static char *
2537section_flags(struct readelf *re, struct section *s)
2538{
2539#define BUF_SZ 256
2540	static char	buf[BUF_SZ];
2541	int		i, p, nb;
2542
2543	p = 0;
2544	nb = re->ec == ELFCLASS32 ? 8 : 16;
2545	if (re->options & RE_T) {
2546		snprintf(buf, BUF_SZ, "[%*.*jx]: ", nb, nb,
2547		    (uintmax_t)s->flags);
2548		p += nb + 4;
2549	}
2550	for (i = 0; section_flag[i].ln != NULL; i++) {
2551		if ((s->flags & section_flag[i].value) == 0)
2552			continue;
2553		if (re->options & RE_T) {
2554			snprintf(&buf[p], BUF_SZ - p, "%s, ",
2555			    section_flag[i].ln);
2556			p += strlen(section_flag[i].ln) + 2;
2557		} else
2558			buf[p++] = section_flag[i].sn;
2559	}
2560	if (re->options & RE_T && p > nb + 4)
2561		p -= 2;
2562	buf[p] = '\0';
2563
2564	return (buf);
2565}
2566
2567static void
2568dump_shdr(struct readelf *re)
2569{
2570	struct section	*s;
2571	int		 i;
2572
2573#define	S_HDR	"[Nr] Name", "Type", "Addr", "Off", "Size", "ES",	\
2574		"Flg", "Lk", "Inf", "Al"
2575#define	S_HDRL	"[Nr] Name", "Type", "Address", "Offset", "Size",	\
2576		"EntSize", "Flags", "Link", "Info", "Align"
2577#define	ST_HDR	"[Nr] Name", "Type", "Addr", "Off", "Size", "ES",	\
2578		"Lk", "Inf", "Al", "Flags"
2579#define	ST_HDRL	"[Nr] Name", "Type", "Address", "Offset", "Link",	\
2580		"Size", "EntSize", "Info", "Align", "Flags"
2581#define	S_CT	i, s->name, section_type(re->ehdr.e_machine, s->type),	\
2582		(uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\
2583		(uintmax_t)s->entsize, section_flags(re, s),		\
2584		s->link, s->info, (uintmax_t)s->align
2585#define	ST_CT	i, s->name, section_type(re->ehdr.e_machine, s->type),  \
2586		(uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\
2587		(uintmax_t)s->entsize, s->link, s->info,		\
2588		(uintmax_t)s->align, section_flags(re, s)
2589#define	ST_CTL	i, s->name, section_type(re->ehdr.e_machine, s->type),  \
2590		(uintmax_t)s->addr, (uintmax_t)s->off, s->link,		\
2591		(uintmax_t)s->sz, (uintmax_t)s->entsize, s->info,	\
2592		(uintmax_t)s->align, section_flags(re, s)
2593
2594	if (re->shnum == 0) {
2595		printf("\nThere are no sections in this file.\n");
2596		return;
2597	}
2598	printf("There are %ju section headers, starting at offset 0x%jx:\n",
2599	    (uintmax_t)re->shnum, (uintmax_t)re->ehdr.e_shoff);
2600	printf("\nSection Headers:\n");
2601	if (re->ec == ELFCLASS32) {
2602		if (re->options & RE_T)
2603			printf("  %s\n       %-16s%-9s%-7s%-7s%-5s%-3s%-4s%s\n"
2604			    "%12s\n", ST_HDR);
2605		else
2606			printf("  %-23s%-16s%-9s%-7s%-7s%-3s%-4s%-3s%-4s%s\n",
2607			    S_HDR);
2608	} else if (re->options & RE_WW) {
2609		if (re->options & RE_T)
2610			printf("  %s\n       %-16s%-17s%-7s%-7s%-5s%-3s%-4s%s\n"
2611			    "%12s\n", ST_HDR);
2612		else
2613			printf("  %-23s%-16s%-17s%-7s%-7s%-3s%-4s%-3s%-4s%s\n",
2614			    S_HDR);
2615	} else {
2616		if (re->options & RE_T)
2617			printf("  %s\n       %-18s%-17s%-18s%s\n       %-18s"
2618			    "%-17s%-18s%s\n%12s\n", ST_HDRL);
2619		else
2620			printf("  %-23s%-17s%-18s%s\n       %-18s%-17s%-7s%"
2621			    "-6s%-6s%s\n", S_HDRL);
2622	}
2623	for (i = 0; (size_t)i < re->shnum; i++) {
2624		s = &re->sl[i];
2625		if (re->ec == ELFCLASS32) {
2626			if (re->options & RE_T)
2627				printf("  [%2d] %s\n       %-15.15s %8.8jx"
2628				    " %6.6jx %6.6jx %2.2jx  %2u %3u %2ju\n"
2629				    "       %s\n", ST_CT);
2630			else
2631				printf("  [%2d] %-17.17s %-15.15s %8.8jx"
2632				    " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n",
2633				    S_CT);
2634		} else if (re->options & RE_WW) {
2635			if (re->options & RE_T)
2636				printf("  [%2d] %s\n       %-15.15s %16.16jx"
2637				    " %6.6jx %6.6jx %2.2jx  %2u %3u %2ju\n"
2638				    "       %s\n", ST_CT);
2639			else
2640				printf("  [%2d] %-17.17s %-15.15s %16.16jx"
2641				    " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n",
2642				    S_CT);
2643		} else {
2644			if (re->options & RE_T)
2645				printf("  [%2d] %s\n       %-15.15s  %16.16jx"
2646				    "  %16.16jx  %u\n       %16.16jx %16.16jx"
2647				    "  %-16u  %ju\n       %s\n", ST_CTL);
2648			else
2649				printf("  [%2d] %-17.17s %-15.15s  %16.16jx"
2650				    "  %8.8jx\n       %16.16jx  %16.16jx "
2651				    "%3s      %2u   %3u     %ju\n", S_CT);
2652		}
2653	}
2654	if ((re->options & RE_T) == 0)
2655		printf("Key to Flags:\n  W (write), A (alloc),"
2656		    " X (execute), M (merge), S (strings)\n"
2657		    "  I (info), L (link order), G (group), x (unknown)\n"
2658		    "  O (extra OS processing required)"
2659		    " o (OS specific), p (processor specific)\n");
2660
2661#undef	S_HDR
2662#undef	S_HDRL
2663#undef	ST_HDR
2664#undef	ST_HDRL
2665#undef	S_CT
2666#undef	ST_CT
2667#undef	ST_CTL
2668}
2669
2670/*
2671 * Return number of entries in the given section. We'd prefer ent_count be a
2672 * size_t *, but libelf APIs already use int for section indices.
2673 */
2674static int
2675get_ent_count(struct section *s, int *ent_count)
2676{
2677	if (s->entsize == 0) {
2678		warnx("section %s has entry size 0", s->name);
2679		return (0);
2680	} else if (s->sz / s->entsize > INT_MAX) {
2681		warnx("section %s has invalid section count", s->name);
2682		return (0);
2683	}
2684	*ent_count = (int)(s->sz / s->entsize);
2685	return (1);
2686}
2687
2688static void
2689dump_dynamic(struct readelf *re)
2690{
2691	GElf_Dyn	 dyn;
2692	Elf_Data	*d;
2693	struct section	*s;
2694	int		 elferr, i, is_dynamic, j, jmax, nentries;
2695
2696	is_dynamic = 0;
2697
2698	for (i = 0; (size_t)i < re->shnum; i++) {
2699		s = &re->sl[i];
2700		if (s->type != SHT_DYNAMIC)
2701			continue;
2702		(void) elf_errno();
2703		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
2704			elferr = elf_errno();
2705			if (elferr != 0)
2706				warnx("elf_getdata failed: %s", elf_errmsg(-1));
2707			continue;
2708		}
2709		if (d->d_size <= 0)
2710			continue;
2711
2712		is_dynamic = 1;
2713
2714		/* Determine the actual number of table entries. */
2715		nentries = 0;
2716		if (!get_ent_count(s, &jmax))
2717			continue;
2718		for (j = 0; j < jmax; j++) {
2719			if (gelf_getdyn(d, j, &dyn) != &dyn) {
2720				warnx("gelf_getdyn failed: %s",
2721				    elf_errmsg(-1));
2722				continue;
2723			}
2724			nentries ++;
2725			if (dyn.d_tag == DT_NULL)
2726				break;
2727                }
2728
2729		printf("\nDynamic section at offset 0x%jx", (uintmax_t)s->off);
2730		printf(" contains %u entries:\n", nentries);
2731
2732		if (re->ec == ELFCLASS32)
2733			printf("%5s%12s%28s\n", "Tag", "Type", "Name/Value");
2734		else
2735			printf("%5s%20s%28s\n", "Tag", "Type", "Name/Value");
2736
2737		for (j = 0; j < nentries; j++) {
2738			if (gelf_getdyn(d, j, &dyn) != &dyn)
2739				continue;
2740			/* Dump dynamic entry type. */
2741			if (re->ec == ELFCLASS32)
2742				printf(" 0x%8.8jx", (uintmax_t)dyn.d_tag);
2743			else
2744				printf(" 0x%16.16jx", (uintmax_t)dyn.d_tag);
2745			printf(" %-20s", dt_type(re->ehdr.e_machine,
2746			    dyn.d_tag));
2747			/* Dump dynamic entry value. */
2748			dump_dyn_val(re, &dyn, s->link);
2749		}
2750	}
2751
2752	if (!is_dynamic)
2753		printf("\nThere is no dynamic section in this file.\n");
2754}
2755
2756static char *
2757timestamp(time_t ti)
2758{
2759	static char ts[32];
2760	struct tm *t;
2761
2762	t = gmtime(&ti);
2763	snprintf(ts, sizeof(ts), "%04d-%02d-%02dT%02d:%02d:%02d",
2764	    t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
2765	    t->tm_min, t->tm_sec);
2766
2767	return (ts);
2768}
2769
2770static const char *
2771dyn_str(struct readelf *re, uint32_t stab, uint64_t d_val)
2772{
2773	const char *name;
2774
2775	if (stab == SHN_UNDEF)
2776		name = "ERROR";
2777	else if ((name = elf_strptr(re->elf, stab, d_val)) == NULL) {
2778		(void) elf_errno(); /* clear error */
2779		name = "ERROR";
2780	}
2781
2782	return (name);
2783}
2784
2785static void
2786dump_arch_dyn_val(struct readelf *re, GElf_Dyn *dyn)
2787{
2788	switch (re->ehdr.e_machine) {
2789	case EM_MIPS:
2790	case EM_MIPS_RS3_LE:
2791		switch (dyn->d_tag) {
2792		case DT_MIPS_RLD_VERSION:
2793		case DT_MIPS_LOCAL_GOTNO:
2794		case DT_MIPS_CONFLICTNO:
2795		case DT_MIPS_LIBLISTNO:
2796		case DT_MIPS_SYMTABNO:
2797		case DT_MIPS_UNREFEXTNO:
2798		case DT_MIPS_GOTSYM:
2799		case DT_MIPS_HIPAGENO:
2800		case DT_MIPS_DELTA_CLASS_NO:
2801		case DT_MIPS_DELTA_INSTANCE_NO:
2802		case DT_MIPS_DELTA_RELOC_NO:
2803		case DT_MIPS_DELTA_SYM_NO:
2804		case DT_MIPS_DELTA_CLASSSYM_NO:
2805		case DT_MIPS_LOCALPAGE_GOTIDX:
2806		case DT_MIPS_LOCAL_GOTIDX:
2807		case DT_MIPS_HIDDEN_GOTIDX:
2808		case DT_MIPS_PROTECTED_GOTIDX:
2809			printf(" %ju\n", (uintmax_t) dyn->d_un.d_val);
2810			break;
2811		case DT_MIPS_ICHECKSUM:
2812		case DT_MIPS_FLAGS:
2813		case DT_MIPS_BASE_ADDRESS:
2814		case DT_MIPS_CONFLICT:
2815		case DT_MIPS_LIBLIST:
2816		case DT_MIPS_RLD_MAP:
2817		case DT_MIPS_DELTA_CLASS:
2818		case DT_MIPS_DELTA_INSTANCE:
2819		case DT_MIPS_DELTA_RELOC:
2820		case DT_MIPS_DELTA_SYM:
2821		case DT_MIPS_DELTA_CLASSSYM:
2822		case DT_MIPS_CXX_FLAGS:
2823		case DT_MIPS_PIXIE_INIT:
2824		case DT_MIPS_SYMBOL_LIB:
2825		case DT_MIPS_OPTIONS:
2826		case DT_MIPS_INTERFACE:
2827		case DT_MIPS_DYNSTR_ALIGN:
2828		case DT_MIPS_INTERFACE_SIZE:
2829		case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
2830		case DT_MIPS_COMPACT_SIZE:
2831		case DT_MIPS_GP_VALUE:
2832		case DT_MIPS_AUX_DYNAMIC:
2833		case DT_MIPS_PLTGOT:
2834		case DT_MIPS_RLD_OBJ_UPDATE:
2835		case DT_MIPS_RWPLT:
2836			printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val);
2837			break;
2838		case DT_MIPS_IVERSION:
2839		case DT_MIPS_PERF_SUFFIX:
2840		case DT_MIPS_TIME_STAMP:
2841			printf(" %s\n", timestamp(dyn->d_un.d_val));
2842			break;
2843		default:
2844			printf("\n");
2845			break;
2846		}
2847		break;
2848	default:
2849		printf("\n");
2850		break;
2851	}
2852}
2853
2854static void
2855dump_flags(struct flag_desc *desc, uint64_t val)
2856{
2857	struct flag_desc *fd;
2858
2859	for (fd = desc; fd->flag != 0; fd++) {
2860		if (val & fd->flag) {
2861			val &= ~fd->flag;
2862			printf(" %s", fd->desc);
2863		}
2864	}
2865	if (val != 0)
2866		printf(" unknown (0x%jx)", (uintmax_t)val);
2867	printf("\n");
2868}
2869
2870static struct flag_desc dt_flags[] = {
2871	{ DF_ORIGIN,		"ORIGIN" },
2872	{ DF_SYMBOLIC,		"SYMBOLIC" },
2873	{ DF_TEXTREL,		"TEXTREL" },
2874	{ DF_BIND_NOW,		"BIND_NOW" },
2875	{ DF_STATIC_TLS,	"STATIC_TLS" },
2876	{ 0, NULL }
2877};
2878
2879static struct flag_desc dt_flags_1[] = {
2880	{ DF_1_BIND_NOW,	"NOW" },
2881	{ DF_1_GLOBAL,		"GLOBAL" },
2882	{ 0x4,			"GROUP" },
2883	{ DF_1_NODELETE,	"NODELETE" },
2884	{ DF_1_LOADFLTR,	"LOADFLTR" },
2885	{ 0x20,			"INITFIRST" },
2886	{ DF_1_NOOPEN,		"NOOPEN" },
2887	{ DF_1_ORIGIN,		"ORIGIN" },
2888	{ 0x100,		"DIRECT" },
2889	{ DF_1_INTERPOSE,	"INTERPOSE" },
2890	{ DF_1_NODEFLIB,	"NODEFLIB" },
2891	{ 0x1000,		"NODUMP" },
2892	{ 0x2000,		"CONFALT" },
2893	{ 0x4000,		"ENDFILTEE" },
2894	{ 0x8000,		"DISPRELDNE" },
2895	{ 0x10000,		"DISPRELPND" },
2896	{ 0x20000,		"NODIRECT" },
2897	{ 0x40000,		"IGNMULDEF" },
2898	{ 0x80000,		"NOKSYMS" },
2899	{ 0x100000,		"NOHDR" },
2900	{ 0x200000,		"EDITED" },
2901	{ 0x400000,		"NORELOC" },
2902	{ 0x800000,		"SYMINTPOSE" },
2903	{ 0x1000000,		"GLOBAUDIT" },
2904	{ 0x02000000,		"SINGLETON" },
2905	{ 0x04000000,		"STUB" },
2906	{ DF_1_PIE,		"PIE" },
2907	{ 0, NULL }
2908};
2909
2910static void
2911dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab)
2912{
2913	const char *name;
2914
2915	if (dyn->d_tag >= DT_LOPROC && dyn->d_tag <= DT_HIPROC &&
2916	    dyn->d_tag != DT_AUXILIARY && dyn->d_tag != DT_FILTER) {
2917		dump_arch_dyn_val(re, dyn);
2918		return;
2919	}
2920
2921	/* These entry values are index into the string table. */
2922	name = NULL;
2923	if (dyn->d_tag == DT_AUXILIARY || dyn->d_tag == DT_FILTER ||
2924	    dyn->d_tag == DT_NEEDED || dyn->d_tag == DT_SONAME ||
2925	    dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH)
2926		name = dyn_str(re, stab, dyn->d_un.d_val);
2927
2928	switch(dyn->d_tag) {
2929	case DT_NULL:
2930	case DT_PLTGOT:
2931	case DT_HASH:
2932	case DT_STRTAB:
2933	case DT_SYMTAB:
2934	case DT_RELA:
2935	case DT_INIT:
2936	case DT_SYMBOLIC:
2937	case DT_REL:
2938	case DT_DEBUG:
2939	case DT_TEXTREL:
2940	case DT_JMPREL:
2941	case DT_FINI:
2942	case DT_VERDEF:
2943	case DT_VERNEED:
2944	case DT_VERSYM:
2945	case DT_GNU_HASH:
2946	case DT_GNU_LIBLIST:
2947	case DT_GNU_CONFLICT:
2948		printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val);
2949		break;
2950	case DT_PLTRELSZ:
2951	case DT_RELASZ:
2952	case DT_RELAENT:
2953	case DT_STRSZ:
2954	case DT_SYMENT:
2955	case DT_RELSZ:
2956	case DT_RELENT:
2957	case DT_PREINIT_ARRAYSZ:
2958	case DT_INIT_ARRAYSZ:
2959	case DT_FINI_ARRAYSZ:
2960	case DT_GNU_CONFLICTSZ:
2961	case DT_GNU_LIBLISTSZ:
2962		printf(" %ju (bytes)\n", (uintmax_t) dyn->d_un.d_val);
2963		break;
2964 	case DT_RELACOUNT:
2965	case DT_RELCOUNT:
2966	case DT_VERDEFNUM:
2967	case DT_VERNEEDNUM:
2968		printf(" %ju\n", (uintmax_t) dyn->d_un.d_val);
2969		break;
2970	case DT_AUXILIARY:
2971		printf(" Auxiliary library: [%s]\n", name);
2972		break;
2973	case DT_FILTER:
2974		printf(" Filter library: [%s]\n", name);
2975		break;
2976	case DT_NEEDED:
2977		printf(" Shared library: [%s]\n", name);
2978		break;
2979	case DT_SONAME:
2980		printf(" Library soname: [%s]\n", name);
2981		break;
2982	case DT_RPATH:
2983		printf(" Library rpath: [%s]\n", name);
2984		break;
2985	case DT_RUNPATH:
2986		printf(" Library runpath: [%s]\n", name);
2987		break;
2988	case DT_PLTREL:
2989		printf(" %s\n", dt_type(re->ehdr.e_machine, dyn->d_un.d_val));
2990		break;
2991	case DT_GNU_PRELINKED:
2992		printf(" %s\n", timestamp(dyn->d_un.d_val));
2993		break;
2994	case DT_FLAGS:
2995		dump_flags(dt_flags, dyn->d_un.d_val);
2996		break;
2997	case DT_FLAGS_1:
2998		dump_flags(dt_flags_1, dyn->d_un.d_val);
2999		break;
3000	default:
3001		printf("\n");
3002	}
3003}
3004
3005static void
3006dump_rel(struct readelf *re, struct section *s, Elf_Data *d)
3007{
3008	GElf_Rel r;
3009	const char *symname;
3010	uint64_t symval;
3011	int i, len;
3012	uint32_t type;
3013	uint8_t type2, type3;
3014
3015	if (s->link >= re->shnum)
3016		return;
3017
3018#define	REL_HDR "r_offset", "r_info", "r_type", "st_value", "st_name"
3019#define	REL_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
3020		elftc_reloc_type_str(re->ehdr.e_machine,	    \
3021		ELF32_R_TYPE(r.r_info)), (uintmax_t)symval, symname
3022#define	REL_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
3023		elftc_reloc_type_str(re->ehdr.e_machine, type),	    \
3024		(uintmax_t)symval, symname
3025
3026	printf("\nRelocation section (%s):\n", s->name);
3027	if (re->ec == ELFCLASS32)
3028		printf("%-8s %-8s %-19s %-8s %s\n", REL_HDR);
3029	else {
3030		if (re->options & RE_WW)
3031			printf("%-16s %-16s %-24s %-16s %s\n", REL_HDR);
3032		else
3033			printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR);
3034	}
3035	assert(d->d_size == s->sz);
3036	if (!get_ent_count(s, &len))
3037		return;
3038	for (i = 0; i < len; i++) {
3039		if (gelf_getrel(d, i, &r) != &r) {
3040			warnx("gelf_getrel failed: %s", elf_errmsg(-1));
3041			continue;
3042		}
3043		symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info));
3044		symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info));
3045		if (re->ec == ELFCLASS32) {
3046			r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info),
3047			    ELF64_R_TYPE(r.r_info));
3048			printf("%8.8jx %8.8jx %-19.19s %8.8jx %s\n", REL_CT32);
3049		} else {
3050			type = ELF64_R_TYPE(r.r_info);
3051			if (re->ehdr.e_machine == EM_MIPS) {
3052				type2 = (type >> 8) & 0xFF;
3053				type3 = (type >> 16) & 0xFF;
3054				type = type & 0xFF;
3055			} else {
3056				type2 = type3 = 0;
3057			}
3058			if (re->options & RE_WW)
3059				printf("%16.16jx %16.16jx %-24.24s"
3060				    " %16.16jx %s\n", REL_CT64);
3061			else
3062				printf("%12.12jx %12.12jx %-19.19s"
3063				    " %16.16jx %s\n", REL_CT64);
3064			if (re->ehdr.e_machine == EM_MIPS) {
3065				if (re->options & RE_WW) {
3066					printf("%32s: %s\n", "Type2",
3067					    elftc_reloc_type_str(EM_MIPS,
3068					    type2));
3069					printf("%32s: %s\n", "Type3",
3070					    elftc_reloc_type_str(EM_MIPS,
3071					    type3));
3072				} else {
3073					printf("%24s: %s\n", "Type2",
3074					    elftc_reloc_type_str(EM_MIPS,
3075					    type2));
3076					printf("%24s: %s\n", "Type3",
3077					    elftc_reloc_type_str(EM_MIPS,
3078					    type3));
3079				}
3080			}
3081		}
3082	}
3083
3084#undef	REL_HDR
3085#undef	REL_CT
3086}
3087
3088static void
3089dump_rela(struct readelf *re, struct section *s, Elf_Data *d)
3090{
3091	GElf_Rela r;
3092	const char *symname;
3093	uint64_t symval;
3094	int i, len;
3095	uint32_t type;
3096	uint8_t type2, type3;
3097
3098	if (s->link >= re->shnum)
3099		return;
3100
3101#define	RELA_HDR "r_offset", "r_info", "r_type", "st_value", \
3102		"st_name + r_addend"
3103#define	RELA_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
3104		elftc_reloc_type_str(re->ehdr.e_machine,	    \
3105		ELF32_R_TYPE(r.r_info)), (uintmax_t)symval, symname
3106#define	RELA_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info,	    \
3107		elftc_reloc_type_str(re->ehdr.e_machine, type),	    \
3108		(uintmax_t)symval, symname
3109
3110	printf("\nRelocation section with addend (%s):\n", s->name);
3111	if (re->ec == ELFCLASS32)
3112		printf("%-8s %-8s %-19s %-8s %s\n", RELA_HDR);
3113	else {
3114		if (re->options & RE_WW)
3115			printf("%-16s %-16s %-24s %-16s %s\n", RELA_HDR);
3116		else
3117			printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR);
3118	}
3119	assert(d->d_size == s->sz);
3120	if (!get_ent_count(s, &len))
3121		return;
3122	for (i = 0; i < len; i++) {
3123		if (gelf_getrela(d, i, &r) != &r) {
3124			warnx("gelf_getrel failed: %s", elf_errmsg(-1));
3125			continue;
3126		}
3127		symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info));
3128		symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info));
3129		if (re->ec == ELFCLASS32) {
3130			r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info),
3131			    ELF64_R_TYPE(r.r_info));
3132			printf("%8.8jx %8.8jx %-19.19s %8.8jx %s", RELA_CT32);
3133			printf(" + %x\n", (uint32_t) r.r_addend);
3134		} else {
3135			type = ELF64_R_TYPE(r.r_info);
3136			if (re->ehdr.e_machine == EM_MIPS) {
3137				type2 = (type >> 8) & 0xFF;
3138				type3 = (type >> 16) & 0xFF;
3139				type = type & 0xFF;
3140			} else {
3141				type2 = type3 = 0;
3142			}
3143			if (re->options & RE_WW)
3144				printf("%16.16jx %16.16jx %-24.24s"
3145				    " %16.16jx %s", RELA_CT64);
3146			else
3147				printf("%12.12jx %12.12jx %-19.19s"
3148				    " %16.16jx %s", RELA_CT64);
3149			printf(" + %jx\n", (uintmax_t) r.r_addend);
3150			if (re->ehdr.e_machine == EM_MIPS) {
3151				if (re->options & RE_WW) {
3152					printf("%32s: %s\n", "Type2",
3153					    elftc_reloc_type_str(EM_MIPS,
3154					    type2));
3155					printf("%32s: %s\n", "Type3",
3156					    elftc_reloc_type_str(EM_MIPS,
3157					    type3));
3158				} else {
3159					printf("%24s: %s\n", "Type2",
3160					    elftc_reloc_type_str(EM_MIPS,
3161					    type2));
3162					printf("%24s: %s\n", "Type3",
3163					    elftc_reloc_type_str(EM_MIPS,
3164					    type3));
3165				}
3166			}
3167		}
3168	}
3169
3170#undef	RELA_HDR
3171#undef	RELA_CT
3172}
3173
3174static void
3175dump_reloc(struct readelf *re)
3176{
3177	struct section *s;
3178	Elf_Data *d;
3179	int i, elferr;
3180
3181	for (i = 0; (size_t)i < re->shnum; i++) {
3182		s = &re->sl[i];
3183		if (s->type == SHT_REL || s->type == SHT_RELA) {
3184			(void) elf_errno();
3185			if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3186				elferr = elf_errno();
3187				if (elferr != 0)
3188					warnx("elf_getdata failed: %s",
3189					    elf_errmsg(elferr));
3190				continue;
3191			}
3192			if (s->type == SHT_REL)
3193				dump_rel(re, s, d);
3194			else
3195				dump_rela(re, s, d);
3196		}
3197	}
3198}
3199
3200static void
3201dump_symtab(struct readelf *re, int i)
3202{
3203	struct section *s;
3204	Elf_Data *d;
3205	GElf_Sym sym;
3206	const char *name;
3207	uint32_t stab;
3208	int elferr, j, len;
3209	uint16_t vs;
3210
3211	s = &re->sl[i];
3212	if (s->link >= re->shnum)
3213		return;
3214	stab = s->link;
3215	(void) elf_errno();
3216	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3217		elferr = elf_errno();
3218		if (elferr != 0)
3219			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3220		return;
3221	}
3222	if (d->d_size <= 0)
3223		return;
3224	if (!get_ent_count(s, &len))
3225		return;
3226	printf("Symbol table (%s)", s->name);
3227	printf(" contains %d entries:\n", len);
3228	printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type",
3229	    "Bind", "Vis", "Ndx", "Name");
3230
3231	for (j = 0; j < len; j++) {
3232		if (gelf_getsym(d, j, &sym) != &sym) {
3233			warnx("gelf_getsym failed: %s", elf_errmsg(-1));
3234			continue;
3235		}
3236		printf("%6d:", j);
3237		printf(" %16.16jx", (uintmax_t) sym.st_value);
3238		printf(" %5ju", (uintmax_t) sym.st_size);
3239		printf(" %-7s", st_type(re->ehdr.e_machine,
3240		    re->ehdr.e_ident[EI_OSABI], GELF_ST_TYPE(sym.st_info)));
3241		printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info)));
3242		printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other)));
3243		printf(" %3s", st_shndx(sym.st_shndx));
3244		if ((name = elf_strptr(re->elf, stab, sym.st_name)) != NULL)
3245			printf(" %s", name);
3246		/* Append symbol version string for SHT_DYNSYM symbol table. */
3247		if (s->type == SHT_DYNSYM && re->ver != NULL &&
3248		    re->vs != NULL && re->vs[j] > 1) {
3249			vs = re->vs[j] & VERSYM_VERSION;
3250			if (vs >= re->ver_sz || re->ver[vs].name == NULL) {
3251				warnx("invalid versym version index %u", vs);
3252				break;
3253			}
3254			if (re->vs[j] & VERSYM_HIDDEN || re->ver[vs].type == 0)
3255				printf("@%s (%d)", re->ver[vs].name, vs);
3256			else
3257				printf("@@%s (%d)", re->ver[vs].name, vs);
3258		}
3259		putchar('\n');
3260	}
3261
3262}
3263
3264static void
3265dump_symtabs(struct readelf *re)
3266{
3267	GElf_Dyn dyn;
3268	Elf_Data *d;
3269	struct section *s;
3270	uint64_t dyn_off;
3271	int elferr, i, len;
3272
3273	/*
3274	 * If -D is specified, only dump the symbol table specified by
3275	 * the DT_SYMTAB entry in the .dynamic section.
3276	 */
3277	dyn_off = 0;
3278	if (re->options & RE_DD) {
3279		s = NULL;
3280		for (i = 0; (size_t)i < re->shnum; i++)
3281			if (re->sl[i].type == SHT_DYNAMIC) {
3282				s = &re->sl[i];
3283				break;
3284			}
3285		if (s == NULL)
3286			return;
3287		(void) elf_errno();
3288		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3289			elferr = elf_errno();
3290			if (elferr != 0)
3291				warnx("elf_getdata failed: %s", elf_errmsg(-1));
3292			return;
3293		}
3294		if (d->d_size <= 0)
3295			return;
3296		if (!get_ent_count(s, &len))
3297			return;
3298
3299		for (i = 0; i < len; i++) {
3300			if (gelf_getdyn(d, i, &dyn) != &dyn) {
3301				warnx("gelf_getdyn failed: %s", elf_errmsg(-1));
3302				continue;
3303			}
3304			if (dyn.d_tag == DT_SYMTAB) {
3305				dyn_off = dyn.d_un.d_val;
3306				break;
3307			}
3308		}
3309	}
3310
3311	/* Find and dump symbol tables. */
3312	for (i = 0; (size_t)i < re->shnum; i++) {
3313		s = &re->sl[i];
3314		if (s->type == SHT_SYMTAB || s->type == SHT_DYNSYM) {
3315			if (re->options & RE_DD) {
3316				if (dyn_off == s->addr) {
3317					dump_symtab(re, i);
3318					break;
3319				}
3320			} else
3321				dump_symtab(re, i);
3322		}
3323	}
3324}
3325
3326static void
3327dump_svr4_hash(struct section *s)
3328{
3329	Elf_Data	*d;
3330	uint32_t	*buf;
3331	uint32_t	 nbucket, nchain;
3332	uint32_t	*bucket, *chain;
3333	uint32_t	*bl, *c, maxl, total;
3334	int		 elferr, i, j;
3335
3336	/* Read and parse the content of .hash section. */
3337	(void) elf_errno();
3338	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3339		elferr = elf_errno();
3340		if (elferr != 0)
3341			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3342		return;
3343	}
3344	if (d->d_size < 2 * sizeof(uint32_t)) {
3345		warnx(".hash section too small");
3346		return;
3347	}
3348	buf = d->d_buf;
3349	nbucket = buf[0];
3350	nchain = buf[1];
3351	if (nbucket <= 0 || nchain <= 0) {
3352		warnx("Malformed .hash section");
3353		return;
3354	}
3355	if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
3356		warnx("Malformed .hash section");
3357		return;
3358	}
3359	bucket = &buf[2];
3360	chain = &buf[2 + nbucket];
3361
3362	maxl = 0;
3363	if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
3364		errx(EXIT_FAILURE, "calloc failed");
3365	for (i = 0; (uint32_t)i < nbucket; i++)
3366		for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j])
3367			if (++bl[i] > maxl)
3368				maxl = bl[i];
3369	if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
3370		errx(EXIT_FAILURE, "calloc failed");
3371	for (i = 0; (uint32_t)i < nbucket; i++)
3372		c[bl[i]]++;
3373	printf("\nHistogram for bucket list length (total of %u buckets):\n",
3374	    nbucket);
3375	printf(" Length\tNumber\t\t%% of total\tCoverage\n");
3376	total = 0;
3377	for (i = 0; (uint32_t)i <= maxl; i++) {
3378		total += c[i] * i;
3379		printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i],
3380		    c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
3381	}
3382	free(c);
3383	free(bl);
3384}
3385
3386static void
3387dump_svr4_hash64(struct readelf *re, struct section *s)
3388{
3389	Elf_Data	*d, dst;
3390	uint64_t	*buf;
3391	uint64_t	 nbucket, nchain;
3392	uint64_t	*bucket, *chain;
3393	uint64_t	*bl, *c, maxl, total;
3394	int		 elferr, i, j;
3395
3396	/*
3397	 * ALPHA uses 64-bit hash entries. Since libelf assumes that
3398	 * .hash section contains only 32-bit entry, an explicit
3399	 * gelf_xlatetom is needed here.
3400	 */
3401	(void) elf_errno();
3402	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
3403		elferr = elf_errno();
3404		if (elferr != 0)
3405			warnx("elf_rawdata failed: %s",
3406			    elf_errmsg(elferr));
3407		return;
3408	}
3409	d->d_type = ELF_T_XWORD;
3410	memcpy(&dst, d, sizeof(Elf_Data));
3411	if (gelf_xlatetom(re->elf, &dst, d,
3412		re->ehdr.e_ident[EI_DATA]) != &dst) {
3413		warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
3414		return;
3415	}
3416	if (dst.d_size < 2 * sizeof(uint64_t)) {
3417		warnx(".hash section too small");
3418		return;
3419	}
3420	buf = dst.d_buf;
3421	nbucket = buf[0];
3422	nchain = buf[1];
3423	if (nbucket <= 0 || nchain <= 0) {
3424		warnx("Malformed .hash section");
3425		return;
3426	}
3427	if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
3428		warnx("Malformed .hash section");
3429		return;
3430	}
3431	bucket = &buf[2];
3432	chain = &buf[2 + nbucket];
3433
3434	maxl = 0;
3435	if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
3436		errx(EXIT_FAILURE, "calloc failed");
3437	for (i = 0; (uint32_t)i < nbucket; i++)
3438		for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j])
3439			if (++bl[i] > maxl)
3440				maxl = bl[i];
3441	if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
3442		errx(EXIT_FAILURE, "calloc failed");
3443	for (i = 0; (uint64_t)i < nbucket; i++)
3444		c[bl[i]]++;
3445	printf("Histogram for bucket list length (total of %ju buckets):\n",
3446	    (uintmax_t)nbucket);
3447	printf(" Length\tNumber\t\t%% of total\tCoverage\n");
3448	total = 0;
3449	for (i = 0; (uint64_t)i <= maxl; i++) {
3450		total += c[i] * i;
3451		printf("%7u\t%-10ju\t(%5.1f%%)\t%5.1f%%\n", i, (uintmax_t)c[i],
3452		    c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
3453	}
3454	free(c);
3455	free(bl);
3456}
3457
3458static void
3459dump_gnu_hash(struct readelf *re, struct section *s)
3460{
3461	struct section	*ds;
3462	Elf_Data	*d;
3463	uint32_t	*buf;
3464	uint32_t	*bucket, *chain;
3465	uint32_t	 nbucket, nchain, symndx, maskwords;
3466	uint32_t	*bl, *c, maxl, total;
3467	int		 elferr, dynsymcount, i, j;
3468
3469	(void) elf_errno();
3470	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3471		elferr = elf_errno();
3472		if (elferr != 0)
3473			warnx("elf_getdata failed: %s",
3474			    elf_errmsg(elferr));
3475		return;
3476	}
3477	if (d->d_size < 4 * sizeof(uint32_t)) {
3478		warnx(".gnu.hash section too small");
3479		return;
3480	}
3481	buf = d->d_buf;
3482	nbucket = buf[0];
3483	symndx = buf[1];
3484	maskwords = buf[2];
3485	buf += 4;
3486	if (s->link >= re->shnum)
3487		return;
3488	ds = &re->sl[s->link];
3489	if (!get_ent_count(ds, &dynsymcount))
3490		return;
3491	if (symndx >= (uint32_t)dynsymcount) {
3492		warnx("Malformed .gnu.hash section (symndx out of range)");
3493		return;
3494	}
3495	nchain = dynsymcount - symndx;
3496	if (d->d_size != 4 * sizeof(uint32_t) + maskwords *
3497	    (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) +
3498	    (nbucket + nchain) * sizeof(uint32_t)) {
3499		warnx("Malformed .gnu.hash section");
3500		return;
3501	}
3502	bucket = buf + (re->ec == ELFCLASS32 ? maskwords : maskwords * 2);
3503	chain = bucket + nbucket;
3504
3505	maxl = 0;
3506	if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
3507		errx(EXIT_FAILURE, "calloc failed");
3508	for (i = 0; (uint32_t)i < nbucket; i++)
3509		for (j = bucket[i]; j > 0 && (uint32_t)j - symndx < nchain;
3510		     j++) {
3511			if (++bl[i] > maxl)
3512				maxl = bl[i];
3513			if (chain[j - symndx] & 1)
3514				break;
3515		}
3516	if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
3517		errx(EXIT_FAILURE, "calloc failed");
3518	for (i = 0; (uint32_t)i < nbucket; i++)
3519		c[bl[i]]++;
3520	printf("Histogram for bucket list length (total of %u buckets):\n",
3521	    nbucket);
3522	printf(" Length\tNumber\t\t%% of total\tCoverage\n");
3523	total = 0;
3524	for (i = 0; (uint32_t)i <= maxl; i++) {
3525		total += c[i] * i;
3526		printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i],
3527		    c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
3528	}
3529	free(c);
3530	free(bl);
3531}
3532
3533static struct flag_desc gnu_property_x86_feature_1_and_bits[] = {
3534	{ GNU_PROPERTY_X86_FEATURE_1_IBT,	"IBT" },
3535	{ GNU_PROPERTY_X86_FEATURE_1_SHSTK,	"SHSTK" },
3536	{ 0, NULL }
3537};
3538
3539static void
3540dump_gnu_property_type_0(struct readelf *re, const char *buf, size_t sz)
3541{
3542	size_t i;
3543	uint32_t type, prop_sz;
3544
3545	printf("      Properties: ");
3546	while (sz > 0) {
3547		if (sz < 8)
3548			goto bad;
3549
3550		type = *(const uint32_t *)(const void *)buf;
3551		prop_sz = *(const uint32_t *)(const void *)(buf + 4);
3552		buf += 8;
3553		sz -= 8;
3554
3555		if (prop_sz > sz)
3556			goto bad;
3557
3558		if (type >= GNU_PROPERTY_LOPROC &&
3559		    type <= GNU_PROPERTY_HIPROC) {
3560			if (re->ehdr.e_machine != EM_X86_64) {
3561				printf("machine type %x unknown\n",
3562				    re->ehdr.e_machine);
3563				goto unknown;
3564			}
3565			switch (type) {
3566			case GNU_PROPERTY_X86_FEATURE_1_AND:
3567				printf("x86 features:");
3568				if (prop_sz != 4)
3569					goto bad;
3570				dump_flags(gnu_property_x86_feature_1_and_bits,
3571				    *(const uint32_t *)(const void *)buf);
3572				break;
3573			}
3574		}
3575
3576		buf += roundup2(prop_sz, 8);
3577		sz -= roundup2(prop_sz, 8);
3578	}
3579	return;
3580bad:
3581	printf("corrupt GNU property\n");
3582unknown:
3583	printf("remaining description data:");
3584	for (i = 0; i < sz; i++)
3585		printf(" %02x", (unsigned char)buf[i]);
3586	printf("\n");
3587}
3588
3589static void
3590dump_hash(struct readelf *re)
3591{
3592	struct section	*s;
3593	int		 i;
3594
3595	for (i = 0; (size_t) i < re->shnum; i++) {
3596		s = &re->sl[i];
3597		if (s->type == SHT_HASH || s->type == SHT_GNU_HASH) {
3598			if (s->type == SHT_GNU_HASH)
3599				dump_gnu_hash(re, s);
3600			else if (re->ehdr.e_machine == EM_ALPHA &&
3601			    s->entsize == 8)
3602				dump_svr4_hash64(re, s);
3603			else
3604				dump_svr4_hash(s);
3605		}
3606	}
3607}
3608
3609static void
3610dump_notes(struct readelf *re)
3611{
3612	struct section *s;
3613	const char *rawfile;
3614	GElf_Phdr phdr;
3615	Elf_Data *d;
3616	size_t filesize, phnum;
3617	int i, elferr;
3618
3619	if (re->ehdr.e_type == ET_CORE) {
3620		/*
3621		 * Search program headers in the core file for
3622		 * PT_NOTE entry.
3623		 */
3624		if (elf_getphnum(re->elf, &phnum) == 0) {
3625			warnx("elf_getphnum failed: %s", elf_errmsg(-1));
3626			return;
3627		}
3628		if (phnum == 0)
3629			return;
3630		if ((rawfile = elf_rawfile(re->elf, &filesize)) == NULL) {
3631			warnx("elf_rawfile failed: %s", elf_errmsg(-1));
3632			return;
3633		}
3634		for (i = 0; (size_t) i < phnum; i++) {
3635			if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
3636				warnx("gelf_getphdr failed: %s",
3637				    elf_errmsg(-1));
3638				continue;
3639			}
3640			if (phdr.p_type == PT_NOTE) {
3641				if (phdr.p_offset >= filesize ||
3642				    phdr.p_filesz > filesize - phdr.p_offset) {
3643					warnx("invalid PHDR offset");
3644					continue;
3645				}
3646				dump_notes_content(re, rawfile + phdr.p_offset,
3647				    phdr.p_filesz, phdr.p_offset);
3648			}
3649		}
3650
3651	} else {
3652		/*
3653		 * For objects other than core files, Search for
3654		 * SHT_NOTE sections.
3655		 */
3656		for (i = 0; (size_t) i < re->shnum; i++) {
3657			s = &re->sl[i];
3658			if (s->type == SHT_NOTE) {
3659				(void) elf_errno();
3660				if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3661					elferr = elf_errno();
3662					if (elferr != 0)
3663						warnx("elf_getdata failed: %s",
3664						    elf_errmsg(elferr));
3665					continue;
3666				}
3667				dump_notes_content(re, d->d_buf, d->d_size,
3668				    s->off);
3669			}
3670		}
3671	}
3672}
3673
3674static struct flag_desc note_feature_ctl_flags[] = {
3675	{ NT_FREEBSD_FCTL_ASLR_DISABLE,		"ASLR_DISABLE" },
3676	{ NT_FREEBSD_FCTL_PROTMAX_DISABLE,	"PROTMAX_DISABLE" },
3677	{ NT_FREEBSD_FCTL_STKGAP_DISABLE,	"STKGAP_DISABLE" },
3678	{ NT_FREEBSD_FCTL_WXNEEDED,		"WXNEEDED" },
3679	{ 0, NULL }
3680};
3681
3682static bool
3683dump_note_string(const char *description, const char *s, size_t len)
3684{
3685	size_t i;
3686
3687	if (len == 0 || s[--len] != '\0') {
3688		return (false);
3689	} else {
3690		for (i = 0; i < len; i++)
3691			if (!isprint(s[i]))
3692				return (false);
3693	}
3694
3695	printf("   %s: %s\n", description, s);
3696	return (true);
3697}
3698
3699struct note_desc {
3700	uint32_t type;
3701	const char *description;
3702	bool (*fp)(const char *, const char *, size_t);
3703};
3704
3705static struct note_desc xen_notes[] = {
3706	{ 5, "Xen version", dump_note_string },
3707	{ 6, "Guest OS", dump_note_string },
3708	{ 7, "Guest version", dump_note_string },
3709	{ 8, "Loader", dump_note_string },
3710	{ 9, "PAE mode", dump_note_string },
3711	{ 10, "Features", dump_note_string },
3712	{ 11, "BSD symtab", dump_note_string },
3713	{ 0, NULL, NULL }
3714};
3715
3716static void
3717dump_notes_data(struct readelf *re, const char *name, uint32_t type,
3718    const char *buf, size_t sz)
3719{
3720	struct note_desc *nd;
3721	size_t i;
3722	const uint32_t *ubuf;
3723
3724	/* Note data is at least 4-byte aligned. */
3725	if (((uintptr_t)buf & 3) != 0) {
3726		warnx("bad note data alignment");
3727		goto unknown;
3728	}
3729	ubuf = (const uint32_t *)(const void *)buf;
3730
3731	if (strcmp(name, "FreeBSD") == 0) {
3732		switch (type) {
3733		case NT_FREEBSD_ABI_TAG:
3734			if (sz != 4)
3735				goto unknown;
3736			printf("   ABI tag: %u\n", ubuf[0]);
3737			return;
3738		/* NT_FREEBSD_NOINIT_TAG carries no data, treat as unknown. */
3739		case NT_FREEBSD_ARCH_TAG:
3740			if (sz != 4)
3741				goto unknown;
3742			printf("   Arch tag: %x\n", ubuf[0]);
3743			return;
3744		case NT_FREEBSD_FEATURE_CTL:
3745			if (sz != 4)
3746				goto unknown;
3747			printf("   Features:");
3748			dump_flags(note_feature_ctl_flags, ubuf[0]);
3749			return;
3750		}
3751	} else if (strcmp(name, "GNU") == 0) {
3752		switch (type) {
3753		case NT_GNU_PROPERTY_TYPE_0:
3754			dump_gnu_property_type_0(re, buf, sz);
3755			return;
3756		case NT_GNU_BUILD_ID:
3757			printf("   Build ID: ");
3758			for (i = 0; i < sz; i++)
3759				printf("%02x", (unsigned char)buf[i]);
3760			printf("\n");
3761			return;
3762		}
3763	} else if (strcmp(name, "Xen") == 0) {
3764		for (nd = xen_notes; nd->description != NULL; nd++) {
3765			if (nd->type == type) {
3766				if (nd->fp(nd->description, buf, sz))
3767					return;
3768				else
3769					break;
3770			}
3771		}
3772	}
3773unknown:
3774	printf("   description data:");
3775	for (i = 0; i < sz; i++)
3776		printf(" %02x", (unsigned char)buf[i]);
3777	printf("\n");
3778}
3779
3780static void
3781dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off)
3782{
3783	Elf_Note *note;
3784	const char *end, *name;
3785	uint32_t namesz, descsz;
3786
3787	printf("\nNotes at offset %#010jx with length %#010jx:\n",
3788	    (uintmax_t) off, (uintmax_t) sz);
3789	printf("  %-13s %-15s %s\n", "Owner", "Data size", "Description");
3790	end = buf + sz;
3791	while (buf < end) {
3792		if (buf + sizeof(*note) > end) {
3793			warnx("invalid note header");
3794			return;
3795		}
3796		note = (Elf_Note *)(uintptr_t) buf;
3797		namesz = roundup2(note->n_namesz, 4);
3798		descsz = roundup2(note->n_descsz, 4);
3799		if (namesz < note->n_namesz || descsz < note->n_descsz ||
3800		    buf + namesz + descsz > end) {
3801			warnx("invalid note header");
3802			return;
3803		}
3804		buf += sizeof(Elf_Note);
3805		name = buf;
3806		buf += namesz;
3807		/*
3808		 * The name field is required to be nul-terminated, and
3809		 * n_namesz includes the terminating nul in observed
3810		 * implementations (contrary to the ELF-64 spec). A special
3811		 * case is needed for cores generated by some older Linux
3812		 * versions, which write a note named "CORE" without a nul
3813		 * terminator and n_namesz = 4.
3814		 */
3815		if (note->n_namesz == 0)
3816			name = "";
3817		else if (note->n_namesz == 4 && strncmp(name, "CORE", 4) == 0)
3818			name = "CORE";
3819		else if (strnlen(name, note->n_namesz) >= note->n_namesz)
3820			name = "<invalid>";
3821		printf("  %-13s %#010jx", name, (uintmax_t) note->n_descsz);
3822		printf("      %s\n", note_type(name, re->ehdr.e_type,
3823		    note->n_type));
3824		dump_notes_data(re, name, note->n_type, buf, note->n_descsz);
3825		buf += descsz;
3826	}
3827}
3828
3829/*
3830 * Symbol versioning sections are the same for 32bit and 64bit
3831 * ELF objects.
3832 */
3833#define Elf_Verdef	Elf32_Verdef
3834#define	Elf_Verdaux	Elf32_Verdaux
3835#define	Elf_Verneed	Elf32_Verneed
3836#define	Elf_Vernaux	Elf32_Vernaux
3837
3838#define	SAVE_VERSION_NAME(x, n, t)					\
3839	do {								\
3840		while (x >= re->ver_sz) {				\
3841			nv = realloc(re->ver,				\
3842			    sizeof(*re->ver) * re->ver_sz * 2);		\
3843			if (nv == NULL) {				\
3844				warn("realloc failed");			\
3845				free(re->ver);				\
3846				return;					\
3847			}						\
3848			re->ver = nv;					\
3849			for (i = re->ver_sz; i < re->ver_sz * 2; i++) {	\
3850				re->ver[i].name = NULL;			\
3851				re->ver[i].type = 0;			\
3852			}						\
3853			re->ver_sz *= 2;				\
3854		}							\
3855		if (x > 1) {						\
3856			re->ver[x].name = n;				\
3857			re->ver[x].type = t;				\
3858		}							\
3859	} while (0)
3860
3861
3862static void
3863dump_verdef(struct readelf *re, int dump)
3864{
3865	struct section *s;
3866	struct symver *nv;
3867	Elf_Data *d;
3868	Elf_Verdef *vd;
3869	Elf_Verdaux *vda;
3870	uint8_t *buf, *end, *buf2;
3871	const char *name;
3872	int elferr, i, j;
3873
3874	if ((s = re->vd_s) == NULL)
3875		return;
3876	if (s->link >= re->shnum)
3877		return;
3878
3879	if (re->ver == NULL) {
3880		re->ver_sz = 16;
3881		if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) ==
3882		    NULL) {
3883			warn("calloc failed");
3884			return;
3885		}
3886		re->ver[0].name = "*local*";
3887		re->ver[1].name = "*global*";
3888	}
3889
3890	if (dump)
3891		printf("\nVersion definition section (%s):\n", s->name);
3892	(void) elf_errno();
3893	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3894		elferr = elf_errno();
3895		if (elferr != 0)
3896			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3897		return;
3898	}
3899	if (d->d_size == 0)
3900		return;
3901
3902	buf = d->d_buf;
3903	end = buf + d->d_size;
3904	while (buf + sizeof(Elf_Verdef) <= end) {
3905		vd = (Elf_Verdef *) (uintptr_t) buf;
3906		if (dump) {
3907			printf("  0x%4.4lx", (unsigned long)
3908			    (buf - (uint8_t *)d->d_buf));
3909			printf(" vd_version: %u vd_flags: %d"
3910			    " vd_ndx: %u vd_cnt: %u", vd->vd_version,
3911			    vd->vd_flags, vd->vd_ndx, vd->vd_cnt);
3912		}
3913		buf2 = buf + vd->vd_aux;
3914		j = 0;
3915		while (buf2 + sizeof(Elf_Verdaux) <= end && j < vd->vd_cnt) {
3916			vda = (Elf_Verdaux *) (uintptr_t) buf2;
3917			name = get_string(re, s->link, vda->vda_name);
3918			if (j == 0) {
3919				if (dump)
3920					printf(" vda_name: %s\n", name);
3921				SAVE_VERSION_NAME((int)vd->vd_ndx, name, 1);
3922			} else if (dump)
3923				printf("  0x%4.4lx parent: %s\n",
3924				    (unsigned long) (buf2 -
3925				    (uint8_t *)d->d_buf), name);
3926			if (vda->vda_next == 0)
3927				break;
3928			buf2 += vda->vda_next;
3929			j++;
3930		}
3931		if (vd->vd_next == 0)
3932			break;
3933		buf += vd->vd_next;
3934	}
3935}
3936
3937static void
3938dump_verneed(struct readelf *re, int dump)
3939{
3940	struct section *s;
3941	struct symver *nv;
3942	Elf_Data *d;
3943	Elf_Verneed *vn;
3944	Elf_Vernaux *vna;
3945	uint8_t *buf, *end, *buf2;
3946	const char *name;
3947	int elferr, i, j;
3948
3949	if ((s = re->vn_s) == NULL)
3950		return;
3951	if (s->link >= re->shnum)
3952		return;
3953
3954	if (re->ver == NULL) {
3955		re->ver_sz = 16;
3956		if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) ==
3957		    NULL) {
3958			warn("calloc failed");
3959			return;
3960		}
3961		re->ver[0].name = "*local*";
3962		re->ver[1].name = "*global*";
3963	}
3964
3965	if (dump)
3966		printf("\nVersion needed section (%s):\n", s->name);
3967	(void) elf_errno();
3968	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3969		elferr = elf_errno();
3970		if (elferr != 0)
3971			warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3972		return;
3973	}
3974	if (d->d_size == 0)
3975		return;
3976
3977	buf = d->d_buf;
3978	end = buf + d->d_size;
3979	while (buf + sizeof(Elf_Verneed) <= end) {
3980		vn = (Elf_Verneed *) (uintptr_t) buf;
3981		if (dump) {
3982			printf("  0x%4.4lx", (unsigned long)
3983			    (buf - (uint8_t *)d->d_buf));
3984			printf(" vn_version: %u vn_file: %s vn_cnt: %u\n",
3985			    vn->vn_version,
3986			    get_string(re, s->link, vn->vn_file),
3987			    vn->vn_cnt);
3988		}
3989		buf2 = buf + vn->vn_aux;
3990		j = 0;
3991		while (buf2 + sizeof(Elf_Vernaux) <= end && j < vn->vn_cnt) {
3992			vna = (Elf32_Vernaux *) (uintptr_t) buf2;
3993			if (dump)
3994				printf("  0x%4.4lx", (unsigned long)
3995				    (buf2 - (uint8_t *)d->d_buf));
3996			name = get_string(re, s->link, vna->vna_name);
3997			if (dump)
3998				printf("   vna_name: %s vna_flags: %u"
3999				    " vna_other: %u\n", name,
4000				    vna->vna_flags, vna->vna_other);
4001			SAVE_VERSION_NAME((int)vna->vna_other, name, 0);
4002			if (vna->vna_next == 0)
4003				break;
4004			buf2 += vna->vna_next;
4005			j++;
4006		}
4007		if (vn->vn_next == 0)
4008			break;
4009		buf += vn->vn_next;
4010	}
4011}
4012
4013static void
4014dump_versym(struct readelf *re)
4015{
4016	int i;
4017	uint16_t vs;
4018
4019	if (re->vs_s == NULL || re->ver == NULL || re->vs == NULL)
4020		return;
4021	printf("\nVersion symbol section (%s):\n", re->vs_s->name);
4022	for (i = 0; i < re->vs_sz; i++) {
4023		if ((i & 3) == 0) {
4024			if (i > 0)
4025				putchar('\n');
4026			printf("  %03x:", i);
4027		}
4028		vs = re->vs[i] & VERSYM_VERSION;
4029		if (vs >= re->ver_sz || re->ver[vs].name == NULL) {
4030			warnx("invalid versym version index %u", re->vs[i]);
4031			break;
4032		}
4033		if (re->vs[i] & VERSYM_HIDDEN)
4034			printf(" %3xh %-12s ", vs,
4035			    re->ver[re->vs[i] & VERSYM_VERSION].name);
4036		else
4037			printf(" %3x %-12s ", vs, re->ver[re->vs[i]].name);
4038	}
4039	putchar('\n');
4040}
4041
4042static void
4043dump_ver(struct readelf *re)
4044{
4045
4046	if (re->vs_s && re->ver && re->vs)
4047		dump_versym(re);
4048	if (re->vd_s)
4049		dump_verdef(re, 1);
4050	if (re->vn_s)
4051		dump_verneed(re, 1);
4052}
4053
4054static void
4055search_ver(struct readelf *re)
4056{
4057	struct section *s;
4058	Elf_Data *d;
4059	int elferr, i;
4060
4061	for (i = 0; (size_t) i < re->shnum; i++) {
4062		s = &re->sl[i];
4063		if (s->type == SHT_SUNW_versym)
4064			re->vs_s = s;
4065		if (s->type == SHT_SUNW_verneed)
4066			re->vn_s = s;
4067		if (s->type == SHT_SUNW_verdef)
4068			re->vd_s = s;
4069	}
4070	if (re->vd_s)
4071		dump_verdef(re, 0);
4072	if (re->vn_s)
4073		dump_verneed(re, 0);
4074	if (re->vs_s && re->ver != NULL) {
4075		(void) elf_errno();
4076		if ((d = elf_getdata(re->vs_s->scn, NULL)) == NULL) {
4077			elferr = elf_errno();
4078			if (elferr != 0)
4079				warnx("elf_getdata failed: %s",
4080				    elf_errmsg(elferr));
4081			return;
4082		}
4083		if (d->d_size == 0)
4084			return;
4085		re->vs = d->d_buf;
4086		re->vs_sz = d->d_size / sizeof(Elf32_Half);
4087	}
4088}
4089
4090#undef	Elf_Verdef
4091#undef	Elf_Verdaux
4092#undef	Elf_Verneed
4093#undef	Elf_Vernaux
4094#undef	SAVE_VERSION_NAME
4095
4096/*
4097 * Elf32_Lib and Elf64_Lib are identical.
4098 */
4099#define	Elf_Lib		Elf32_Lib
4100
4101static void
4102dump_liblist(struct readelf *re)
4103{
4104	struct section *s;
4105	struct tm *t;
4106	time_t ti;
4107	char tbuf[20];
4108	Elf_Data *d;
4109	Elf_Lib *lib;
4110	int i, j, k, elferr, first, len;
4111
4112	for (i = 0; (size_t) i < re->shnum; i++) {
4113		s = &re->sl[i];
4114		if (s->type != SHT_GNU_LIBLIST)
4115			continue;
4116		if (s->link >= re->shnum)
4117			continue;
4118		(void) elf_errno();
4119		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
4120			elferr = elf_errno();
4121			if (elferr != 0)
4122				warnx("elf_getdata failed: %s",
4123				    elf_errmsg(elferr));
4124			continue;
4125		}
4126		if (d->d_size <= 0)
4127			continue;
4128		lib = d->d_buf;
4129		if (!get_ent_count(s, &len))
4130			continue;
4131		printf("\nLibrary list section '%s' ", s->name);
4132		printf("contains %d entries:\n", len);
4133		printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp",
4134		    "Checksum", "Version", "Flags");
4135		for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) {
4136			printf("%3d: ", j);
4137			printf("%-20.20s ",
4138			    get_string(re, s->link, lib->l_name));
4139			ti = lib->l_time_stamp;
4140			t = gmtime(&ti);
4141			snprintf(tbuf, sizeof(tbuf), "%04d-%02d-%02dT%02d:%02d"
4142			    ":%2d", t->tm_year + 1900, t->tm_mon + 1,
4143			    t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
4144			printf("%-19.19s ", tbuf);
4145			printf("0x%08x ", lib->l_checksum);
4146			printf("%-7d %#x", lib->l_version, lib->l_flags);
4147			if (lib->l_flags != 0) {
4148				first = 1;
4149				putchar('(');
4150				for (k = 0; l_flag[k].name != NULL; k++) {
4151					if ((l_flag[k].value & lib->l_flags) ==
4152					    0)
4153						continue;
4154					if (!first)
4155						putchar(',');
4156					else
4157						first = 0;
4158					printf("%s", l_flag[k].name);
4159				}
4160				putchar(')');
4161			}
4162			putchar('\n');
4163			lib++;
4164		}
4165	}
4166}
4167
4168#undef Elf_Lib
4169
4170static void
4171dump_section_groups(struct readelf *re)
4172{
4173	struct section *s;
4174	const char *symname;
4175	Elf_Data *d;
4176	uint32_t *w;
4177	int i, j, elferr;
4178	size_t n;
4179
4180	for (i = 0; (size_t) i < re->shnum; i++) {
4181		s = &re->sl[i];
4182		if (s->type != SHT_GROUP)
4183			continue;
4184		if (s->link >= re->shnum)
4185			continue;
4186		(void) elf_errno();
4187		if ((d = elf_getdata(s->scn, NULL)) == NULL) {
4188			elferr = elf_errno();
4189			if (elferr != 0)
4190				warnx("elf_getdata failed: %s",
4191				    elf_errmsg(elferr));
4192			continue;
4193		}
4194		if (d->d_size <= 0)
4195			continue;
4196
4197		w = d->d_buf;
4198
4199		/* We only support COMDAT section. */
4200#ifndef GRP_COMDAT
4201#define	GRP_COMDAT 0x1
4202#endif
4203		if ((*w++ & GRP_COMDAT) == 0)
4204			return;
4205
4206		if (s->entsize == 0)
4207			s->entsize = 4;
4208
4209		symname = get_symbol_name(re, s->link, s->info);
4210		n = s->sz / s->entsize;
4211		if (n-- < 1)
4212			return;
4213
4214		printf("\nCOMDAT group section [%5d] `%s' [%s] contains %ju"
4215		    " sections:\n", i, s->name, symname, (uintmax_t)n);
4216		printf("   %-10.10s %s\n", "[Index]", "Name");
4217		for (j = 0; (size_t) j < n; j++, w++) {
4218			if (*w >= re->shnum) {
4219				warnx("invalid section index: %u", *w);
4220				continue;
4221			}
4222			printf("   [%5u]   %s\n", *w, re->sl[*w].name);
4223		}
4224	}
4225}
4226
4227static uint8_t *
4228dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe)
4229{
4230	uint64_t val;
4231
4232	/*
4233	 * According to ARM EABI: For tags > 32, even numbered tags have
4234	 * a ULEB128 param and odd numbered ones have NUL-terminated
4235	 * string param. This rule probably also applies for tags <= 32
4236	 * if the object arch is not ARM.
4237	 */
4238
4239	printf("  Tag_unknown_%ju: ", (uintmax_t) tag);
4240
4241	if (tag & 1) {
4242		printf("%s\n", (char *) p);
4243		p += strlen((char *) p) + 1;
4244	} else {
4245		val = _decode_uleb128(&p, pe);
4246		printf("%ju\n", (uintmax_t) val);
4247	}
4248
4249	return (p);
4250}
4251
4252static uint8_t *
4253dump_compatibility_tag(uint8_t *p, uint8_t *pe)
4254{
4255	uint64_t val;
4256
4257	val = _decode_uleb128(&p, pe);
4258	printf("flag = %ju, vendor = %s\n", (uintmax_t) val, p);
4259	p += strlen((char *) p) + 1;
4260
4261	return (p);
4262}
4263
4264static void
4265dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe)
4266{
4267	uint64_t tag, val;
4268	size_t i;
4269	int found, desc;
4270
4271	(void) re;
4272
4273	while (p < pe) {
4274		tag = _decode_uleb128(&p, pe);
4275		found = desc = 0;
4276		for (i = 0; i < sizeof(aeabi_tags) / sizeof(aeabi_tags[0]);
4277		     i++) {
4278			if (tag == aeabi_tags[i].tag) {
4279				found = 1;
4280				printf("  %s: ", aeabi_tags[i].s_tag);
4281				if (aeabi_tags[i].get_desc) {
4282					desc = 1;
4283					val = _decode_uleb128(&p, pe);
4284					printf("%s\n",
4285					    aeabi_tags[i].get_desc(val));
4286				}
4287				break;
4288			}
4289			if (tag < aeabi_tags[i].tag)
4290				break;
4291		}
4292		if (!found) {
4293			p = dump_unknown_tag(tag, p, pe);
4294			continue;
4295		}
4296		if (desc)
4297			continue;
4298
4299		switch (tag) {
4300		case 4:		/* Tag_CPU_raw_name */
4301		case 5:		/* Tag_CPU_name */
4302		case 67:	/* Tag_conformance */
4303			printf("%s\n", (char *) p);
4304			p += strlen((char *) p) + 1;
4305			break;
4306		case 32:	/* Tag_compatibility */
4307			p = dump_compatibility_tag(p, pe);
4308			break;
4309		case 64:	/* Tag_nodefaults */
4310			/* ignored, written as 0. */
4311			(void) _decode_uleb128(&p, pe);
4312			printf("True\n");
4313			break;
4314		case 65:	/* Tag_also_compatible_with */
4315			val = _decode_uleb128(&p, pe);
4316			/* Must be Tag_CPU_arch */
4317			if (val != 6) {
4318				printf("unknown\n");
4319				break;
4320			}
4321			val = _decode_uleb128(&p, pe);
4322			printf("%s\n", aeabi_cpu_arch(val));
4323			/* Skip NUL terminator. */
4324			p++;
4325			break;
4326		default:
4327			putchar('\n');
4328			break;
4329		}
4330	}
4331}
4332
4333#ifndef	Tag_GNU_MIPS_ABI_FP
4334#define	Tag_GNU_MIPS_ABI_FP	4
4335#endif
4336
4337static void
4338dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe)
4339{
4340	uint64_t tag, val;
4341
4342	(void) re;
4343
4344	while (p < pe) {
4345		tag = _decode_uleb128(&p, pe);
4346		switch (tag) {
4347		case Tag_GNU_MIPS_ABI_FP:
4348			val = _decode_uleb128(&p, pe);
4349			printf("  Tag_GNU_MIPS_ABI_FP: %s\n", mips_abi_fp(val));
4350			break;
4351		case 32:	/* Tag_compatibility */
4352			p = dump_compatibility_tag(p, pe);
4353			break;
4354		default:
4355			p = dump_unknown_tag(tag, p, pe);
4356			break;
4357		}
4358	}
4359}
4360
4361#ifndef Tag_GNU_Power_ABI_FP
4362#define	Tag_GNU_Power_ABI_FP	4
4363#endif
4364
4365#ifndef Tag_GNU_Power_ABI_Vector
4366#define	Tag_GNU_Power_ABI_Vector	8
4367#endif
4368
4369static void
4370dump_ppc_attributes(uint8_t *p, uint8_t *pe)
4371{
4372	uint64_t tag, val;
4373
4374	while (p < pe) {
4375		tag = _decode_uleb128(&p, pe);
4376		switch (tag) {
4377		case Tag_GNU_Power_ABI_FP:
4378			val = _decode_uleb128(&p, pe);
4379			printf("  Tag_GNU_Power_ABI_FP: %s\n", ppc_abi_fp(val));
4380			break;
4381		case Tag_GNU_Power_ABI_Vector:
4382			val = _decode_uleb128(&p, pe);
4383			printf("  Tag_GNU_Power_ABI_Vector: %s\n",
4384			    ppc_abi_vector(val));
4385			break;
4386		case 32:	/* Tag_compatibility */
4387			p = dump_compatibility_tag(p, pe);
4388			break;
4389		default:
4390			p = dump_unknown_tag(tag, p, pe);
4391			break;
4392		}
4393	}
4394}
4395
4396static void
4397dump_attributes(struct readelf *re)
4398{
4399	struct section *s;
4400	Elf_Data *d;
4401	uint8_t *p, *pe, *sp;
4402	size_t len, seclen, nlen, sublen;
4403	uint64_t val;
4404	int tag, i, elferr;
4405
4406	for (i = 0; (size_t) i < re->shnum; i++) {
4407		s = &re->sl[i];
4408		if (s->type != SHT_GNU_ATTRIBUTES &&
4409		    (re->ehdr.e_machine != EM_ARM || s->type != SHT_LOPROC + 3))
4410			continue;
4411		(void) elf_errno();
4412		if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4413			elferr = elf_errno();
4414			if (elferr != 0)
4415				warnx("elf_rawdata failed: %s",
4416				    elf_errmsg(elferr));
4417			continue;
4418		}
4419		if (d->d_size <= 0)
4420			continue;
4421		p = d->d_buf;
4422		pe = p + d->d_size;
4423		if (*p != 'A') {
4424			printf("Unknown Attribute Section Format: %c\n",
4425			    (char) *p);
4426			continue;
4427		}
4428		len = d->d_size - 1;
4429		p++;
4430		while (len > 0) {
4431			if (len < 4) {
4432				warnx("truncated attribute section length");
4433				return;
4434			}
4435			seclen = re->dw_decode(&p, 4);
4436			if (seclen > len) {
4437				warnx("invalid attribute section length");
4438				return;
4439			}
4440			len -= seclen;
4441			nlen = strlen((char *) p) + 1;
4442			if (nlen + 4 > seclen) {
4443				warnx("invalid attribute section name");
4444				return;
4445			}
4446			printf("Attribute Section: %s\n", (char *) p);
4447			p += nlen;
4448			seclen -= nlen + 4;
4449			while (seclen > 0) {
4450				sp = p;
4451				tag = *p++;
4452				sublen = re->dw_decode(&p, 4);
4453				if (sublen > seclen) {
4454					warnx("invalid attribute sub-section"
4455					    " length");
4456					return;
4457				}
4458				seclen -= sublen;
4459				printf("%s", top_tag(tag));
4460				if (tag == 2 || tag == 3) {
4461					putchar(':');
4462					for (;;) {
4463						val = _decode_uleb128(&p, pe);
4464						if (val == 0)
4465							break;
4466						printf(" %ju", (uintmax_t) val);
4467					}
4468				}
4469				putchar('\n');
4470				if (re->ehdr.e_machine == EM_ARM &&
4471				    s->type == SHT_LOPROC + 3)
4472					dump_arm_attributes(re, p, sp + sublen);
4473				else if (re->ehdr.e_machine == EM_MIPS ||
4474				    re->ehdr.e_machine == EM_MIPS_RS3_LE)
4475					dump_mips_attributes(re, p,
4476					    sp + sublen);
4477				else if (re->ehdr.e_machine == EM_PPC)
4478					dump_ppc_attributes(p, sp + sublen);
4479				p = sp + sublen;
4480			}
4481		}
4482	}
4483}
4484
4485static void
4486dump_mips_specific_info(struct readelf *re)
4487{
4488	struct section *s;
4489	int i;
4490
4491	s = NULL;
4492	for (i = 0; (size_t) i < re->shnum; i++) {
4493		s = &re->sl[i];
4494		if (s->name != NULL && (!strcmp(s->name, ".MIPS.options") ||
4495		    (s->type == SHT_MIPS_OPTIONS))) {
4496			dump_mips_options(re, s);
4497		}
4498	}
4499
4500	if (s->name != NULL && (!strcmp(s->name, ".MIPS.abiflags") ||
4501	    (s->type == SHT_MIPS_ABIFLAGS)))
4502		dump_mips_abiflags(re, s);
4503
4504	/*
4505	 * Dump .reginfo if present (although it will be ignored by an OS if a
4506	 * .MIPS.options section is present, according to SGI mips64 spec).
4507	 */
4508	for (i = 0; (size_t) i < re->shnum; i++) {
4509		s = &re->sl[i];
4510		if (s->name != NULL && (!strcmp(s->name, ".reginfo") ||
4511		    (s->type == SHT_MIPS_REGINFO)))
4512			dump_mips_reginfo(re, s);
4513	}
4514}
4515
4516static void
4517dump_mips_abiflags(struct readelf *re, struct section *s)
4518{
4519	Elf_Data *d;
4520	uint8_t *p;
4521	int elferr;
4522	uint32_t isa_ext, ases, flags1, flags2;
4523	uint16_t version;
4524	uint8_t isa_level, isa_rev, gpr_size, cpr1_size, cpr2_size, fp_abi;
4525
4526	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4527		elferr = elf_errno();
4528		if (elferr != 0)
4529			warnx("elf_rawdata failed: %s",
4530			    elf_errmsg(elferr));
4531		return;
4532	}
4533	if (d->d_size != 24) {
4534		warnx("invalid MIPS abiflags section size");
4535		return;
4536	}
4537
4538	p = d->d_buf;
4539	version = re->dw_decode(&p, 2);
4540	printf("MIPS ABI Flags Version: %u", version);
4541	if (version != 0) {
4542		printf(" (unknown)\n\n");
4543		return;
4544	}
4545	printf("\n\n");
4546
4547	isa_level = re->dw_decode(&p, 1);
4548	isa_rev = re->dw_decode(&p, 1);
4549	gpr_size = re->dw_decode(&p, 1);
4550	cpr1_size = re->dw_decode(&p, 1);
4551	cpr2_size = re->dw_decode(&p, 1);
4552	fp_abi = re->dw_decode(&p, 1);
4553	isa_ext = re->dw_decode(&p, 4);
4554	ases = re->dw_decode(&p, 4);
4555	flags1 = re->dw_decode(&p, 4);
4556	flags2 = re->dw_decode(&p, 4);
4557
4558	printf("ISA: ");
4559	if (isa_rev <= 1)
4560		printf("MIPS%u\n", isa_level);
4561	else
4562		printf("MIPS%ur%u\n", isa_level, isa_rev);
4563	printf("GPR size: %d\n", get_mips_register_size(gpr_size));
4564	printf("CPR1 size: %d\n", get_mips_register_size(cpr1_size));
4565	printf("CPR2 size: %d\n", get_mips_register_size(cpr2_size));
4566	printf("FP ABI: ");
4567	switch (fp_abi) {
4568	case 3:
4569		printf("Soft float");
4570		break;
4571	default:
4572		printf("%u", fp_abi);
4573		break;
4574	}
4575	printf("\nISA Extension: %u\n", isa_ext);
4576	printf("ASEs: %u\n", ases);
4577	printf("FLAGS 1: %08x\n", flags1);
4578	printf("FLAGS 2: %08x\n", flags2);
4579}
4580
4581static int
4582get_mips_register_size(uint8_t flag)
4583{
4584	switch (flag) {
4585	case 0: return 0;
4586	case 1: return 32;
4587	case 2: return 64;
4588	case 3: return 128;
4589	default: return -1;
4590	}
4591}
4592static void
4593dump_mips_reginfo(struct readelf *re, struct section *s)
4594{
4595	Elf_Data *d;
4596	int elferr, len;
4597
4598	(void) elf_errno();
4599	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4600		elferr = elf_errno();
4601		if (elferr != 0)
4602			warnx("elf_rawdata failed: %s",
4603			    elf_errmsg(elferr));
4604		return;
4605	}
4606	if (d->d_size <= 0)
4607		return;
4608	if (!get_ent_count(s, &len))
4609		return;
4610
4611	printf("\nSection '%s' contains %d entries:\n", s->name, len);
4612	dump_mips_odk_reginfo(re, d->d_buf, d->d_size);
4613}
4614
4615static void
4616dump_mips_options(struct readelf *re, struct section *s)
4617{
4618	Elf_Data *d;
4619	uint32_t info;
4620	uint16_t sndx;
4621	uint8_t *p, *pe;
4622	uint8_t kind, size;
4623	int elferr;
4624
4625	(void) elf_errno();
4626	if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4627		elferr = elf_errno();
4628		if (elferr != 0)
4629			warnx("elf_rawdata failed: %s",
4630			    elf_errmsg(elferr));
4631		return;
4632	}
4633	if (d->d_size == 0)
4634		return;
4635
4636	printf("\nSection %s contains:\n", s->name);
4637	p = d->d_buf;
4638	pe = p + d->d_size;
4639	while (p < pe) {
4640		if (pe - p < 8) {
4641			warnx("Truncated MIPS option header");
4642			return;
4643		}
4644		kind = re->dw_decode(&p, 1);
4645		size = re->dw_decode(&p, 1);
4646		sndx = re->dw_decode(&p, 2);
4647		info = re->dw_decode(&p, 4);
4648		if (size < 8 || size - 8 > pe - p) {
4649			warnx("Malformed MIPS option header");
4650			return;
4651		}
4652		size -= 8;
4653		switch (kind) {
4654		case ODK_REGINFO:
4655			dump_mips_odk_reginfo(re, p, size);
4656			break;
4657		case ODK_EXCEPTIONS:
4658			printf(" EXCEPTIONS FPU_MIN: %#x\n",
4659			    info & OEX_FPU_MIN);
4660			printf("%11.11s FPU_MAX: %#x\n", "",
4661			    info & OEX_FPU_MAX);
4662			dump_mips_option_flags("", mips_exceptions_option,
4663			    info);
4664			break;
4665		case ODK_PAD:
4666			printf(" %-10.10s section: %ju\n", "OPAD",
4667			    (uintmax_t) sndx);
4668			dump_mips_option_flags("", mips_pad_option, info);
4669			break;
4670		case ODK_HWPATCH:
4671			dump_mips_option_flags("HWPATCH", mips_hwpatch_option,
4672			    info);
4673			break;
4674		case ODK_HWAND:
4675			dump_mips_option_flags("HWAND", mips_hwa_option, info);
4676			break;
4677		case ODK_HWOR:
4678			dump_mips_option_flags("HWOR", mips_hwo_option, info);
4679			break;
4680		case ODK_FILL:
4681			printf(" %-10.10s %#jx\n", "FILL", (uintmax_t) info);
4682			break;
4683		case ODK_TAGS:
4684			printf(" %-10.10s\n", "TAGS");
4685			break;
4686		case ODK_GP_GROUP:
4687			printf(" %-10.10s GP group number: %#x\n", "GP_GROUP",
4688			    info & 0xFFFF);
4689			if (info & 0x10000)
4690				printf(" %-10.10s GP group is "
4691				    "self-contained\n", "");
4692			break;
4693		case ODK_IDENT:
4694			printf(" %-10.10s default GP group number: %#x\n",
4695			    "IDENT", info & 0xFFFF);
4696			if (info & 0x10000)
4697				printf(" %-10.10s default GP group is "
4698				    "self-contained\n", "");
4699			break;
4700		case ODK_PAGESIZE:
4701			printf(" %-10.10s\n", "PAGESIZE");
4702			break;
4703		default:
4704			break;
4705		}
4706		p += size;
4707	}
4708}
4709
4710static void
4711dump_mips_option_flags(const char *name, struct mips_option *opt, uint64_t info)
4712{
4713	int first;
4714
4715	first = 1;
4716	for (; opt->desc != NULL; opt++) {
4717		if (info & opt->flag) {
4718			printf(" %-10.10s %s\n", first ? name : "",
4719			    opt->desc);
4720			first = 0;
4721		}
4722	}
4723}
4724
4725static void
4726dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz)
4727{
4728	uint32_t ri_gprmask;
4729	uint32_t ri_cprmask[4];
4730	uint64_t ri_gp_value;
4731	uint8_t *pe;
4732	int i;
4733
4734	pe = p + sz;
4735	while (p < pe) {
4736		ri_gprmask = re->dw_decode(&p, 4);
4737		/* Skip ri_pad padding field for mips64. */
4738		if (re->ec == ELFCLASS64)
4739			re->dw_decode(&p, 4);
4740		for (i = 0; i < 4; i++)
4741			ri_cprmask[i] = re->dw_decode(&p, 4);
4742		if (re->ec == ELFCLASS32)
4743			ri_gp_value = re->dw_decode(&p, 4);
4744		else
4745			ri_gp_value = re->dw_decode(&p, 8);
4746		printf(" %s    ", option_kind(ODK_REGINFO));
4747		printf("ri_gprmask:    0x%08jx\n", (uintmax_t) ri_gprmask);
4748		for (i = 0; i < 4; i++)
4749			printf("%11.11s ri_cprmask[%d]: 0x%08jx\n", "", i,
4750			    (uintmax_t) ri_cprmask[i]);
4751		printf("%12.12s", "");
4752		printf("ri_gp_value:   %#jx\n", (uintmax_t) ri_gp_value);
4753	}
4754}
4755
4756static void
4757dump_arch_specific_info(struct readelf *re)
4758{
4759
4760	dump_liblist(re);
4761	dump_attributes(re);
4762
4763	switch (re->ehdr.e_machine) {
4764	case EM_MIPS:
4765	case EM_MIPS_RS3_LE:
4766		dump_mips_specific_info(re);
4767	default:
4768		break;
4769	}
4770}
4771
4772static const char *
4773dwarf_regname(struct readelf *re, unsigned int num)
4774{
4775	static char rx[32];
4776	const char *rn;
4777
4778	if ((rn = dwarf_reg(re->ehdr.e_machine, num)) != NULL)
4779		return (rn);
4780
4781	snprintf(rx, sizeof(rx), "r%u", num);
4782
4783	return (rx);
4784}
4785
4786static void
4787dump_dwarf_line(struct readelf *re)
4788{
4789	struct section *s;
4790	Dwarf_Die die;
4791	Dwarf_Error de;
4792	Dwarf_Half tag, version, pointer_size;
4793	Dwarf_Unsigned offset, endoff, length, hdrlen, dirndx, mtime, fsize;
4794	Dwarf_Small minlen, defstmt, lrange, opbase, oplen;
4795	Elf_Data *d;
4796	char *pn;
4797	uint64_t address, file, line, column, isa, opsize, udelta;
4798	int64_t sdelta;
4799	uint8_t *p, *pe;
4800	int8_t lbase;
4801	int i, is_stmt, dwarf_size, elferr, ret;
4802
4803	printf("\nDump of debug contents of section .debug_line:\n");
4804
4805	s = NULL;
4806	for (i = 0; (size_t) i < re->shnum; i++) {
4807		s = &re->sl[i];
4808		if (s->name != NULL && !strcmp(s->name, ".debug_line"))
4809			break;
4810	}
4811	if ((size_t) i >= re->shnum)
4812		return;
4813
4814	(void) elf_errno();
4815	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
4816		elferr = elf_errno();
4817		if (elferr != 0)
4818			warnx("elf_getdata failed: %s", elf_errmsg(-1));
4819		return;
4820	}
4821	if (d->d_size <= 0)
4822		return;
4823
4824	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
4825	    NULL, &de)) ==  DW_DLV_OK) {
4826		die = NULL;
4827		while (dwarf_siblingof(re->dbg, die, &die, &de) == DW_DLV_OK) {
4828			if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
4829				warnx("dwarf_tag failed: %s",
4830				    dwarf_errmsg(de));
4831				return;
4832			}
4833			/* XXX: What about DW_TAG_partial_unit? */
4834			if (tag == DW_TAG_compile_unit)
4835				break;
4836		}
4837		if (die == NULL) {
4838			warnx("could not find DW_TAG_compile_unit die");
4839			return;
4840		}
4841		if (dwarf_attrval_unsigned(die, DW_AT_stmt_list, &offset,
4842		    &de) != DW_DLV_OK)
4843			continue;
4844
4845		length = re->dw_read(d, &offset, 4);
4846		if (length == 0xffffffff) {
4847			dwarf_size = 8;
4848			length = re->dw_read(d, &offset, 8);
4849		} else
4850			dwarf_size = 4;
4851
4852		if (length > d->d_size - offset) {
4853			warnx("invalid .dwarf_line section");
4854			continue;
4855		}
4856
4857		endoff = offset + length;
4858		pe = (uint8_t *) d->d_buf + endoff;
4859		version = re->dw_read(d, &offset, 2);
4860		hdrlen = re->dw_read(d, &offset, dwarf_size);
4861		minlen = re->dw_read(d, &offset, 1);
4862		defstmt = re->dw_read(d, &offset, 1);
4863		lbase = re->dw_read(d, &offset, 1);
4864		lrange = re->dw_read(d, &offset, 1);
4865		opbase = re->dw_read(d, &offset, 1);
4866
4867		printf("\n");
4868		printf("  Length:\t\t\t%ju\n", (uintmax_t) length);
4869		printf("  DWARF version:\t\t%u\n", version);
4870		printf("  Prologue Length:\t\t%ju\n", (uintmax_t) hdrlen);
4871		printf("  Minimum Instruction Length:\t%u\n", minlen);
4872		printf("  Initial value of 'is_stmt':\t%u\n", defstmt);
4873		printf("  Line Base:\t\t\t%d\n", lbase);
4874		printf("  Line Range:\t\t\t%u\n", lrange);
4875		printf("  Opcode Base:\t\t\t%u\n", opbase);
4876		(void) dwarf_get_address_size(re->dbg, &pointer_size, &de);
4877		printf("  (Pointer size:\t\t%u)\n", pointer_size);
4878
4879		printf("\n");
4880		printf(" Opcodes:\n");
4881		for (i = 1; i < opbase; i++) {
4882			oplen = re->dw_read(d, &offset, 1);
4883			printf("  Opcode %d has %u args\n", i, oplen);
4884		}
4885
4886		printf("\n");
4887		printf(" The Directory Table:\n");
4888		p = (uint8_t *) d->d_buf + offset;
4889		while (*p != '\0') {
4890			printf("  %s\n", (char *) p);
4891			p += strlen((char *) p) + 1;
4892		}
4893
4894		p++;
4895		printf("\n");
4896		printf(" The File Name Table:\n");
4897		printf("  Entry\tDir\tTime\tSize\tName\n");
4898		i = 0;
4899		while (*p != '\0') {
4900			i++;
4901			pn = (char *) p;
4902			p += strlen(pn) + 1;
4903			dirndx = _decode_uleb128(&p, pe);
4904			mtime = _decode_uleb128(&p, pe);
4905			fsize = _decode_uleb128(&p, pe);
4906			printf("  %d\t%ju\t%ju\t%ju\t%s\n", i,
4907			    (uintmax_t) dirndx, (uintmax_t) mtime,
4908			    (uintmax_t) fsize, pn);
4909		}
4910
4911#define	RESET_REGISTERS						\
4912	do {							\
4913		address	       = 0;				\
4914		file	       = 1;				\
4915		line	       = 1;				\
4916		column	       = 0;				\
4917		is_stmt	       = defstmt;			\
4918	} while(0)
4919
4920#define	LINE(x) (lbase + (((x) - opbase) % lrange))
4921#define	ADDRESS(x) ((((x) - opbase) / lrange) * minlen)
4922
4923		p++;
4924		printf("\n");
4925		printf(" Line Number Statements:\n");
4926
4927		RESET_REGISTERS;
4928
4929		while (p < pe) {
4930
4931			if (*p == 0) {
4932				/*
4933				 * Extended Opcodes.
4934				 */
4935				p++;
4936				opsize = _decode_uleb128(&p, pe);
4937				printf("  Extended opcode %u: ", *p);
4938				switch (*p) {
4939				case DW_LNE_end_sequence:
4940					p++;
4941					RESET_REGISTERS;
4942					printf("End of Sequence\n");
4943					break;
4944				case DW_LNE_set_address:
4945					p++;
4946					address = re->dw_decode(&p,
4947					    pointer_size);
4948					printf("set Address to %#jx\n",
4949					    (uintmax_t) address);
4950					break;
4951				case DW_LNE_define_file:
4952					p++;
4953					pn = (char *) p;
4954					p += strlen(pn) + 1;
4955					dirndx = _decode_uleb128(&p, pe);
4956					mtime = _decode_uleb128(&p, pe);
4957					fsize = _decode_uleb128(&p, pe);
4958					printf("define new file: %s\n", pn);
4959					break;
4960				default:
4961					/* Unrecognized extened opcodes. */
4962					p += opsize;
4963					printf("unknown opcode\n");
4964				}
4965			} else if (*p > 0 && *p < opbase) {
4966				/*
4967				 * Standard Opcodes.
4968				 */
4969				switch(*p++) {
4970				case DW_LNS_copy:
4971					printf("  Copy\n");
4972					break;
4973				case DW_LNS_advance_pc:
4974					udelta = _decode_uleb128(&p, pe) *
4975					    minlen;
4976					address += udelta;
4977					printf("  Advance PC by %ju to %#jx\n",
4978					    (uintmax_t) udelta,
4979					    (uintmax_t) address);
4980					break;
4981				case DW_LNS_advance_line:
4982					sdelta = _decode_sleb128(&p, pe);
4983					line += sdelta;
4984					printf("  Advance Line by %jd to %ju\n",
4985					    (intmax_t) sdelta,
4986					    (uintmax_t) line);
4987					break;
4988				case DW_LNS_set_file:
4989					file = _decode_uleb128(&p, pe);
4990					printf("  Set File to %ju\n",
4991					    (uintmax_t) file);
4992					break;
4993				case DW_LNS_set_column:
4994					column = _decode_uleb128(&p, pe);
4995					printf("  Set Column to %ju\n",
4996					    (uintmax_t) column);
4997					break;
4998				case DW_LNS_negate_stmt:
4999					is_stmt = !is_stmt;
5000					printf("  Set is_stmt to %d\n", is_stmt);
5001					break;
5002				case DW_LNS_set_basic_block:
5003					printf("  Set basic block flag\n");
5004					break;
5005				case DW_LNS_const_add_pc:
5006					address += ADDRESS(255);
5007					printf("  Advance PC by constant %ju"
5008					    " to %#jx\n",
5009					    (uintmax_t) ADDRESS(255),
5010					    (uintmax_t) address);
5011					break;
5012				case DW_LNS_fixed_advance_pc:
5013					udelta = re->dw_decode(&p, 2);
5014					address += udelta;
5015					printf("  Advance PC by fixed value "
5016					    "%ju to %#jx\n",
5017					    (uintmax_t) udelta,
5018					    (uintmax_t) address);
5019					break;
5020				case DW_LNS_set_prologue_end:
5021					printf("  Set prologue end flag\n");
5022					break;
5023				case DW_LNS_set_epilogue_begin:
5024					printf("  Set epilogue begin flag\n");
5025					break;
5026				case DW_LNS_set_isa:
5027					isa = _decode_uleb128(&p, pe);
5028					printf("  Set isa to %ju\n",
5029					    (uintmax_t) isa);
5030					break;
5031				default:
5032					/* Unrecognized extended opcodes. */
5033					printf("  Unknown extended opcode %u\n",
5034					    *(p - 1));
5035					break;
5036				}
5037
5038			} else {
5039				/*
5040				 * Special Opcodes.
5041				 */
5042				line += LINE(*p);
5043				address += ADDRESS(*p);
5044				printf("  Special opcode %u: advance Address "
5045				    "by %ju to %#jx and Line by %jd to %ju\n",
5046				    *p - opbase, (uintmax_t) ADDRESS(*p),
5047				    (uintmax_t) address, (intmax_t) LINE(*p),
5048				    (uintmax_t) line);
5049				p++;
5050			}
5051
5052
5053		}
5054	}
5055	if (ret == DW_DLV_ERROR)
5056		warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
5057
5058#undef	RESET_REGISTERS
5059#undef	LINE
5060#undef	ADDRESS
5061}
5062
5063static void
5064dump_dwarf_line_decoded(struct readelf *re)
5065{
5066	Dwarf_Die die;
5067	Dwarf_Line *linebuf, ln;
5068	Dwarf_Addr lineaddr;
5069	Dwarf_Signed linecount, srccount;
5070	Dwarf_Unsigned lineno, fn;
5071	Dwarf_Error de;
5072	const char *dir, *file;
5073	char **srcfiles;
5074	int i, ret;
5075
5076	printf("Decoded dump of debug contents of section .debug_line:\n\n");
5077	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
5078	    NULL, &de)) == DW_DLV_OK) {
5079		if (dwarf_siblingof(re->dbg, NULL, &die, &de) != DW_DLV_OK)
5080			continue;
5081		if (dwarf_attrval_string(die, DW_AT_name, &file, &de) !=
5082		    DW_DLV_OK)
5083			file = NULL;
5084		if (dwarf_attrval_string(die, DW_AT_comp_dir, &dir, &de) !=
5085		    DW_DLV_OK)
5086			dir = NULL;
5087		printf("CU: ");
5088		if (dir && file && file[0] != '/')
5089			printf("%s/", dir);
5090		if (file)
5091			printf("%s", file);
5092		putchar('\n');
5093		printf("%-37s %11s   %s\n", "Filename", "Line Number",
5094		    "Starting Address");
5095		if (dwarf_srclines(die, &linebuf, &linecount, &de) != DW_DLV_OK)
5096			continue;
5097		if (dwarf_srcfiles(die, &srcfiles, &srccount, &de) != DW_DLV_OK)
5098			continue;
5099		for (i = 0; i < linecount; i++) {
5100			ln = linebuf[i];
5101			if (dwarf_line_srcfileno(ln, &fn, &de) != DW_DLV_OK)
5102				continue;
5103			if (dwarf_lineno(ln, &lineno, &de) != DW_DLV_OK)
5104				continue;
5105			if (dwarf_lineaddr(ln, &lineaddr, &de) != DW_DLV_OK)
5106				continue;
5107			printf("%-37s %11ju %#18jx\n",
5108			    basename(srcfiles[fn - 1]), (uintmax_t) lineno,
5109			    (uintmax_t) lineaddr);
5110		}
5111		putchar('\n');
5112	}
5113}
5114
5115static void
5116dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level)
5117{
5118	Dwarf_Attribute *attr_list;
5119	Dwarf_Die ret_die;
5120	Dwarf_Off dieoff, cuoff, culen, attroff;
5121	Dwarf_Unsigned ate, lang, v_udata, v_sig;
5122	Dwarf_Signed attr_count, v_sdata;
5123	Dwarf_Off v_off;
5124	Dwarf_Addr v_addr;
5125	Dwarf_Half tag, attr, form;
5126	Dwarf_Block *v_block;
5127	Dwarf_Bool v_bool, is_info;
5128	Dwarf_Sig8 v_sig8;
5129	Dwarf_Error de;
5130	Dwarf_Ptr v_expr;
5131	const char *tag_str, *attr_str, *ate_str, *lang_str;
5132	char unk_tag[32], unk_attr[32];
5133	char *v_str;
5134	uint8_t *b, *p;
5135	int i, j, abc, ret;
5136
5137	if (dwarf_dieoffset(die, &dieoff, &de) != DW_DLV_OK) {
5138		warnx("dwarf_dieoffset failed: %s", dwarf_errmsg(de));
5139		goto cont_search;
5140	}
5141
5142	printf(" <%d><%jx>: ", level, (uintmax_t) dieoff);
5143
5144	if (dwarf_die_CU_offset_range(die, &cuoff, &culen, &de) != DW_DLV_OK) {
5145		warnx("dwarf_die_CU_offset_range failed: %s",
5146		      dwarf_errmsg(de));
5147		cuoff = 0;
5148	}
5149
5150	abc = dwarf_die_abbrev_code(die);
5151	if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
5152		warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
5153		goto cont_search;
5154	}
5155	if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) {
5156		snprintf(unk_tag, sizeof(unk_tag), "[Unknown Tag: %#x]", tag);
5157		tag_str = unk_tag;
5158	}
5159
5160	printf("Abbrev Number: %d (%s)\n", abc, tag_str);
5161
5162	if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
5163	    DW_DLV_OK) {
5164		if (ret == DW_DLV_ERROR)
5165			warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
5166		goto cont_search;
5167	}
5168
5169	for (i = 0; i < attr_count; i++) {
5170		if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) {
5171			warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
5172			continue;
5173		}
5174		if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
5175			warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
5176			continue;
5177		}
5178		if (dwarf_get_AT_name(attr, &attr_str) != DW_DLV_OK) {
5179			snprintf(unk_attr, sizeof(unk_attr),
5180			    "[Unknown AT: %#x]", attr);
5181			attr_str = unk_attr;
5182		}
5183		if (dwarf_attroffset(attr_list[i], &attroff, &de) !=
5184		    DW_DLV_OK) {
5185			warnx("dwarf_attroffset failed: %s", dwarf_errmsg(de));
5186			attroff = 0;
5187		}
5188		printf("    <%jx>   %-18s: ", (uintmax_t) attroff, attr_str);
5189		switch (form) {
5190		case DW_FORM_ref_addr:
5191		case DW_FORM_sec_offset:
5192			if (dwarf_global_formref(attr_list[i], &v_off, &de) !=
5193			    DW_DLV_OK) {
5194				warnx("dwarf_global_formref failed: %s",
5195				    dwarf_errmsg(de));
5196				continue;
5197			}
5198			if (form == DW_FORM_ref_addr)
5199				printf("<0x%jx>", (uintmax_t) v_off);
5200			else
5201				printf("0x%jx", (uintmax_t) v_off);
5202			break;
5203
5204		case DW_FORM_ref1:
5205		case DW_FORM_ref2:
5206		case DW_FORM_ref4:
5207		case DW_FORM_ref8:
5208		case DW_FORM_ref_udata:
5209			if (dwarf_formref(attr_list[i], &v_off, &de) !=
5210			    DW_DLV_OK) {
5211				warnx("dwarf_formref failed: %s",
5212				    dwarf_errmsg(de));
5213				continue;
5214			}
5215			v_off += cuoff;
5216			printf("<0x%jx>", (uintmax_t) v_off);
5217			break;
5218
5219		case DW_FORM_addr:
5220			if (dwarf_formaddr(attr_list[i], &v_addr, &de) !=
5221			    DW_DLV_OK) {
5222				warnx("dwarf_formaddr failed: %s",
5223				    dwarf_errmsg(de));
5224				continue;
5225			}
5226			printf("%#jx", (uintmax_t) v_addr);
5227			break;
5228
5229		case DW_FORM_data1:
5230		case DW_FORM_data2:
5231		case DW_FORM_data4:
5232		case DW_FORM_data8:
5233		case DW_FORM_udata:
5234			if (dwarf_formudata(attr_list[i], &v_udata, &de) !=
5235			    DW_DLV_OK) {
5236				warnx("dwarf_formudata failed: %s",
5237				    dwarf_errmsg(de));
5238				continue;
5239			}
5240			if (attr == DW_AT_high_pc)
5241				printf("0x%jx", (uintmax_t) v_udata);
5242			else
5243				printf("%ju", (uintmax_t) v_udata);
5244			break;
5245
5246		case DW_FORM_sdata:
5247			if (dwarf_formsdata(attr_list[i], &v_sdata, &de) !=
5248			    DW_DLV_OK) {
5249				warnx("dwarf_formudata failed: %s",
5250				    dwarf_errmsg(de));
5251				continue;
5252			}
5253			printf("%jd", (intmax_t) v_sdata);
5254			break;
5255
5256		case DW_FORM_flag:
5257			if (dwarf_formflag(attr_list[i], &v_bool, &de) !=
5258			    DW_DLV_OK) {
5259				warnx("dwarf_formflag failed: %s",
5260				    dwarf_errmsg(de));
5261				continue;
5262			}
5263			printf("%jd", (intmax_t) v_bool);
5264			break;
5265
5266		case DW_FORM_flag_present:
5267			putchar('1');
5268			break;
5269
5270		case DW_FORM_string:
5271		case DW_FORM_strp:
5272			if (dwarf_formstring(attr_list[i], &v_str, &de) !=
5273			    DW_DLV_OK) {
5274				warnx("dwarf_formstring failed: %s",
5275				    dwarf_errmsg(de));
5276				continue;
5277			}
5278			if (form == DW_FORM_string)
5279				printf("%s", v_str);
5280			else
5281				printf("(indirect string) %s", v_str);
5282			break;
5283
5284		case DW_FORM_block:
5285		case DW_FORM_block1:
5286		case DW_FORM_block2:
5287		case DW_FORM_block4:
5288			if (dwarf_formblock(attr_list[i], &v_block, &de) !=
5289			    DW_DLV_OK) {
5290				warnx("dwarf_formblock failed: %s",
5291				    dwarf_errmsg(de));
5292				continue;
5293			}
5294			printf("%ju byte block:", (uintmax_t) v_block->bl_len);
5295			b = v_block->bl_data;
5296			for (j = 0; (Dwarf_Unsigned) j < v_block->bl_len; j++)
5297				printf(" %x", b[j]);
5298			printf("\t(");
5299			dump_dwarf_block(re, v_block->bl_data, v_block->bl_len);
5300			putchar(')');
5301			break;
5302
5303		case DW_FORM_exprloc:
5304			if (dwarf_formexprloc(attr_list[i], &v_udata, &v_expr,
5305			    &de) != DW_DLV_OK) {
5306				warnx("dwarf_formexprloc failed: %s",
5307				    dwarf_errmsg(de));
5308				continue;
5309			}
5310			printf("%ju byte block:", (uintmax_t) v_udata);
5311			b = v_expr;
5312			for (j = 0; (Dwarf_Unsigned) j < v_udata; j++)
5313				printf(" %x", b[j]);
5314			printf("\t(");
5315			dump_dwarf_block(re, v_expr, v_udata);
5316			putchar(')');
5317			break;
5318
5319		case DW_FORM_ref_sig8:
5320			if (dwarf_formsig8(attr_list[i], &v_sig8, &de) !=
5321			    DW_DLV_OK) {
5322				warnx("dwarf_formsig8 failed: %s",
5323				    dwarf_errmsg(de));
5324				continue;
5325			}
5326			p = (uint8_t *)(uintptr_t) &v_sig8.signature[0];
5327			v_sig = re->dw_decode(&p, 8);
5328			printf("signature: 0x%jx", (uintmax_t) v_sig);
5329		}
5330		switch (attr) {
5331		case DW_AT_encoding:
5332			if (dwarf_attrval_unsigned(die, attr, &ate, &de) !=
5333			    DW_DLV_OK)
5334				break;
5335			if (dwarf_get_ATE_name(ate, &ate_str) != DW_DLV_OK)
5336				ate_str = "DW_ATE_UNKNOWN";
5337			printf("\t(%s)", &ate_str[strlen("DW_ATE_")]);
5338			break;
5339
5340		case DW_AT_language:
5341			if (dwarf_attrval_unsigned(die, attr, &lang, &de) !=
5342			    DW_DLV_OK)
5343				break;
5344			if (dwarf_get_LANG_name(lang, &lang_str) != DW_DLV_OK)
5345				break;
5346			printf("\t(%s)", &lang_str[strlen("DW_LANG_")]);
5347			break;
5348
5349		case DW_AT_location:
5350		case DW_AT_string_length:
5351		case DW_AT_return_addr:
5352		case DW_AT_data_member_location:
5353		case DW_AT_frame_base:
5354		case DW_AT_segment:
5355		case DW_AT_static_link:
5356		case DW_AT_use_location:
5357		case DW_AT_vtable_elem_location:
5358			switch (form) {
5359			case DW_FORM_data4:
5360			case DW_FORM_data8:
5361			case DW_FORM_sec_offset:
5362				printf("\t(location list)");
5363				break;
5364			default:
5365				break;
5366			}
5367
5368		default:
5369			break;
5370		}
5371		putchar('\n');
5372	}
5373
5374
5375cont_search:
5376	/* Search children. */
5377	ret = dwarf_child(die, &ret_die, &de);
5378	if (ret == DW_DLV_ERROR)
5379		warnx("dwarf_child: %s", dwarf_errmsg(de));
5380	else if (ret == DW_DLV_OK)
5381		dump_dwarf_die(re, ret_die, level + 1);
5382
5383	/* Search sibling. */
5384	is_info = dwarf_get_die_infotypes_flag(die);
5385	ret = dwarf_siblingof_b(re->dbg, die, &ret_die, is_info, &de);
5386	if (ret == DW_DLV_ERROR)
5387		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
5388	else if (ret == DW_DLV_OK)
5389		dump_dwarf_die(re, ret_die, level);
5390
5391	dwarf_dealloc(re->dbg, die, DW_DLA_DIE);
5392}
5393
5394static void
5395set_cu_context(struct readelf *re, Dwarf_Half psize, Dwarf_Half osize,
5396    Dwarf_Half ver)
5397{
5398
5399	re->cu_psize = psize;
5400	re->cu_osize = osize;
5401	re->cu_ver = ver;
5402}
5403
5404static void
5405dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info)
5406{
5407	struct section *s;
5408	Dwarf_Die die;
5409	Dwarf_Error de;
5410	Dwarf_Half tag, version, pointer_size, off_size;
5411	Dwarf_Off cu_offset, cu_length;
5412	Dwarf_Off aboff;
5413	Dwarf_Unsigned typeoff;
5414	Dwarf_Sig8 sig8;
5415	Dwarf_Unsigned sig;
5416	uint8_t *p;
5417	const char *sn;
5418	int i, ret;
5419
5420	sn = is_info ? ".debug_info" : ".debug_types";
5421
5422	s = NULL;
5423	for (i = 0; (size_t) i < re->shnum; i++) {
5424		s = &re->sl[i];
5425		if (s->name != NULL && !strcmp(s->name, sn))
5426			break;
5427	}
5428	if ((size_t) i >= re->shnum)
5429		return;
5430
5431	do {
5432		printf("\nDump of debug contents of section %s:\n", sn);
5433
5434		while ((ret = dwarf_next_cu_header_c(re->dbg, is_info, NULL,
5435		    &version, &aboff, &pointer_size, &off_size, NULL, &sig8,
5436		    &typeoff, NULL, &de)) == DW_DLV_OK) {
5437			set_cu_context(re, pointer_size, off_size, version);
5438			die = NULL;
5439			while (dwarf_siblingof_b(re->dbg, die, &die, is_info,
5440			    &de) == DW_DLV_OK) {
5441				if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
5442					warnx("dwarf_tag failed: %s",
5443					    dwarf_errmsg(de));
5444					continue;
5445				}
5446				/* XXX: What about DW_TAG_partial_unit? */
5447				if ((is_info && tag == DW_TAG_compile_unit) ||
5448				    (!is_info && tag == DW_TAG_type_unit))
5449					break;
5450			}
5451			if (die == NULL && is_info) {
5452				warnx("could not find DW_TAG_compile_unit "
5453				    "die");
5454				continue;
5455			} else if (die == NULL && !is_info) {
5456				warnx("could not find DW_TAG_type_unit die");
5457				continue;
5458			}
5459
5460			if (dwarf_die_CU_offset_range(die, &cu_offset,
5461			    &cu_length, &de) != DW_DLV_OK) {
5462				warnx("dwarf_die_CU_offset failed: %s",
5463				    dwarf_errmsg(de));
5464				continue;
5465			}
5466
5467			cu_length -= off_size == 4 ? 4 : 12;
5468
5469			sig = 0;
5470			if (!is_info) {
5471				p = (uint8_t *)(uintptr_t) &sig8.signature[0];
5472				sig = re->dw_decode(&p, 8);
5473			}
5474
5475			printf("\n  Type Unit @ offset 0x%jx:\n",
5476			    (uintmax_t) cu_offset);
5477			printf("    Length:\t\t%#jx (%d-bit)\n",
5478			    (uintmax_t) cu_length, off_size == 4 ? 32 : 64);
5479			printf("    Version:\t\t%u\n", version);
5480			printf("    Abbrev Offset:\t0x%jx\n",
5481			    (uintmax_t) aboff);
5482			printf("    Pointer Size:\t%u\n", pointer_size);
5483			if (!is_info) {
5484				printf("    Signature:\t\t0x%016jx\n",
5485				    (uintmax_t) sig);
5486				printf("    Type Offset:\t0x%jx\n",
5487				    (uintmax_t) typeoff);
5488			}
5489
5490			dump_dwarf_die(re, die, 0);
5491		}
5492		if (ret == DW_DLV_ERROR)
5493			warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
5494		if (is_info)
5495			break;
5496	} while (dwarf_next_types_section(re->dbg, &de) == DW_DLV_OK);
5497}
5498
5499static void
5500dump_dwarf_abbrev(struct readelf *re)
5501{
5502	Dwarf_Abbrev ab;
5503	Dwarf_Off aboff, atoff;
5504	Dwarf_Unsigned length, attr_count;
5505	Dwarf_Signed flag, form;
5506	Dwarf_Half tag, attr;
5507	Dwarf_Error de;
5508	const char *tag_str, *attr_str, *form_str;
5509	char unk_tag[32], unk_attr[32], unk_form[32];
5510	int i, j, ret;
5511
5512	printf("\nContents of section .debug_abbrev:\n\n");
5513
5514	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, &aboff,
5515	    NULL, NULL, &de)) ==  DW_DLV_OK) {
5516		printf("  Number TAG\n");
5517		i = 0;
5518		while ((ret = dwarf_get_abbrev(re->dbg, aboff, &ab, &length,
5519		    &attr_count, &de)) == DW_DLV_OK) {
5520			if (length == 1) {
5521				dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV);
5522				break;
5523			}
5524			aboff += length;
5525			printf("%4d", ++i);
5526			if (dwarf_get_abbrev_tag(ab, &tag, &de) != DW_DLV_OK) {
5527				warnx("dwarf_get_abbrev_tag failed: %s",
5528				    dwarf_errmsg(de));
5529				goto next_abbrev;
5530			}
5531			if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) {
5532				snprintf(unk_tag, sizeof(unk_tag),
5533				    "[Unknown Tag: %#x]", tag);
5534				tag_str = unk_tag;
5535			}
5536			if (dwarf_get_abbrev_children_flag(ab, &flag, &de) !=
5537			    DW_DLV_OK) {
5538				warnx("dwarf_get_abbrev_children_flag failed:"
5539				    " %s", dwarf_errmsg(de));
5540				goto next_abbrev;
5541			}
5542			printf("      %s    %s\n", tag_str,
5543			    flag ? "[has children]" : "[no children]");
5544			for (j = 0; (Dwarf_Unsigned) j < attr_count; j++) {
5545				if (dwarf_get_abbrev_entry(ab, (Dwarf_Signed) j,
5546				    &attr, &form, &atoff, &de) != DW_DLV_OK) {
5547					warnx("dwarf_get_abbrev_entry failed:"
5548					    " %s", dwarf_errmsg(de));
5549					continue;
5550				}
5551				if (dwarf_get_AT_name(attr, &attr_str) !=
5552				    DW_DLV_OK) {
5553					snprintf(unk_attr, sizeof(unk_attr),
5554					    "[Unknown AT: %#x]", attr);
5555					attr_str = unk_attr;
5556				}
5557				if (dwarf_get_FORM_name(form, &form_str) !=
5558				    DW_DLV_OK) {
5559					snprintf(unk_form, sizeof(unk_form),
5560					    "[Unknown Form: %#x]",
5561					    (Dwarf_Half) form);
5562					form_str = unk_form;
5563				}
5564				printf("    %-18s %s\n", attr_str, form_str);
5565			}
5566		next_abbrev:
5567			dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV);
5568		}
5569		if (ret != DW_DLV_OK)
5570			warnx("dwarf_get_abbrev: %s", dwarf_errmsg(de));
5571	}
5572	if (ret == DW_DLV_ERROR)
5573		warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
5574}
5575
5576static void
5577dump_dwarf_pubnames(struct readelf *re)
5578{
5579	struct section *s;
5580	Dwarf_Off die_off;
5581	Dwarf_Unsigned offset, length, nt_cu_offset, nt_cu_length;
5582	Dwarf_Signed cnt;
5583	Dwarf_Global *globs;
5584	Dwarf_Half nt_version;
5585	Dwarf_Error de;
5586	Elf_Data *d;
5587	char *glob_name;
5588	int i, dwarf_size, elferr;
5589
5590	printf("\nContents of the .debug_pubnames section:\n");
5591
5592	s = NULL;
5593	for (i = 0; (size_t) i < re->shnum; i++) {
5594		s = &re->sl[i];
5595		if (s->name != NULL && !strcmp(s->name, ".debug_pubnames"))
5596			break;
5597	}
5598	if ((size_t) i >= re->shnum)
5599		return;
5600
5601	(void) elf_errno();
5602	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
5603		elferr = elf_errno();
5604		if (elferr != 0)
5605			warnx("elf_getdata failed: %s", elf_errmsg(-1));
5606		return;
5607	}
5608	if (d->d_size <= 0)
5609		return;
5610
5611	/* Read in .debug_pubnames section table header. */
5612	offset = 0;
5613	length = re->dw_read(d, &offset, 4);
5614	if (length == 0xffffffff) {
5615		dwarf_size = 8;
5616		length = re->dw_read(d, &offset, 8);
5617	} else
5618		dwarf_size = 4;
5619
5620	if (length > d->d_size - offset) {
5621		warnx("invalid .dwarf_pubnames section");
5622		return;
5623	}
5624
5625	nt_version = re->dw_read(d, &offset, 2);
5626	nt_cu_offset = re->dw_read(d, &offset, dwarf_size);
5627	nt_cu_length = re->dw_read(d, &offset, dwarf_size);
5628	printf("  Length:\t\t\t\t%ju\n", (uintmax_t) length);
5629	printf("  Version:\t\t\t\t%u\n", nt_version);
5630	printf("  Offset into .debug_info section:\t%ju\n",
5631	    (uintmax_t) nt_cu_offset);
5632	printf("  Size of area in .debug_info section:\t%ju\n",
5633	    (uintmax_t) nt_cu_length);
5634
5635	if (dwarf_get_globals(re->dbg, &globs, &cnt, &de) != DW_DLV_OK) {
5636		warnx("dwarf_get_globals failed: %s", dwarf_errmsg(de));
5637		return;
5638	}
5639
5640	printf("\n    Offset      Name\n");
5641	for (i = 0; i < cnt; i++) {
5642		if (dwarf_globname(globs[i], &glob_name, &de) != DW_DLV_OK) {
5643			warnx("dwarf_globname failed: %s", dwarf_errmsg(de));
5644			continue;
5645		}
5646		if (dwarf_global_die_offset(globs[i], &die_off, &de) !=
5647		    DW_DLV_OK) {
5648			warnx("dwarf_global_die_offset failed: %s",
5649			    dwarf_errmsg(de));
5650			continue;
5651		}
5652		printf("    %-11ju %s\n", (uintmax_t) die_off, glob_name);
5653	}
5654}
5655
5656static void
5657dump_dwarf_aranges(struct readelf *re)
5658{
5659	struct section *s;
5660	Dwarf_Arange *aranges;
5661	Dwarf_Addr start;
5662	Dwarf_Unsigned offset, length, as_cu_offset;
5663	Dwarf_Off die_off;
5664	Dwarf_Signed cnt;
5665	Dwarf_Half as_version, as_addrsz, as_segsz;
5666	Dwarf_Error de;
5667	Elf_Data *d;
5668	int i, dwarf_size, elferr;
5669
5670	printf("\nContents of section .debug_aranges:\n");
5671
5672	s = NULL;
5673	for (i = 0; (size_t) i < re->shnum; i++) {
5674		s = &re->sl[i];
5675		if (s->name != NULL && !strcmp(s->name, ".debug_aranges"))
5676			break;
5677	}
5678	if ((size_t) i >= re->shnum)
5679		return;
5680
5681	(void) elf_errno();
5682	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
5683		elferr = elf_errno();
5684		if (elferr != 0)
5685			warnx("elf_getdata failed: %s", elf_errmsg(-1));
5686		return;
5687	}
5688	if (d->d_size <= 0)
5689		return;
5690
5691	/* Read in the .debug_aranges section table header. */
5692	offset = 0;
5693	length = re->dw_read(d, &offset, 4);
5694	if (length == 0xffffffff) {
5695		dwarf_size = 8;
5696		length = re->dw_read(d, &offset, 8);
5697	} else
5698		dwarf_size = 4;
5699
5700	if (length > d->d_size - offset) {
5701		warnx("invalid .dwarf_aranges section");
5702		return;
5703	}
5704
5705	as_version = re->dw_read(d, &offset, 2);
5706	as_cu_offset = re->dw_read(d, &offset, dwarf_size);
5707	as_addrsz = re->dw_read(d, &offset, 1);
5708	as_segsz = re->dw_read(d, &offset, 1);
5709
5710	printf("  Length:\t\t\t%ju\n", (uintmax_t) length);
5711	printf("  Version:\t\t\t%u\n", as_version);
5712	printf("  Offset into .debug_info:\t%ju\n", (uintmax_t) as_cu_offset);
5713	printf("  Pointer Size:\t\t\t%u\n", as_addrsz);
5714	printf("  Segment Size:\t\t\t%u\n", as_segsz);
5715
5716	if (dwarf_get_aranges(re->dbg, &aranges, &cnt, &de) != DW_DLV_OK) {
5717		warnx("dwarf_get_aranges failed: %s", dwarf_errmsg(de));
5718		return;
5719	}
5720
5721	printf("\n    Address  Length\n");
5722	for (i = 0; i < cnt; i++) {
5723		if (dwarf_get_arange_info(aranges[i], &start, &length,
5724		    &die_off, &de) != DW_DLV_OK) {
5725			warnx("dwarf_get_arange_info failed: %s",
5726			    dwarf_errmsg(de));
5727			continue;
5728		}
5729		printf("    %08jx %ju\n", (uintmax_t) start,
5730		    (uintmax_t) length);
5731	}
5732}
5733
5734static void
5735dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base)
5736{
5737	Dwarf_Attribute *attr_list;
5738	Dwarf_Ranges *ranges;
5739	Dwarf_Die ret_die;
5740	Dwarf_Error de;
5741	Dwarf_Addr base0;
5742	Dwarf_Half attr;
5743	Dwarf_Signed attr_count, cnt;
5744	Dwarf_Unsigned off, bytecnt;
5745	int i, j, ret;
5746
5747	if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
5748	    DW_DLV_OK) {
5749		if (ret == DW_DLV_ERROR)
5750			warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
5751		goto cont_search;
5752	}
5753
5754	for (i = 0; i < attr_count; i++) {
5755		if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
5756			warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
5757			continue;
5758		}
5759		if (attr != DW_AT_ranges)
5760			continue;
5761		if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) {
5762			warnx("dwarf_formudata failed: %s", dwarf_errmsg(de));
5763			continue;
5764		}
5765		if (dwarf_get_ranges(re->dbg, (Dwarf_Off) off, &ranges, &cnt,
5766		    &bytecnt, &de) != DW_DLV_OK)
5767			continue;
5768		base0 = base;
5769		for (j = 0; j < cnt; j++) {
5770			printf("    %08jx ", (uintmax_t) off);
5771			if (ranges[j].dwr_type == DW_RANGES_END) {
5772				printf("%s\n", "<End of list>");
5773				continue;
5774			} else if (ranges[j].dwr_type ==
5775			    DW_RANGES_ADDRESS_SELECTION) {
5776				base0 = ranges[j].dwr_addr2;
5777				continue;
5778			}
5779			if (re->ec == ELFCLASS32)
5780				printf("%08jx %08jx\n",
5781				    (uintmax_t) (ranges[j].dwr_addr1 + base0),
5782				    (uintmax_t) (ranges[j].dwr_addr2 + base0));
5783			else
5784				printf("%016jx %016jx\n",
5785				    (uintmax_t) (ranges[j].dwr_addr1 + base0),
5786				    (uintmax_t) (ranges[j].dwr_addr2 + base0));
5787		}
5788	}
5789
5790cont_search:
5791	/* Search children. */
5792	ret = dwarf_child(die, &ret_die, &de);
5793	if (ret == DW_DLV_ERROR)
5794		warnx("dwarf_child: %s", dwarf_errmsg(de));
5795	else if (ret == DW_DLV_OK)
5796		dump_dwarf_ranges_foreach(re, ret_die, base);
5797
5798	/* Search sibling. */
5799	ret = dwarf_siblingof(re->dbg, die, &ret_die, &de);
5800	if (ret == DW_DLV_ERROR)
5801		warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
5802	else if (ret == DW_DLV_OK)
5803		dump_dwarf_ranges_foreach(re, ret_die, base);
5804}
5805
5806static void
5807dump_dwarf_ranges(struct readelf *re)
5808{
5809	Dwarf_Ranges *ranges;
5810	Dwarf_Die die;
5811	Dwarf_Signed cnt;
5812	Dwarf_Unsigned bytecnt;
5813	Dwarf_Half tag;
5814	Dwarf_Error de;
5815	Dwarf_Unsigned lowpc;
5816	int ret;
5817
5818	if (dwarf_get_ranges(re->dbg, 0, &ranges, &cnt, &bytecnt, &de) !=
5819	    DW_DLV_OK)
5820		return;
5821
5822	printf("Contents of the .debug_ranges section:\n\n");
5823	if (re->ec == ELFCLASS32)
5824		printf("    %-8s %-8s %s\n", "Offset", "Begin", "End");
5825	else
5826		printf("    %-8s %-16s %s\n", "Offset", "Begin", "End");
5827
5828	while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
5829	    NULL, &de)) == DW_DLV_OK) {
5830		die = NULL;
5831		if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK)
5832			continue;
5833		if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
5834			warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
5835			continue;
5836		}
5837		/* XXX: What about DW_TAG_partial_unit? */
5838		lowpc = 0;
5839		if (tag == DW_TAG_compile_unit) {
5840			if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc,
5841			    &de) != DW_DLV_OK)
5842				lowpc = 0;
5843		}
5844
5845		dump_dwarf_ranges_foreach(re, die, (Dwarf_Addr) lowpc);
5846	}
5847	putchar('\n');
5848}
5849
5850static void
5851dump_dwarf_macinfo(struct readelf *re)
5852{
5853	Dwarf_Unsigned offset;
5854	Dwarf_Signed cnt;
5855	Dwarf_Macro_Details *md;
5856	Dwarf_Error de;
5857	const char *mi_str;
5858	char unk_mi[32];
5859	int i;
5860
5861#define	_MAX_MACINFO_ENTRY	65535
5862
5863	printf("\nContents of section .debug_macinfo:\n\n");
5864
5865	offset = 0;
5866	while (dwarf_get_macro_details(re->dbg, offset, _MAX_MACINFO_ENTRY,
5867	    &cnt, &md, &de) == DW_DLV_OK) {
5868		for (i = 0; i < cnt; i++) {
5869			offset = md[i].dmd_offset + 1;
5870			if (md[i].dmd_type == 0)
5871				break;
5872			if (dwarf_get_MACINFO_name(md[i].dmd_type, &mi_str) !=
5873			    DW_DLV_OK) {
5874				snprintf(unk_mi, sizeof(unk_mi),
5875				    "[Unknown MACINFO: %#x]", md[i].dmd_type);
5876				mi_str = unk_mi;
5877			}
5878			printf(" %s", mi_str);
5879			switch (md[i].dmd_type) {
5880			case DW_MACINFO_define:
5881			case DW_MACINFO_undef:
5882				printf(" - lineno : %jd macro : %s\n",
5883				    (intmax_t) md[i].dmd_lineno,
5884				    md[i].dmd_macro);
5885				break;
5886			case DW_MACINFO_start_file:
5887				printf(" - lineno : %jd filenum : %jd\n",
5888				    (intmax_t) md[i].dmd_lineno,
5889				    (intmax_t) md[i].dmd_fileindex);
5890				break;
5891			default:
5892				putchar('\n');
5893				break;
5894			}
5895		}
5896	}
5897
5898#undef	_MAX_MACINFO_ENTRY
5899}
5900
5901static void
5902dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie, uint8_t *insts,
5903    Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf, Dwarf_Addr pc,
5904    Dwarf_Debug dbg)
5905{
5906	Dwarf_Frame_Op *oplist;
5907	Dwarf_Signed opcnt, delta;
5908	Dwarf_Small op;
5909	Dwarf_Error de;
5910	const char *op_str;
5911	char unk_op[32];
5912	int i;
5913
5914	if (dwarf_expand_frame_instructions(cie, insts, len, &oplist,
5915	    &opcnt, &de) != DW_DLV_OK) {
5916		warnx("dwarf_expand_frame_instructions failed: %s",
5917		    dwarf_errmsg(de));
5918		return;
5919	}
5920
5921	for (i = 0; i < opcnt; i++) {
5922		if (oplist[i].fp_base_op != 0)
5923			op = oplist[i].fp_base_op << 6;
5924		else
5925			op = oplist[i].fp_extended_op;
5926		if (dwarf_get_CFA_name(op, &op_str) != DW_DLV_OK) {
5927			snprintf(unk_op, sizeof(unk_op), "[Unknown CFA: %#x]",
5928			    op);
5929			op_str = unk_op;
5930		}
5931		printf("  %s", op_str);
5932		switch (op) {
5933		case DW_CFA_advance_loc:
5934			delta = oplist[i].fp_offset * caf;
5935			pc += delta;
5936			printf(": %ju to %08jx", (uintmax_t) delta,
5937			    (uintmax_t) pc);
5938			break;
5939		case DW_CFA_offset:
5940		case DW_CFA_offset_extended:
5941		case DW_CFA_offset_extended_sf:
5942			delta = oplist[i].fp_offset * daf;
5943			printf(": r%u (%s) at cfa%+jd", oplist[i].fp_register,
5944			    dwarf_regname(re, oplist[i].fp_register),
5945			    (intmax_t) delta);
5946			break;
5947		case DW_CFA_restore:
5948			printf(": r%u (%s)", oplist[i].fp_register,
5949			    dwarf_regname(re, oplist[i].fp_register));
5950			break;
5951		case DW_CFA_set_loc:
5952			pc = oplist[i].fp_offset;
5953			printf(": to %08jx", (uintmax_t) pc);
5954			break;
5955		case DW_CFA_advance_loc1:
5956		case DW_CFA_advance_loc2:
5957		case DW_CFA_advance_loc4:
5958			pc += oplist[i].fp_offset;
5959			printf(": %jd to %08jx", (intmax_t) oplist[i].fp_offset,
5960			    (uintmax_t) pc);
5961			break;
5962		case DW_CFA_def_cfa:
5963			printf(": r%u (%s) ofs %ju", oplist[i].fp_register,
5964			    dwarf_regname(re, oplist[i].fp_register),
5965			    (uintmax_t) oplist[i].fp_offset);
5966			break;
5967		case DW_CFA_def_cfa_sf:
5968			printf(": r%u (%s) ofs %jd", oplist[i].fp_register,
5969			    dwarf_regname(re, oplist[i].fp_register),
5970			    (intmax_t) (oplist[i].fp_offset * daf));
5971			break;
5972		case DW_CFA_def_cfa_register:
5973			printf(": r%u (%s)", oplist[i].fp_register,
5974			    dwarf_regname(re, oplist[i].fp_register));
5975			break;
5976		case DW_CFA_def_cfa_offset:
5977			printf(": %ju", (uintmax_t) oplist[i].fp_offset);
5978			break;
5979		case DW_CFA_def_cfa_offset_sf:
5980			printf(": %jd", (intmax_t) (oplist[i].fp_offset * daf));
5981			break;
5982		default:
5983			break;
5984		}
5985		putchar('\n');
5986	}
5987
5988	dwarf_dealloc(dbg, oplist, DW_DLA_FRAME_BLOCK);
5989}
5990
5991static char *
5992get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off)
5993{
5994	static char rs[16];
5995
5996	if (reg == DW_FRAME_UNDEFINED_VAL || reg == DW_FRAME_REG_INITIAL_VALUE)
5997		snprintf(rs, sizeof(rs), "%c", 'u');
5998	else if (reg == DW_FRAME_CFA_COL)
5999		snprintf(rs, sizeof(rs), "c%+jd", (intmax_t) off);
6000	else
6001		snprintf(rs, sizeof(rs), "%s%+jd", dwarf_regname(re, reg),
6002		    (intmax_t) off);
6003
6004	return (rs);
6005}
6006
6007static int
6008dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde, Dwarf_Addr pc,
6009    Dwarf_Unsigned func_len, Dwarf_Half cie_ra)
6010{
6011	Dwarf_Regtable rt;
6012	Dwarf_Addr row_pc, end_pc, pre_pc, cur_pc;
6013	Dwarf_Error de;
6014	char *vec;
6015	int i;
6016
6017#define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7))
6018#define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7)))
6019#define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7)))
6020#define	RT(x) rt.rules[(x)]
6021
6022	vec = calloc((DW_REG_TABLE_SIZE + 7) / 8, 1);
6023	if (vec == NULL)
6024		err(EXIT_FAILURE, "calloc failed");
6025
6026	pre_pc = ~((Dwarf_Addr) 0);
6027	cur_pc = pc;
6028	end_pc = pc + func_len;
6029	for (; cur_pc < end_pc; cur_pc++) {
6030		if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc,
6031		    &de) != DW_DLV_OK) {
6032			free(vec);
6033			warnx("dwarf_get_fde_info_for_all_regs failed: %s\n",
6034			    dwarf_errmsg(de));
6035			return (-1);
6036		}
6037		if (row_pc == pre_pc)
6038			continue;
6039		pre_pc = row_pc;
6040		for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
6041			if (rt.rules[i].dw_regnum != DW_FRAME_REG_INITIAL_VALUE)
6042				BIT_SET(vec, i);
6043		}
6044	}
6045
6046	printf("   LOC   CFA      ");
6047	for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
6048		if (BIT_ISSET(vec, i)) {
6049			if ((Dwarf_Half) i == cie_ra)
6050				printf("ra   ");
6051			else
6052				printf("%-5s",
6053				    dwarf_regname(re, (unsigned int) i));
6054		}
6055	}
6056	putchar('\n');
6057
6058	pre_pc = ~((Dwarf_Addr) 0);
6059	cur_pc = pc;
6060	end_pc = pc + func_len;
6061	for (; cur_pc < end_pc; cur_pc++) {
6062		if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc,
6063		    &de) != DW_DLV_OK) {
6064			free(vec);
6065			warnx("dwarf_get_fde_info_for_all_regs failed: %s\n",
6066			    dwarf_errmsg(de));
6067			return (-1);
6068		}
6069		if (row_pc == pre_pc)
6070			continue;
6071		pre_pc = row_pc;
6072		printf("%08jx ", (uintmax_t) row_pc);
6073		printf("%-8s ", get_regoff_str(re, RT(0).dw_regnum,
6074		    RT(0).dw_offset));
6075		for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
6076			if (BIT_ISSET(vec, i)) {
6077				printf("%-5s", get_regoff_str(re,
6078				    RT(i).dw_regnum, RT(i).dw_offset));
6079			}
6080		}
6081		putchar('\n');
6082	}
6083
6084	free(vec);
6085
6086	return (0);
6087
6088#undef	BIT_SET
6089#undef	BIT_CLR
6090#undef	BIT_ISSET
6091#undef	RT
6092}
6093
6094static void
6095dump_dwarf_frame_section(struct readelf *re, struct section *s, int alt)
6096{
6097	Dwarf_Cie *cie_list, cie, pre_cie;
6098	Dwarf_Fde *fde_list, fde;
6099	Dwarf_Off cie_offset, fde_offset;
6100	Dwarf_Unsigned cie_length, fde_instlen;
6101	Dwarf_Unsigned cie_caf, cie_daf, cie_instlen, func_len, fde_length;
6102	Dwarf_Signed cie_count, fde_count, cie_index;
6103	Dwarf_Addr low_pc;
6104	Dwarf_Half cie_ra;
6105	Dwarf_Small cie_version;
6106	Dwarf_Ptr fde_addr, fde_inst, cie_inst;
6107	char *cie_aug, c;
6108	int i, eh_frame;
6109	Dwarf_Error de;
6110
6111	printf("\nThe section %s contains:\n\n", s->name);
6112
6113	if (!strcmp(s->name, ".debug_frame")) {
6114		eh_frame = 0;
6115		if (dwarf_get_fde_list(re->dbg, &cie_list, &cie_count,
6116		    &fde_list, &fde_count, &de) != DW_DLV_OK) {
6117			warnx("dwarf_get_fde_list failed: %s",
6118			    dwarf_errmsg(de));
6119			return;
6120		}
6121	} else if (!strcmp(s->name, ".eh_frame")) {
6122		eh_frame = 1;
6123		if (dwarf_get_fde_list_eh(re->dbg, &cie_list, &cie_count,
6124		    &fde_list, &fde_count, &de) != DW_DLV_OK) {
6125			warnx("dwarf_get_fde_list_eh failed: %s",
6126			    dwarf_errmsg(de));
6127			return;
6128		}
6129	} else
6130		return;
6131
6132	pre_cie = NULL;
6133	for (i = 0; i < fde_count; i++) {
6134		if (dwarf_get_fde_n(fde_list, i, &fde, &de) != DW_DLV_OK) {
6135			warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de));
6136			continue;
6137		}
6138		if (dwarf_get_cie_of_fde(fde, &cie, &de) != DW_DLV_OK) {
6139			warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de));
6140			continue;
6141		}
6142		if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_addr,
6143		    &fde_length, &cie_offset, &cie_index, &fde_offset,
6144		    &de) != DW_DLV_OK) {
6145			warnx("dwarf_get_fde_range failed: %s",
6146			    dwarf_errmsg(de));
6147			continue;
6148		}
6149		if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_instlen,
6150		    &de) != DW_DLV_OK) {
6151			warnx("dwarf_get_fde_instr_bytes failed: %s",
6152			    dwarf_errmsg(de));
6153			continue;
6154		}
6155		if (pre_cie == NULL || cie != pre_cie) {
6156			pre_cie = cie;
6157			if (dwarf_get_cie_info(cie, &cie_length, &cie_version,
6158			    &cie_aug, &cie_caf, &cie_daf, &cie_ra,
6159			    &cie_inst, &cie_instlen, &de) != DW_DLV_OK) {
6160				warnx("dwarf_get_cie_info failed: %s",
6161				    dwarf_errmsg(de));
6162				continue;
6163			}
6164			printf("%08jx %08jx %8.8jx CIE",
6165			    (uintmax_t) cie_offset,
6166			    (uintmax_t) cie_length,
6167			    (uintmax_t) (eh_frame ? 0 : ~0U));
6168			if (!alt) {
6169				putchar('\n');
6170				printf("  Version:\t\t\t%u\n", cie_version);
6171				printf("  Augmentation:\t\t\t\"");
6172				while ((c = *cie_aug++) != '\0')
6173					putchar(c);
6174				printf("\"\n");
6175				printf("  Code alignment factor:\t%ju\n",
6176				    (uintmax_t) cie_caf);
6177				printf("  Data alignment factor:\t%jd\n",
6178				    (intmax_t) cie_daf);
6179				printf("  Return address column:\t%ju\n",
6180				    (uintmax_t) cie_ra);
6181				putchar('\n');
6182				dump_dwarf_frame_inst(re, cie, cie_inst,
6183				    cie_instlen, cie_caf, cie_daf, 0,
6184				    re->dbg);
6185				putchar('\n');
6186			} else {
6187				printf(" \"");
6188				while ((c = *cie_aug++) != '\0')
6189					putchar(c);
6190				putchar('"');
6191				printf(" cf=%ju df=%jd ra=%ju\n",
6192				    (uintmax_t) cie_caf,
6193				    (uintmax_t) cie_daf,
6194				    (uintmax_t) cie_ra);
6195				dump_dwarf_frame_regtable(re, fde, low_pc, 1,
6196				    cie_ra);
6197				putchar('\n');
6198			}
6199		}
6200		printf("%08jx %08jx %08jx FDE cie=%08jx pc=%08jx..%08jx\n",
6201		    (uintmax_t) fde_offset, (uintmax_t) fde_length,
6202		    (uintmax_t) cie_offset,
6203		    (uintmax_t) (eh_frame ? fde_offset + 4 - cie_offset :
6204			cie_offset),
6205		    (uintmax_t) low_pc, (uintmax_t) (low_pc + func_len));
6206		if (!alt)
6207			dump_dwarf_frame_inst(re, cie, fde_inst, fde_instlen,
6208			    cie_caf, cie_daf, low_pc, re->dbg);
6209		else
6210			dump_dwarf_frame_regtable(re, fde, low_pc, func_len,
6211			    cie_ra);
6212		putchar('\n');
6213	}
6214}
6215
6216static void
6217dump_dwarf_frame(struct readelf *re, int alt)
6218{
6219	struct section *s;
6220	int i;
6221
6222	(void) dwarf_set_frame_cfa_value(re->dbg, DW_FRAME_CFA_COL);
6223
6224	for (i = 0; (size_t) i < re->shnum; i++) {
6225		s = &re->sl[i];
6226		if (s->name != NULL && (!strcmp(s->name, ".debug_frame") ||
6227		    !strcmp(s->name, ".eh_frame")))
6228			dump_dwarf_frame_section(re, s, alt);
6229	}
6230}
6231
6232static void
6233dump_dwarf_str(struct readelf *re)
6234{
6235	struct section *s;
6236	Elf_Data *d;
6237	unsigned char *p;
6238	int elferr, end, i, j;
6239
6240	printf("\nContents of section .debug_str:\n");
6241
6242	s = NULL;
6243	for (i = 0; (size_t) i < re->shnum; i++) {
6244		s = &re->sl[i];
6245		if (s->name != NULL && !strcmp(s->name, ".debug_str"))
6246			break;
6247	}
6248	if ((size_t) i >= re->shnum)
6249		return;
6250
6251	(void) elf_errno();
6252	if ((d = elf_getdata(s->scn, NULL)) == NULL) {
6253		elferr = elf_errno();
6254		if (elferr != 0)
6255			warnx("elf_getdata failed: %s", elf_errmsg(-1));
6256		return;
6257	}
6258	if (d->d_size <= 0)
6259		return;
6260
6261	for (i = 0, p = d->d_buf; (size_t) i < d->d_size; i += 16) {
6262		printf("  0x%08x", (unsigned int) i);
6263		if ((size_t) i + 16 > d->d_size)
6264			end = d->d_size;
6265		else
6266			end = i + 16;
6267		for (j = i; j < i + 16; j++) {
6268			if ((j - i) % 4 == 0)
6269				putchar(' ');
6270			if (j >= end) {
6271				printf("  ");
6272				continue;
6273			}
6274			printf("%02x", (uint8_t) p[j]);
6275		}
6276		putchar(' ');
6277		for (j = i; j < end; j++) {
6278			if (isprint(p[j]))
6279				putchar(p[j]);
6280			else if (p[j] == 0)
6281				putchar('.');
6282			else
6283				putchar(' ');
6284		}
6285		putchar('\n');
6286	}
6287}
6288
6289static int
6290loc_at_comparator(const void *la1, const void *la2)
6291{
6292	const struct loc_at *left, *right;
6293
6294	left = (const struct loc_at *)la1;
6295	right = (const struct loc_at *)la2;
6296
6297	if (left->la_off > right->la_off)
6298		return (1);
6299	else if (left->la_off < right->la_off)
6300		return (-1);
6301	else
6302		return (0);
6303}
6304
6305static void
6306search_loclist_at(struct readelf *re, Dwarf_Die