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 #include <ar.h>
30 #include <assert.h>
31 #include <ctype.h>
32 #include <dwarf.h>
33 #include <err.h>
34 #include <fcntl.h>
35 #include <gelf.h>
36 #include <getopt.h>
37 #include <libdwarf.h>
38 #include <libelftc.h>
39 #include <libgen.h>
40 #include <stdarg.h>
41 #include <stdbool.h>
42 #include <stdint.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <unistd.h>
48 #include <zlib.h>
49
50 #include "_elftc.h"
51
52 ELFTC_VCSID("$Id: readelf.c 3769 2019-06-29 15:15:02Z emaste $");
53
54 /* Backwards compatability for older FreeBSD releases. */
55 #ifndef STB_GNU_UNIQUE
56 #define STB_GNU_UNIQUE 10
57 #endif
58 #ifndef STT_SPARC_REGISTER
59 #define STT_SPARC_REGISTER 13
60 #endif
61
62
63 /*
64 * readelf(1) options.
65 */
66 #define RE_AA 0x00000001
67 #define RE_C 0x00000002
68 #define RE_DD 0x00000004
69 #define RE_D 0x00000008
70 #define RE_G 0x00000010
71 #define RE_H 0x00000020
72 #define RE_II 0x00000040
73 #define RE_I 0x00000080
74 #define RE_L 0x00000100
75 #define RE_NN 0x00000200
76 #define RE_N 0x00000400
77 #define RE_P 0x00000800
78 #define RE_R 0x00001000
79 #define RE_SS 0x00002000
80 #define RE_S 0x00004000
81 #define RE_T 0x00008000
82 #define RE_U 0x00010000
83 #define RE_VV 0x00020000
84 #define RE_WW 0x00040000
85 #define RE_W 0x00080000
86 #define RE_X 0x00100000
87 #define RE_Z 0x00200000
88
89 /*
90 * dwarf dump options.
91 */
92 #define DW_A 0x00000001
93 #define DW_FF 0x00000002
94 #define DW_F 0x00000004
95 #define DW_I 0x00000008
96 #define DW_LL 0x00000010
97 #define DW_L 0x00000020
98 #define DW_M 0x00000040
99 #define DW_O 0x00000080
100 #define DW_P 0x00000100
101 #define DW_RR 0x00000200
102 #define DW_R 0x00000400
103 #define DW_S 0x00000800
104
105 #define DW_DEFAULT_OPTIONS (DW_A | DW_F | DW_I | DW_L | DW_O | DW_P | \
106 DW_R | DW_RR | DW_S)
107
108 /*
109 * readelf(1) run control flags.
110 */
111 #define DISPLAY_FILENAME 0x0001
112
113 /*
114 * Internal data structure for sections.
115 */
116 struct section {
117 const char *name; /* section name */
118 Elf_Scn *scn; /* section scn */
119 uint64_t off; /* section offset */
120 uint64_t sz; /* section size */
121 uint64_t entsize; /* section entsize */
122 uint64_t align; /* section alignment */
123 uint64_t type; /* section type */
124 uint64_t flags; /* section flags */
125 uint64_t addr; /* section virtual addr */
126 uint32_t link; /* section link ndx */
127 uint32_t info; /* section info ndx */
128 };
129
130 struct dumpop {
131 union {
132 size_t si; /* section index */
133 const char *sn; /* section name */
134 } u;
135 enum {
136 DUMP_BY_INDEX = 0,
137 DUMP_BY_NAME
138 } type; /* dump type */
139 #define HEX_DUMP 0x0001
140 #define STR_DUMP 0x0002
141 int op; /* dump operation */
142 STAILQ_ENTRY(dumpop) dumpop_list;
143 };
144
145 struct symver {
146 const char *name;
147 int type;
148 };
149
150 /*
151 * Structure encapsulates the global data for readelf(1).
152 */
153 struct readelf {
154 const char *filename; /* current processing file. */
155 int options; /* command line options. */
156 int flags; /* run control flags. */
157 int dop; /* dwarf dump options. */
158 Elf *elf; /* underlying ELF descriptor. */
159 Elf *ar; /* archive ELF descriptor. */
160 Dwarf_Debug dbg; /* DWARF handle. */
161 Dwarf_Half cu_psize; /* DWARF CU pointer size. */
162 Dwarf_Half cu_osize; /* DWARF CU offset size. */
163 Dwarf_Half cu_ver; /* DWARF CU version. */
164 GElf_Ehdr ehdr; /* ELF header. */
165 int ec; /* ELF class. */
166 size_t shnum; /* #sections. */
167 struct section *vd_s; /* Verdef section. */
168 struct section *vn_s; /* Verneed section. */
169 struct section *vs_s; /* Versym section. */
170 uint16_t *vs; /* Versym array. */
171 int vs_sz; /* Versym array size. */
172 struct symver *ver; /* Version array. */
173 int ver_sz; /* Size of version array. */
174 struct section *sl; /* list of sections. */
175 STAILQ_HEAD(, dumpop) v_dumpop; /* list of dump ops. */
176 uint64_t (*dw_read)(Elf_Data *, uint64_t *, int);
177 uint64_t (*dw_decode)(uint8_t **, int);
178 };
179
180 enum options
181 {
182 OPTION_DEBUG_DUMP
183 };
184
185 static struct option longopts[] = {
186 {"all", no_argument, NULL, 'a'},
187 {"arch-specific", no_argument, NULL, 'A'},
188 {"archive-index", no_argument, NULL, 'c'},
189 {"debug-dump", optional_argument, NULL, OPTION_DEBUG_DUMP},
190 {"decompress", no_argument, 0, 'z'},
191 {"dynamic", no_argument, NULL, 'd'},
192 {"file-header", no_argument, NULL, 'h'},
193 {"full-section-name", no_argument, NULL, 'N'},
194 {"headers", no_argument, NULL, 'e'},
195 {"help", no_argument, 0, 'H'},
196 {"hex-dump", required_argument, NULL, 'x'},
197 {"histogram", no_argument, NULL, 'I'},
198 {"notes", no_argument, NULL, 'n'},
199 {"program-headers", no_argument, NULL, 'l'},
200 {"relocs", no_argument, NULL, 'r'},
201 {"sections", no_argument, NULL, 'S'},
202 {"section-headers", no_argument, NULL, 'S'},
203 {"section-groups", no_argument, NULL, 'g'},
204 {"section-details", no_argument, NULL, 't'},
205 {"segments", no_argument, NULL, 'l'},
206 {"string-dump", required_argument, NULL, 'p'},
207 {"symbols", no_argument, NULL, 's'},
208 {"syms", no_argument, NULL, 's'},
209 {"unwind", no_argument, NULL, 'u'},
210 {"use-dynamic", no_argument, NULL, 'D'},
211 {"version-info", no_argument, 0, 'V'},
212 {"version", no_argument, 0, 'v'},
213 {"wide", no_argument, 0, 'W'},
214 {NULL, 0, NULL, 0}
215 };
216
217 struct eflags_desc {
218 uint64_t flag;
219 const char *desc;
220 };
221
222 struct flag_desc {
223 uint64_t flag;
224 const char *desc;
225 };
226
227 struct mips_option {
228 uint64_t flag;
229 const char *desc;
230 };
231
232 struct loc_at {
233 Dwarf_Attribute la_at;
234 Dwarf_Unsigned la_off;
235 Dwarf_Unsigned la_lowpc;
236 Dwarf_Half la_cu_psize;
237 Dwarf_Half la_cu_osize;
238 Dwarf_Half la_cu_ver;
239 };
240
241 static void add_dumpop(struct readelf *re, size_t si, const char *sn, int op,
242 int t);
243 static const char *aeabi_adv_simd_arch(uint64_t simd);
244 static const char *aeabi_align_needed(uint64_t an);
245 static const char *aeabi_align_preserved(uint64_t ap);
246 static const char *aeabi_arm_isa(uint64_t ai);
247 static const char *aeabi_cpu_arch(uint64_t arch);
248 static const char *aeabi_cpu_arch_profile(uint64_t pf);
249 static const char *aeabi_div(uint64_t du);
250 static const char *aeabi_enum_size(uint64_t es);
251 static const char *aeabi_fp_16bit_format(uint64_t fp16);
252 static const char *aeabi_fp_arch(uint64_t fp);
253 static const char *aeabi_fp_denormal(uint64_t fd);
254 static const char *aeabi_fp_exceptions(uint64_t fe);
255 static const char *aeabi_fp_hpext(uint64_t fh);
256 static const char *aeabi_fp_number_model(uint64_t fn);
257 static const char *aeabi_fp_optm_goal(uint64_t fog);
258 static const char *aeabi_fp_rounding(uint64_t fr);
259 static const char *aeabi_hardfp(uint64_t hfp);
260 static const char *aeabi_mpext(uint64_t mp);
261 static const char *aeabi_optm_goal(uint64_t og);
262 static const char *aeabi_pcs_config(uint64_t pcs);
263 static const char *aeabi_pcs_got(uint64_t got);
264 static const char *aeabi_pcs_r9(uint64_t r9);
265 static const char *aeabi_pcs_ro(uint64_t ro);
266 static const char *aeabi_pcs_rw(uint64_t rw);
267 static const char *aeabi_pcs_wchar_t(uint64_t wt);
268 static const char *aeabi_t2ee(uint64_t t2ee);
269 static const char *aeabi_thumb_isa(uint64_t ti);
270 static const char *aeabi_fp_user_exceptions(uint64_t fu);
271 static const char *aeabi_unaligned_access(uint64_t ua);
272 static const char *aeabi_vfp_args(uint64_t va);
273 static const char *aeabi_virtual(uint64_t vt);
274 static const char *aeabi_wmmx_arch(uint64_t wmmx);
275 static const char *aeabi_wmmx_args(uint64_t wa);
276 static const char *elf_class(unsigned int class);
277 static const char *elf_endian(unsigned int endian);
278 static const char *elf_machine(unsigned int mach);
279 static const char *elf_osabi(unsigned int abi);
280 static const char *elf_type(unsigned int type);
281 static const char *elf_ver(unsigned int ver);
282 static const char *dt_type(unsigned int mach, unsigned int dtype);
283 static bool dump_ar(struct readelf *re, int);
284 static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe);
285 static void dump_attributes(struct readelf *re);
286 static uint8_t *dump_compatibility_tag(uint8_t *p, uint8_t *pe);
287 static void dump_dwarf(struct readelf *re);
288 static void dump_dwarf_abbrev(struct readelf *re);
289 static void dump_dwarf_aranges(struct readelf *re);
290 static void dump_dwarf_block(struct readelf *re, uint8_t *b,
291 Dwarf_Unsigned len);
292 static void dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level);
293 static void dump_dwarf_frame(struct readelf *re, int alt);
294 static void dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie,
295 uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf,
296 Dwarf_Addr pc, Dwarf_Debug dbg);
297 static int dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde,
298 Dwarf_Addr pc, Dwarf_Unsigned func_len, Dwarf_Half cie_ra);
299 static void dump_dwarf_frame_section(struct readelf *re, struct section *s,
300 int alt);
301 static void dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info);
302 static void dump_dwarf_macinfo(struct readelf *re);
303 static void dump_dwarf_line(struct readelf *re);
304 static void dump_dwarf_line_decoded(struct readelf *re);
305 static void dump_dwarf_loc(struct readelf *re, Dwarf_Loc *lr);
306 static void dump_dwarf_loclist(struct readelf *re);
307 static void dump_dwarf_pubnames(struct readelf *re);
308 static void dump_dwarf_ranges(struct readelf *re);
309 static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die,
310 Dwarf_Addr base);
311 static void dump_dwarf_str(struct readelf *re);
312 static void dump_eflags(struct readelf *re, uint64_t e_flags);
313 static bool dump_elf(struct readelf *re);
314 static void dump_flags(struct flag_desc *fd, uint64_t flags);
315 static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab);
316 static void dump_dynamic(struct readelf *re);
317 static void dump_liblist(struct readelf *re);
318 static void dump_mips_abiflags(struct readelf *re, struct section *s);
319 static void dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe);
320 static void dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz);
321 static void dump_mips_options(struct readelf *re, struct section *s);
322 static void dump_mips_option_flags(const char *name, struct mips_option *opt,
323 uint64_t info);
324 static void dump_mips_reginfo(struct readelf *re, struct section *s);
325 static void dump_mips_specific_info(struct readelf *re);
326 static void dump_notes(struct readelf *re);
327 static void dump_notes_content(struct readelf *re, const char *buf, size_t sz,
328 off_t off);
329 static void dump_notes_data(struct readelf *re, const char *name,
330 uint32_t type, const char *buf, size_t sz);
331 static void dump_svr4_hash(struct section *s);
332 static void dump_svr4_hash64(struct readelf *re, struct section *s);
333 static void dump_gnu_hash(struct readelf *re, struct section *s);
334 static void dump_gnu_property_type_0(struct readelf *re, const char *buf,
335 size_t sz);
336 static void dump_hash(struct readelf *re);
337 static void dump_phdr(struct readelf *re);
338 static void dump_ppc_attributes(uint8_t *p, uint8_t *pe);
339 static void dump_section_groups(struct readelf *re);
340 static void dump_symtab(struct readelf *re, int i);
341 static void dump_symtabs(struct readelf *re);
342 static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe);
343 static void dump_ver(struct readelf *re);
344 static void dump_verdef(struct readelf *re, int dump);
345 static void dump_verneed(struct readelf *re, int dump);
346 static void dump_versym(struct readelf *re);
347 static const char *dwarf_reg(unsigned int mach, unsigned int reg);
348 static const char *dwarf_regname(struct readelf *re, unsigned int num);
349 static struct dumpop *find_dumpop(struct readelf *re, size_t si,
350 const char *sn, int op, int t);
351 static int get_ent_count(struct section *s, int *ent_count);
352 static int get_mips_register_size(uint8_t flag);
353 static char *get_regoff_str(struct readelf *re, Dwarf_Half reg,
354 Dwarf_Addr off);
355 static const char *get_string(struct readelf *re, int strtab, size_t off);
356 static const char *get_symbol_name(struct readelf *re, int symtab, int i);
357 static uint64_t get_symbol_value(struct readelf *re, int symtab, int i);
358 static void load_sections(struct readelf *re);
359 static int loc_at_comparator(const void *la1, const void *la2);
360 static const char *mips_abi_fp(uint64_t fp);
361 static const char *note_type(const char *note_name, unsigned int et,
362 unsigned int nt);
363 static const char *note_type_freebsd(unsigned int nt);
364 static const char *note_type_freebsd_core(unsigned int nt);
365 static const char *note_type_go(unsigned int nt);
366 static const char *note_type_gnu(unsigned int nt);
367 static const char *note_type_linux_core(unsigned int nt);
368 static const char *note_type_netbsd(unsigned int nt);
369 static const char *note_type_openbsd(unsigned int nt);
370 static const char *note_type_unknown(unsigned int nt);
371 static const char *note_type_xen(unsigned int nt);
372 static const char *option_kind(uint8_t kind);
373 static const char *phdr_type(unsigned int mach, unsigned int ptype);
374 static const char *ppc_abi_fp(uint64_t fp);
375 static const char *ppc_abi_vector(uint64_t vec);
376 static void readelf_usage(int status);
377 static void readelf_version(void);
378 static 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);
381 static void search_ver(struct readelf *re);
382 static const char *section_type(unsigned int mach, unsigned int stype);
383 static void set_cu_context(struct readelf *re, Dwarf_Half psize,
384 Dwarf_Half osize, Dwarf_Half ver);
385 static const char *st_bind(unsigned int sbind);
386 static const char *st_shndx(unsigned int shndx);
387 static const char *st_type(unsigned int mach, unsigned int os,
388 unsigned int stype);
389 static const char *st_vis(unsigned int svis);
390 static const char *top_tag(unsigned int tag);
391 static void unload_sections(struct readelf *re);
392 static uint64_t _read_lsb(Elf_Data *d, uint64_t *offsetp,
393 int bytes_to_read);
394 static uint64_t _read_msb(Elf_Data *d, uint64_t *offsetp,
395 int bytes_to_read);
396 static uint64_t _decode_lsb(uint8_t **data, int bytes_to_read);
397 static uint64_t _decode_msb(uint8_t **data, int bytes_to_read);
398 static int64_t _decode_sleb128(uint8_t **dp, uint8_t *dpe);
399 static uint64_t _decode_uleb128(uint8_t **dp, uint8_t *dpe);
400
401 static 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
422 static 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
434 static 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
441 static 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
448 static 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
456 static const char *
elf_osabi(unsigned int abi)457 elf_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
487 static const char *
elf_machine(unsigned int mach)488 elf_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
592 static const char *
elf_class(unsigned int class)593 elf_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
607 static const char *
elf_endian(unsigned int endian)608 elf_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
622 static const char *
elf_type(unsigned int type)623 elf_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
645 static const char *
elf_ver(unsigned int ver)646 elf_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
660 static const char *
phdr_type(unsigned int mach,unsigned int ptype)661 phdr_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
705 static const char *
section_type(unsigned int mach,unsigned int stype)706 section_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
817 static const char *
dt_type(unsigned int mach,unsigned int dtype)818 dt_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
1023 static const char *
st_bind(unsigned int sbind)1024 st_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
1045 static const char *
st_type(unsigned int mach,unsigned int os,unsigned int stype)1046 st_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
1077 static const char *
st_vis(unsigned int svis)1078 st_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
1093 static const char *
st_shndx(unsigned int shndx)1094 st_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
1113 static 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
1131 static const char *
note_type(const char * name,unsigned int et,unsigned int nt)1132 note_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, "Go") == 0 && et != ET_CORE)
1145 return note_type_go(nt);
1146 else if (strcmp(name, "NetBSD") == 0 && et != ET_CORE)
1147 return note_type_netbsd(nt);
1148 else if (strcmp(name, "OpenBSD") == 0 && et != ET_CORE)
1149 return note_type_openbsd(nt);
1150 else if (strcmp(name, "Xen") == 0 && et != ET_CORE)
1151 return note_type_xen(nt);
1152 return note_type_unknown(nt);
1153 }
1154
1155 static const char *
note_type_freebsd(unsigned int nt)1156 note_type_freebsd(unsigned int nt)
1157 {
1158 switch (nt) {
1159 case 1: return "NT_FREEBSD_ABI_TAG";
1160 case 2: return "NT_FREEBSD_NOINIT_TAG";
1161 case 3: return "NT_FREEBSD_ARCH_TAG";
1162 case 4: return "NT_FREEBSD_FEATURE_CTL";
1163 default: return (note_type_unknown(nt));
1164 }
1165 }
1166
1167 static const char *
note_type_freebsd_core(unsigned int nt)1168 note_type_freebsd_core(unsigned int nt)
1169 {
1170 switch (nt) {
1171 case 1: return "NT_PRSTATUS";
1172 case 2: return "NT_FPREGSET";
1173 case 3: return "NT_PRPSINFO";
1174 case 7: return "NT_THRMISC";
1175 case 8: return "NT_PROCSTAT_PROC";
1176 case 9: return "NT_PROCSTAT_FILES";
1177 case 10: return "NT_PROCSTAT_VMMAP";
1178 case 11: return "NT_PROCSTAT_GROUPS";
1179 case 12: return "NT_PROCSTAT_UMASK";
1180 case 13: return "NT_PROCSTAT_RLIMIT";
1181 case 14: return "NT_PROCSTAT_OSREL";
1182 case 15: return "NT_PROCSTAT_PSSTRINGS";
1183 case 16: return "NT_PROCSTAT_AUXV";
1184 case 17: return "NT_PTLWPINFO";
1185 case 0x100: return "NT_PPC_VMX (ppc Altivec registers)";
1186 case 0x102: return "NT_PPC_VSX (ppc VSX registers)";
1187 case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)";
1188 case 0x400: return "NT_ARM_VFP (arm VFP registers)";
1189 case 0x406: return "NT_ARM_ADDR_MASK (arm address mask)";
1190 default: return (note_type_unknown(nt));
1191 }
1192 }
1193
1194 static const char *
note_type_linux_core(unsigned int nt)1195 note_type_linux_core(unsigned int nt)
1196 {
1197 switch (nt) {
1198 case 1: return "NT_PRSTATUS (Process status)";
1199 case 2: return "NT_FPREGSET (Floating point information)";
1200 case 3: return "NT_PRPSINFO (Process information)";
1201 case 4: return "NT_TASKSTRUCT (Task structure)";
1202 case 6: return "NT_AUXV (Auxiliary vector)";
1203 case 10: return "NT_PSTATUS (Linux process status)";
1204 case 12: return "NT_FPREGS (Linux floating point regset)";
1205 case 13: return "NT_PSINFO (Linux process information)";
1206 case 16: return "NT_LWPSTATUS (Linux lwpstatus_t type)";
1207 case 17: return "NT_LWPSINFO (Linux lwpinfo_t type)";
1208 case 18: return "NT_WIN32PSTATUS (win32_pstatus structure)";
1209 case 0x100: return "NT_PPC_VMX (ppc Altivec registers)";
1210 case 0x102: return "NT_PPC_VSX (ppc VSX registers)";
1211 case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)";
1212 case 0x300: return "NT_S390_HIGH_GPRS (s390 upper register halves)";
1213 case 0x301: return "NT_S390_TIMER (s390 timer register)";
1214 case 0x302: return "NT_S390_TODCMP (s390 TOD comparator register)";
1215 case 0x303: return "NT_S390_TODPREG (s390 TOD programmable register)";
1216 case 0x304: return "NT_S390_CTRS (s390 control registers)";
1217 case 0x305: return "NT_S390_PREFIX (s390 prefix register)";
1218 case 0x400: return "NT_ARM_VFP (arm VFP registers)";
1219 case 0x46494c45UL: return "NT_FILE (mapped files)";
1220 case 0x46E62B7FUL: return "NT_PRXFPREG (Linux user_xfpregs structure)";
1221 case 0x53494749UL: return "NT_SIGINFO (siginfo_t data)";
1222 default: return (note_type_unknown(nt));
1223 }
1224 }
1225
1226 static const char *
note_type_gnu(unsigned int nt)1227 note_type_gnu(unsigned int nt)
1228 {
1229 switch (nt) {
1230 case 1: return "NT_GNU_ABI_TAG";
1231 case 2: return "NT_GNU_HWCAP (Hardware capabilities)";
1232 case 3: return "NT_GNU_BUILD_ID (Build id set by ld(1))";
1233 case 4: return "NT_GNU_GOLD_VERSION (GNU gold version)";
1234 case 5: return "NT_GNU_PROPERTY_TYPE_0";
1235 default: return (note_type_unknown(nt));
1236 }
1237 }
1238
1239 static const char *
note_type_go(unsigned int nt)1240 note_type_go(unsigned int nt)
1241 {
1242 switch (nt) {
1243 case 4: return "elfGoBuildIDTag";
1244 default: return (note_type_unknown(nt));
1245 }
1246 }
1247
1248 static const char *
note_type_netbsd(unsigned int nt)1249 note_type_netbsd(unsigned int nt)
1250 {
1251 switch (nt) {
1252 case 1: return "NT_NETBSD_IDENT";
1253 default: return (note_type_unknown(nt));
1254 }
1255 }
1256
1257 static const char *
note_type_openbsd(unsigned int nt)1258 note_type_openbsd(unsigned int nt)
1259 {
1260 switch (nt) {
1261 case 1: return "NT_OPENBSD_IDENT";
1262 default: return (note_type_unknown(nt));
1263 }
1264 }
1265
1266 static const char *
note_type_unknown(unsigned int nt)1267 note_type_unknown(unsigned int nt)
1268 {
1269 static char s_nt[32];
1270
1271 snprintf(s_nt, sizeof(s_nt),
1272 nt >= 0x100 ? "<unknown: 0x%x>" : "<unknown: %u>", nt);
1273 return (s_nt);
1274 }
1275
1276 static const char *
note_type_xen(unsigned int nt)1277 note_type_xen(unsigned int nt)
1278 {
1279 switch (nt) {
1280 case 0: return "XEN_ELFNOTE_INFO";
1281 case 1: return "XEN_ELFNOTE_ENTRY";
1282 case 2: return "XEN_ELFNOTE_HYPERCALL_PAGE";
1283 case 3: return "XEN_ELFNOTE_VIRT_BASE";
1284 case 4: return "XEN_ELFNOTE_PADDR_OFFSET";
1285 case 5: return "XEN_ELFNOTE_XEN_VERSION";
1286 case 6: return "XEN_ELFNOTE_GUEST_OS";
1287 case 7: return "XEN_ELFNOTE_GUEST_VERSION";
1288 case 8: return "XEN_ELFNOTE_LOADER";
1289 case 9: return "XEN_ELFNOTE_PAE_MODE";
1290 case 10: return "XEN_ELFNOTE_FEATURES";
1291 case 11: return "XEN_ELFNOTE_BSD_SYMTAB";
1292 case 12: return "XEN_ELFNOTE_HV_START_LOW";
1293 case 13: return "XEN_ELFNOTE_L1_MFN_VALID";
1294 case 14: return "XEN_ELFNOTE_SUSPEND_CANCEL";
1295 case 15: return "XEN_ELFNOTE_INIT_P2M";
1296 case 16: return "XEN_ELFNOTE_MOD_START_PFN";
1297 case 17: return "XEN_ELFNOTE_SUPPORTED_FEATURES";
1298 case 18: return "XEN_ELFNOTE_PHYS32_ENTRY";
1299 default: return (note_type_unknown(nt));
1300 }
1301 }
1302
1303 static struct {
1304 const char *name;
1305 int value;
1306 } l_flag[] = {
1307 {"EXACT_MATCH", LL_EXACT_MATCH},
1308 {"IGNORE_INT_VER", LL_IGNORE_INT_VER},
1309 {"REQUIRE_MINOR", LL_REQUIRE_MINOR},
1310 {"EXPORTS", LL_EXPORTS},
1311 {"DELAY_LOAD", LL_DELAY_LOAD},
1312 {"DELTA", LL_DELTA},
1313 {NULL, 0}
1314 };
1315
1316 static struct mips_option mips_exceptions_option[] = {
1317 {OEX_PAGE0, "PAGE0"},
1318 {OEX_SMM, "SMM"},
1319 {OEX_PRECISEFP, "PRECISEFP"},
1320 {OEX_DISMISS, "DISMISS"},
1321 {0, NULL}
1322 };
1323
1324 static struct mips_option mips_pad_option[] = {
1325 {OPAD_PREFIX, "PREFIX"},
1326 {OPAD_POSTFIX, "POSTFIX"},
1327 {OPAD_SYMBOL, "SYMBOL"},
1328 {0, NULL}
1329 };
1330
1331 static struct mips_option mips_hwpatch_option[] = {
1332 {OHW_R4KEOP, "R4KEOP"},
1333 {OHW_R8KPFETCH, "R8KPFETCH"},
1334 {OHW_R5KEOP, "R5KEOP"},
1335 {OHW_R5KCVTL, "R5KCVTL"},
1336 {0, NULL}
1337 };
1338
1339 static struct mips_option mips_hwa_option[] = {
1340 {OHWA0_R4KEOP_CHECKED, "R4KEOP_CHECKED"},
1341 {OHWA0_R4KEOP_CLEAN, "R4KEOP_CLEAN"},
1342 {0, NULL}
1343 };
1344
1345 static struct mips_option mips_hwo_option[] = {
1346 {OHWO0_FIXADE, "FIXADE"},
1347 {0, NULL}
1348 };
1349
1350 static const char *
option_kind(uint8_t kind)1351 option_kind(uint8_t kind)
1352 {
1353 static char s_kind[32];
1354
1355 switch (kind) {
1356 case ODK_NULL: return "NULL";
1357 case ODK_REGINFO: return "REGINFO";
1358 case ODK_EXCEPTIONS: return "EXCEPTIONS";
1359 case ODK_PAD: return "PAD";
1360 case ODK_HWPATCH: return "HWPATCH";
1361 case ODK_FILL: return "FILL";
1362 case ODK_TAGS: return "TAGS";
1363 case ODK_HWAND: return "HWAND";
1364 case ODK_HWOR: return "HWOR";
1365 case ODK_GP_GROUP: return "GP_GROUP";
1366 case ODK_IDENT: return "IDENT";
1367 default:
1368 snprintf(s_kind, sizeof(s_kind), "<unknown: %u>", kind);
1369 return (s_kind);
1370 }
1371 }
1372
1373 static const char *
top_tag(unsigned int tag)1374 top_tag(unsigned int tag)
1375 {
1376 static char s_top_tag[32];
1377
1378 switch (tag) {
1379 case 1: return "File Attributes";
1380 case 2: return "Section Attributes";
1381 case 3: return "Symbol Attributes";
1382 default:
1383 snprintf(s_top_tag, sizeof(s_top_tag), "Unknown tag: %u", tag);
1384 return (s_top_tag);
1385 }
1386 }
1387
1388 static const char *
aeabi_cpu_arch(uint64_t arch)1389 aeabi_cpu_arch(uint64_t arch)
1390 {
1391 static char s_cpu_arch[32];
1392
1393 switch (arch) {
1394 case 0: return "Pre-V4";
1395 case 1: return "ARM v4";
1396 case 2: return "ARM v4T";
1397 case 3: return "ARM v5T";
1398 case 4: return "ARM v5TE";
1399 case 5: return "ARM v5TEJ";
1400 case 6: return "ARM v6";
1401 case 7: return "ARM v6KZ";
1402 case 8: return "ARM v6T2";
1403 case 9: return "ARM v6K";
1404 case 10: return "ARM v7";
1405 case 11: return "ARM v6-M";
1406 case 12: return "ARM v6S-M";
1407 case 13: return "ARM v7E-M";
1408 default:
1409 snprintf(s_cpu_arch, sizeof(s_cpu_arch),
1410 "Unknown (%ju)", (uintmax_t) arch);
1411 return (s_cpu_arch);
1412 }
1413 }
1414
1415 static const char *
aeabi_cpu_arch_profile(uint64_t pf)1416 aeabi_cpu_arch_profile(uint64_t pf)
1417 {
1418 static char s_arch_profile[32];
1419
1420 switch (pf) {
1421 case 0:
1422 return "Not applicable";
1423 case 0x41: /* 'A' */
1424 return "Application Profile";
1425 case 0x52: /* 'R' */
1426 return "Real-Time Profile";
1427 case 0x4D: /* 'M' */
1428 return "Microcontroller Profile";
1429 case 0x53: /* 'S' */
1430 return "Application or Real-Time Profile";
1431 default:
1432 snprintf(s_arch_profile, sizeof(s_arch_profile),
1433 "Unknown (%ju)\n", (uintmax_t) pf);
1434 return (s_arch_profile);
1435 }
1436 }
1437
1438 static const char *
aeabi_arm_isa(uint64_t ai)1439 aeabi_arm_isa(uint64_t ai)
1440 {
1441 static char s_ai[32];
1442
1443 switch (ai) {
1444 case 0: return "No";
1445 case 1: return "Yes";
1446 default:
1447 snprintf(s_ai, sizeof(s_ai), "Unknown (%ju)\n",
1448 (uintmax_t) ai);
1449 return (s_ai);
1450 }
1451 }
1452
1453 static const char *
aeabi_thumb_isa(uint64_t ti)1454 aeabi_thumb_isa(uint64_t ti)
1455 {
1456 static char s_ti[32];
1457
1458 switch (ti) {
1459 case 0: return "No";
1460 case 1: return "16-bit Thumb";
1461 case 2: return "32-bit Thumb";
1462 default:
1463 snprintf(s_ti, sizeof(s_ti), "Unknown (%ju)\n",
1464 (uintmax_t) ti);
1465 return (s_ti);
1466 }
1467 }
1468
1469 static const char *
aeabi_fp_arch(uint64_t fp)1470 aeabi_fp_arch(uint64_t fp)
1471 {
1472 static char s_fp_arch[32];
1473
1474 switch (fp) {
1475 case 0: return "No";
1476 case 1: return "VFPv1";
1477 case 2: return "VFPv2";
1478 case 3: return "VFPv3";
1479 case 4: return "VFPv3-D16";
1480 case 5: return "VFPv4";
1481 case 6: return "VFPv4-D16";
1482 default:
1483 snprintf(s_fp_arch, sizeof(s_fp_arch), "Unknown (%ju)",
1484 (uintmax_t) fp);
1485 return (s_fp_arch);
1486 }
1487 }
1488
1489 static const char *
aeabi_wmmx_arch(uint64_t wmmx)1490 aeabi_wmmx_arch(uint64_t wmmx)
1491 {
1492 static char s_wmmx[32];
1493
1494 switch (wmmx) {
1495 case 0: return "No";
1496 case 1: return "WMMXv1";
1497 case 2: return "WMMXv2";
1498 default:
1499 snprintf(s_wmmx, sizeof(s_wmmx), "Unknown (%ju)",
1500 (uintmax_t) wmmx);
1501 return (s_wmmx);
1502 }
1503 }
1504
1505 static const char *
aeabi_adv_simd_arch(uint64_t simd)1506 aeabi_adv_simd_arch(uint64_t simd)
1507 {
1508 static char s_simd[32];
1509
1510 switch (simd) {
1511 case 0: return "No";
1512 case 1: return "NEONv1";
1513 case 2: return "NEONv2";
1514 default:
1515 snprintf(s_simd, sizeof(s_simd), "Unknown (%ju)",
1516 (uintmax_t) simd);
1517 return (s_simd);
1518 }
1519 }
1520
1521 static const char *
aeabi_pcs_config(uint64_t pcs)1522 aeabi_pcs_config(uint64_t pcs)
1523 {
1524 static char s_pcs[32];
1525
1526 switch (pcs) {
1527 case 0: return "None";
1528 case 1: return "Bare platform";
1529 case 2: return "Linux";
1530 case 3: return "Linux DSO";
1531 case 4: return "Palm OS 2004";
1532 case 5: return "Palm OS (future)";
1533 case 6: return "Symbian OS 2004";
1534 case 7: return "Symbian OS (future)";
1535 default:
1536 snprintf(s_pcs, sizeof(s_pcs), "Unknown (%ju)",
1537 (uintmax_t) pcs);
1538 return (s_pcs);
1539 }
1540 }
1541
1542 static const char *
aeabi_pcs_r9(uint64_t r9)1543 aeabi_pcs_r9(uint64_t r9)
1544 {
1545 static char s_r9[32];
1546
1547 switch (r9) {
1548 case 0: return "V6";
1549 case 1: return "SB";
1550 case 2: return "TLS pointer";
1551 case 3: return "Unused";
1552 default:
1553 snprintf(s_r9, sizeof(s_r9), "Unknown (%ju)", (uintmax_t) r9);
1554 return (s_r9);
1555 }
1556 }
1557
1558 static const char *
aeabi_pcs_rw(uint64_t rw)1559 aeabi_pcs_rw(uint64_t rw)
1560 {
1561 static char s_rw[32];
1562
1563 switch (rw) {
1564 case 0: return "Absolute";
1565 case 1: return "PC-relative";
1566 case 2: return "SB-relative";
1567 case 3: return "None";
1568 default:
1569 snprintf(s_rw, sizeof(s_rw), "Unknown (%ju)", (uintmax_t) rw);
1570 return (s_rw);
1571 }
1572 }
1573
1574 static const char *
aeabi_pcs_ro(uint64_t ro)1575 aeabi_pcs_ro(uint64_t ro)
1576 {
1577 static char s_ro[32];
1578
1579 switch (ro) {
1580 case 0: return "Absolute";
1581 case 1: return "PC-relative";
1582 case 2: return "None";
1583 default:
1584 snprintf(s_ro, sizeof(s_ro), "Unknown (%ju)", (uintmax_t) ro);
1585 return (s_ro);
1586 }
1587 }
1588
1589 static const char *
aeabi_pcs_got(uint64_t got)1590 aeabi_pcs_got(uint64_t got)
1591 {
1592 static char s_got[32];
1593
1594 switch (got) {
1595 case 0: return "None";
1596 case 1: return "direct";
1597 case 2: return "indirect via GOT";
1598 default:
1599 snprintf(s_got, sizeof(s_got), "Unknown (%ju)",
1600 (uintmax_t) got);
1601 return (s_got);
1602 }
1603 }
1604
1605 static const char *
aeabi_pcs_wchar_t(uint64_t wt)1606 aeabi_pcs_wchar_t(uint64_t wt)
1607 {
1608 static char s_wt[32];
1609
1610 switch (wt) {
1611 case 0: return "None";
1612 case 2: return "wchar_t size 2";
1613 case 4: return "wchar_t size 4";
1614 default:
1615 snprintf(s_wt, sizeof(s_wt), "Unknown (%ju)", (uintmax_t) wt);
1616 return (s_wt);
1617 }
1618 }
1619
1620 static const char *
aeabi_enum_size(uint64_t es)1621 aeabi_enum_size(uint64_t es)
1622 {
1623 static char s_es[32];
1624
1625 switch (es) {
1626 case 0: return "None";
1627 case 1: return "smallest";
1628 case 2: return "32-bit";
1629 case 3: return "visible 32-bit";
1630 default:
1631 snprintf(s_es, sizeof(s_es), "Unknown (%ju)", (uintmax_t) es);
1632 return (s_es);
1633 }
1634 }
1635
1636 static const char *
aeabi_align_needed(uint64_t an)1637 aeabi_align_needed(uint64_t an)
1638 {
1639 static char s_align_n[64];
1640
1641 switch (an) {
1642 case 0: return "No";
1643 case 1: return "8-byte align";
1644 case 2: return "4-byte align";
1645 case 3: return "Reserved";
1646 default:
1647 if (an >= 4 && an <= 12)
1648 snprintf(s_align_n, sizeof(s_align_n), "8-byte align"
1649 " and up to 2^%ju-byte extended align",
1650 (uintmax_t) an);
1651 else
1652 snprintf(s_align_n, sizeof(s_align_n), "Unknown (%ju)",
1653 (uintmax_t) an);
1654 return (s_align_n);
1655 }
1656 }
1657
1658 static const char *
aeabi_align_preserved(uint64_t ap)1659 aeabi_align_preserved(uint64_t ap)
1660 {
1661 static char s_align_p[128];
1662
1663 switch (ap) {
1664 case 0: return "No";
1665 case 1: return "8-byte align";
1666 case 2: return "8-byte align and SP % 8 == 0";
1667 case 3: return "Reserved";
1668 default:
1669 if (ap >= 4 && ap <= 12)
1670 snprintf(s_align_p, sizeof(s_align_p), "8-byte align"
1671 " and SP %% 8 == 0 and up to 2^%ju-byte extended"
1672 " align", (uintmax_t) ap);
1673 else
1674 snprintf(s_align_p, sizeof(s_align_p), "Unknown (%ju)",
1675 (uintmax_t) ap);
1676 return (s_align_p);
1677 }
1678 }
1679
1680 static const char *
aeabi_fp_rounding(uint64_t fr)1681 aeabi_fp_rounding(uint64_t fr)
1682 {
1683 static char s_fp_r[32];
1684
1685 switch (fr) {
1686 case 0: return "Unused";
1687 case 1: return "Needed";
1688 default:
1689 snprintf(s_fp_r, sizeof(s_fp_r), "Unknown (%ju)",
1690 (uintmax_t) fr);
1691 return (s_fp_r);
1692 }
1693 }
1694
1695 static const char *
aeabi_fp_denormal(uint64_t fd)1696 aeabi_fp_denormal(uint64_t fd)
1697 {
1698 static char s_fp_d[32];
1699
1700 switch (fd) {
1701 case 0: return "Unused";
1702 case 1: return "Needed";
1703 case 2: return "Sign Only";
1704 default:
1705 snprintf(s_fp_d, sizeof(s_fp_d), "Unknown (%ju)",
1706 (uintmax_t) fd);
1707 return (s_fp_d);
1708 }
1709 }
1710
1711 static const char *
aeabi_fp_exceptions(uint64_t fe)1712 aeabi_fp_exceptions(uint64_t fe)
1713 {
1714 static char s_fp_e[32];
1715
1716 switch (fe) {
1717 case 0: return "Unused";
1718 case 1: return "Needed";
1719 default:
1720 snprintf(s_fp_e, sizeof(s_fp_e), "Unknown (%ju)",
1721 (uintmax_t) fe);
1722 return (s_fp_e);
1723 }
1724 }
1725
1726 static const char *
aeabi_fp_user_exceptions(uint64_t fu)1727 aeabi_fp_user_exceptions(uint64_t fu)
1728 {
1729 static char s_fp_u[32];
1730
1731 switch (fu) {
1732 case 0: return "Unused";
1733 case 1: return "Needed";
1734 default:
1735 snprintf(s_fp_u, sizeof(s_fp_u), "Unknown (%ju)",
1736 (uintmax_t) fu);
1737 return (s_fp_u);
1738 }
1739 }
1740
1741 static const char *
aeabi_fp_number_model(uint64_t fn)1742 aeabi_fp_number_model(uint64_t fn)
1743 {
1744 static char s_fp_n[32];
1745
1746 switch (fn) {
1747 case 0: return "Unused";
1748 case 1: return "IEEE 754 normal";
1749 case 2: return "RTABI";
1750 case 3: return "IEEE 754";
1751 default:
1752 snprintf(s_fp_n, sizeof(s_fp_n), "Unknown (%ju)",
1753 (uintmax_t) fn);
1754 return (s_fp_n);
1755 }
1756 }
1757
1758 static const char *
aeabi_fp_16bit_format(uint64_t fp16)1759 aeabi_fp_16bit_format(uint64_t fp16)
1760 {
1761 static char s_fp_16[64];
1762
1763 switch (fp16) {
1764 case 0: return "None";
1765 case 1: return "IEEE 754";
1766 case 2: return "VFPv3/Advanced SIMD (alternative format)";
1767 default:
1768 snprintf(s_fp_16, sizeof(s_fp_16), "Unknown (%ju)",
1769 (uintmax_t) fp16);
1770 return (s_fp_16);
1771 }
1772 }
1773
1774 static const char *
aeabi_mpext(uint64_t mp)1775 aeabi_mpext(uint64_t mp)
1776 {
1777 static char s_mp[32];
1778
1779 switch (mp) {
1780 case 0: return "Not allowed";
1781 case 1: return "Allowed";
1782 default:
1783 snprintf(s_mp, sizeof(s_mp), "Unknown (%ju)",
1784 (uintmax_t) mp);
1785 return (s_mp);
1786 }
1787 }
1788
1789 static const char *
aeabi_div(uint64_t du)1790 aeabi_div(uint64_t du)
1791 {
1792 static char s_du[32];
1793
1794 switch (du) {
1795 case 0: return "Yes (V7-R/V7-M)";
1796 case 1: return "No";
1797 case 2: return "Yes (V7-A)";
1798 default:
1799 snprintf(s_du, sizeof(s_du), "Unknown (%ju)",
1800 (uintmax_t) du);
1801 return (s_du);
1802 }
1803 }
1804
1805 static const char *
aeabi_t2ee(uint64_t t2ee)1806 aeabi_t2ee(uint64_t t2ee)
1807 {
1808 static char s_t2ee[32];
1809
1810 switch (t2ee) {
1811 case 0: return "Not allowed";
1812 case 1: return "Allowed";
1813 default:
1814 snprintf(s_t2ee, sizeof(s_t2ee), "Unknown(%ju)",
1815 (uintmax_t) t2ee);
1816 return (s_t2ee);
1817 }
1818
1819 }
1820
1821 static const char *
aeabi_hardfp(uint64_t hfp)1822 aeabi_hardfp(uint64_t hfp)
1823 {
1824 static char s_hfp[32];
1825
1826 switch (hfp) {
1827 case 0: return "Tag_FP_arch";
1828 case 1: return "only SP";
1829 case 2: return "only DP";
1830 case 3: return "both SP and DP";
1831 default:
1832 snprintf(s_hfp, sizeof(s_hfp), "Unknown (%ju)",
1833 (uintmax_t) hfp);
1834 return (s_hfp);
1835 }
1836 }
1837
1838 static const char *
aeabi_vfp_args(uint64_t va)1839 aeabi_vfp_args(uint64_t va)
1840 {
1841 static char s_va[32];
1842
1843 switch (va) {
1844 case 0: return "AAPCS (base variant)";
1845 case 1: return "AAPCS (VFP variant)";
1846 case 2: return "toolchain-specific";
1847 default:
1848 snprintf(s_va, sizeof(s_va), "Unknown (%ju)", (uintmax_t) va);
1849 return (s_va);
1850 }
1851 }
1852
1853 static const char *
aeabi_wmmx_args(uint64_t wa)1854 aeabi_wmmx_args(uint64_t wa)
1855 {
1856 static char s_wa[32];
1857
1858 switch (wa) {
1859 case 0: return "AAPCS (base variant)";
1860 case 1: return "Intel WMMX";
1861 case 2: return "toolchain-specific";
1862 default:
1863 snprintf(s_wa, sizeof(s_wa), "Unknown(%ju)", (uintmax_t) wa);
1864 return (s_wa);
1865 }
1866 }
1867
1868 static const char *
aeabi_unaligned_access(uint64_t ua)1869 aeabi_unaligned_access(uint64_t ua)
1870 {
1871 static char s_ua[32];
1872
1873 switch (ua) {
1874 case 0: return "Not allowed";
1875 case 1: return "Allowed";
1876 default:
1877 snprintf(s_ua, sizeof(s_ua), "Unknown(%ju)", (uintmax_t) ua);
1878 return (s_ua);
1879 }
1880 }
1881
1882 static const char *
aeabi_fp_hpext(uint64_t fh)1883 aeabi_fp_hpext(uint64_t fh)
1884 {
1885 static char s_fh[32];
1886
1887 switch (fh) {
1888 case 0: return "Not allowed";
1889 case 1: return "Allowed";
1890 default:
1891 snprintf(s_fh, sizeof(s_fh), "Unknown(%ju)", (uintmax_t) fh);
1892 return (s_fh);
1893 }
1894 }
1895
1896 static const char *
aeabi_optm_goal(uint64_t og)1897 aeabi_optm_goal(uint64_t og)
1898 {
1899 static char s_og[32];
1900
1901 switch (og) {
1902 case 0: return "None";
1903 case 1: return "Speed";
1904 case 2: return "Speed aggressive";
1905 case 3: return "Space";
1906 case 4: return "Space aggressive";
1907 case 5: return "Debugging";
1908 case 6: return "Best Debugging";
1909 default:
1910 snprintf(s_og, sizeof(s_og), "Unknown(%ju)", (uintmax_t) og);
1911 return (s_og);
1912 }
1913 }
1914
1915 static const char *
aeabi_fp_optm_goal(uint64_t fog)1916 aeabi_fp_optm_goal(uint64_t fog)
1917 {
1918 static char s_fog[32];
1919
1920 switch (fog) {
1921 case 0: return "None";
1922 case 1: return "Speed";
1923 case 2: return "Speed aggressive";
1924 case 3: return "Space";
1925 case 4: return "Space aggressive";
1926 case 5: return "Accurary";
1927 case 6: return "Best Accurary";
1928 default:
1929 snprintf(s_fog, sizeof(s_fog), "Unknown(%ju)",
1930 (uintmax_t) fog);
1931 return (s_fog);
1932 }
1933 }
1934
1935 static const char *
aeabi_virtual(uint64_t vt)1936 aeabi_virtual(uint64_t vt)
1937 {
1938 static char s_virtual[64];
1939
1940 switch (vt) {
1941 case 0: return "No";
1942 case 1: return "TrustZone";
1943 case 2: return "Virtualization extension";
1944 case 3: return "TrustZone and virtualization extension";
1945 default:
1946 snprintf(s_virtual, sizeof(s_virtual), "Unknown(%ju)",
1947 (uintmax_t) vt);
1948 return (s_virtual);
1949 }
1950 }
1951
1952 static struct {
1953 uint64_t tag;
1954 const char *s_tag;
1955 const char *(*get_desc)(uint64_t val);
1956 } aeabi_tags[] = {
1957 {4, "Tag_CPU_raw_name", NULL},
1958 {5, "Tag_CPU_name", NULL},
1959 {6, "Tag_CPU_arch", aeabi_cpu_arch},
1960 {7, "Tag_CPU_arch_profile", aeabi_cpu_arch_profile},
1961 {8, "Tag_ARM_ISA_use", aeabi_arm_isa},
1962 {9, "Tag_THUMB_ISA_use", aeabi_thumb_isa},
1963 {10, "Tag_FP_arch", aeabi_fp_arch},
1964 {11, "Tag_WMMX_arch", aeabi_wmmx_arch},
1965 {12, "Tag_Advanced_SIMD_arch", aeabi_adv_simd_arch},
1966 {13, "Tag_PCS_config", aeabi_pcs_config},
1967 {14, "Tag_ABI_PCS_R9_use", aeabi_pcs_r9},
1968 {15, "Tag_ABI_PCS_RW_data", aeabi_pcs_rw},
1969 {16, "Tag_ABI_PCS_RO_data", aeabi_pcs_ro},
1970 {17, "Tag_ABI_PCS_GOT_use", aeabi_pcs_got},
1971 {18, "Tag_ABI_PCS_wchar_t", aeabi_pcs_wchar_t},
1972 {19, "Tag_ABI_FP_rounding", aeabi_fp_rounding},
1973 {20, "Tag_ABI_FP_denormal", aeabi_fp_denormal},
1974 {21, "Tag_ABI_FP_exceptions", aeabi_fp_exceptions},
1975 {22, "Tag_ABI_FP_user_exceptions", aeabi_fp_user_exceptions},
1976 {23, "Tag_ABI_FP_number_model", aeabi_fp_number_model},
1977 {24, "Tag_ABI_align_needed", aeabi_align_needed},
1978 {25, "Tag_ABI_align_preserved", aeabi_align_preserved},
1979 {26, "Tag_ABI_enum_size", aeabi_enum_size},
1980 {27, "Tag_ABI_HardFP_use", aeabi_hardfp},
1981 {28, "Tag_ABI_VFP_args", aeabi_vfp_args},
1982 {29, "Tag_ABI_WMMX_args", aeabi_wmmx_args},
1983 {30, "Tag_ABI_optimization_goals", aeabi_optm_goal},
1984 {31, "Tag_ABI_FP_optimization_goals", aeabi_fp_optm_goal},
1985 {32, "Tag_compatibility", NULL},
1986 {34, "Tag_CPU_unaligned_access", aeabi_unaligned_access},
1987 {36, "Tag_FP_HP_extension", aeabi_fp_hpext},
1988 {38, "Tag_ABI_FP_16bit_format", aeabi_fp_16bit_format},
1989 {42, "Tag_MPextension_use", aeabi_mpext},
1990 {44, "Tag_DIV_use", aeabi_div},
1991 {64, "Tag_nodefaults", NULL},
1992 {65, "Tag_also_compatible_with", NULL},
1993 {66, "Tag_T2EE_use", aeabi_t2ee},
1994 {67, "Tag_conformance", NULL},
1995 {68, "Tag_Virtualization_use", aeabi_virtual},
1996 {70, "Tag_MPextension_use", aeabi_mpext},
1997 };
1998
1999 static const char *
mips_abi_fp(uint64_t fp)2000 mips_abi_fp(uint64_t fp)
2001 {
2002 static char s_mips_abi_fp[64];
2003
2004 switch (fp) {
2005 case 0: return "N/A";
2006 case 1: return "Hard float (double precision)";
2007 case 2: return "Hard float (single precision)";
2008 case 3: return "Soft float";
2009 case 4: return "64-bit float (-mips32r2 -mfp64)";
2010 default:
2011 snprintf(s_mips_abi_fp, sizeof(s_mips_abi_fp), "Unknown(%ju)",
2012 (uintmax_t) fp);
2013 return (s_mips_abi_fp);
2014 }
2015 }
2016
2017 static const char *
ppc_abi_fp(uint64_t fp)2018 ppc_abi_fp(uint64_t fp)
2019 {
2020 static char s_ppc_abi_fp[64];
2021
2022 switch (fp) {
2023 case 0: return "N/A";
2024 case 1: return "Hard float (double precision)";
2025 case 2: return "Soft float";
2026 case 3: return "Hard float (single precision)";
2027 default:
2028 snprintf(s_ppc_abi_fp, sizeof(s_ppc_abi_fp), "Unknown(%ju)",
2029 (uintmax_t) fp);
2030 return (s_ppc_abi_fp);
2031 }
2032 }
2033
2034 static const char *
ppc_abi_vector(uint64_t vec)2035 ppc_abi_vector(uint64_t vec)
2036 {
2037 static char s_vec[64];
2038
2039 switch (vec) {
2040 case 0: return "N/A";
2041 case 1: return "Generic purpose registers";
2042 case 2: return "AltiVec registers";
2043 case 3: return "SPE registers";
2044 default:
2045 snprintf(s_vec, sizeof(s_vec), "Unknown(%ju)", (uintmax_t) vec);
2046 return (s_vec);
2047 }
2048 }
2049
2050 static const char *
dwarf_reg(unsigned int mach,unsigned int reg)2051 dwarf_reg(unsigned int mach, unsigned int reg)
2052 {
2053
2054 switch (mach) {
2055 case EM_386:
2056 case EM_IAMCU:
2057 switch (reg) {
2058 case 0: return "eax";
2059 case 1: return "ecx";
2060 case 2: return "edx";
2061 case 3: return "ebx";
2062 case 4: return "esp";
2063 case 5: return "ebp";
2064 case 6: return "esi";
2065 case 7: return "edi";
2066 case 8: return "eip";
2067 case 9: return "eflags";
2068 case 11: return "st0";
2069 case 12: return "st1";
2070 case 13: return "st2";
2071 case 14: return "st3";
2072 case 15: return "st4";
2073 case 16: return "st5";
2074 case 17: return "st6";
2075 case 18: return "st7";
2076 case 21: return "xmm0";
2077 case 22: return "xmm1";
2078 case 23: return "xmm2";
2079 case 24: return "xmm3";
2080 case 25: return "xmm4";
2081 case 26: return "xmm5";
2082 case 27: return "xmm6";
2083 case 28: return "xmm7";
2084 case 29: return "mm0";
2085 case 30: return "mm1";
2086 case 31: return "mm2";
2087 case 32: return "mm3";
2088 case 33: return "mm4";
2089 case 34: return "mm5";
2090 case 35: return "mm6";
2091 case 36: return "mm7";
2092 case 37: return "fcw";
2093 case 38: return "fsw";
2094 case 39: return "mxcsr";
2095 case 40: return "es";
2096 case 41: return "cs";
2097 case 42: return "ss";
2098 case 43: return "ds";
2099 case 44: return "fs";
2100 case 45: return "gs";
2101 case 48: return "tr";
2102 case 49: return "ldtr";
2103 default: return (NULL);
2104 }
2105 case EM_RISCV:
2106 switch (reg) {
2107 case 0: return "zero";
2108 case 1: return "ra";
2109 case 2: return "sp";
2110 case 3: return "gp";
2111 case 4: return "tp";
2112 case 5: return "t0";
2113 case 6: return "t1";
2114 case 7: return "t2";
2115 case 8: return "s0";
2116 case 9: return "s1";
2117 case 10: return "a0";
2118 case 11: return "a1";
2119 case 12: return "a2";
2120 case 13: return "a3";
2121 case 14: return "a4";
2122 case 15: return "a5";
2123 case 16: return "a6";
2124 case 17: return "a7";
2125 case 18: return "s2";
2126 case 19: return "s3";
2127 case 20: return "s4";
2128 case 21: return "s5";
2129 case 22: return "s6";
2130 case 23: return "s7";
2131 case 24: return "s8";
2132 case 25: return "s9";
2133 case 26: return "s10";
2134 case 27: return "s11";
2135 case 28: return "t3";
2136 case 29: return "t4";
2137 case 30: return "t5";
2138 case 31: return "t6";
2139 case 32: return "ft0";
2140 case 33: return "ft1";
2141 case 34: return "ft2";
2142 case 35: return "ft3";
2143 case 36: return "ft4";
2144 case 37: return "ft5";
2145 case 38: return "ft6";
2146 case 39: return "ft7";
2147 case 40: return "fs0";
2148 case 41: return "fs1";
2149 case 42: return "fa0";
2150 case 43: return "fa1";
2151 case 44: return "fa2";
2152 case 45: return "fa3";
2153 case 46: return "fa4";
2154 case 47: return "fa5";
2155 case 48: return "fa6";
2156 case 49: return "fa7";
2157 case 50: return "fs2";
2158 case 51: return "fs3";
2159 case 52: return "fs4";
2160 case 53: return "fs5";
2161 case 54: return "fs6";
2162 case 55: return "fs7";
2163 case 56: return "fs8";
2164 case 57: return "fs9";
2165 case 58: return "fs10";
2166 case 59: return "fs11";
2167 case 60: return "ft8";
2168 case 61: return "ft9";
2169 case 62: return "ft10";
2170 case 63: return "ft11";
2171 default: return (NULL);
2172 }
2173 case EM_X86_64:
2174 switch (reg) {
2175 case 0: return "rax";
2176 case 1: return "rdx";
2177 case 2: return "rcx";
2178 case 3: return "rbx";
2179 case 4: return "rsi";
2180 case 5: return "rdi";
2181 case 6: return "rbp";
2182 case 7: return "rsp";
2183 case 16: return "rip";
2184 case 17: return "xmm0";
2185 case 18: return "xmm1";
2186 case 19: return "xmm2";
2187 case 20: return "xmm3";
2188 case 21: return "xmm4";
2189 case 22: return "xmm5";
2190 case 23: return "xmm6";
2191 case 24: return "xmm7";
2192 case 25: return "xmm8";
2193 case 26: return "xmm9";
2194 case 27: return "xmm10";
2195 case 28: return "xmm11";
2196 case 29: return "xmm12";
2197 case 30: return "xmm13";
2198 case 31: return "xmm14";
2199 case 32: return "xmm15";
2200 case 33: return "st0";
2201 case 34: return "st1";
2202 case 35: return "st2";
2203 case 36: return "st3";
2204 case 37: return "st4";
2205 case 38: return "st5";
2206 case 39: return "st6";
2207 case 40: return "st7";
2208 case 41: return "mm0";
2209 case 42: return "mm1";
2210 case 43: return "mm2";
2211 case 44: return "mm3";
2212 case 45: return "mm4";
2213 case 46: return "mm5";
2214 case 47: return "mm6";
2215 case 48: return "mm7";
2216 case 49: return "rflags";
2217 case 50: return "es";
2218 case 51: return "cs";
2219 case 52: return "ss";
2220 case 53: return "ds";
2221 case 54: return "fs";
2222 case 55: return "gs";
2223 case 58: return "fs.base";
2224 case 59: return "gs.base";
2225 case 62: return "tr";
2226 case 63: return "ldtr";
2227 case 64: return "mxcsr";
2228 case 65: return "fcw";
2229 case 66: return "fsw";
2230 default: return (NULL);
2231 }
2232 default:
2233 return (NULL);
2234 }
2235 }
2236
2237 static void
dump_ehdr(struct readelf * re)2238 dump_ehdr(struct readelf *re)
2239 {
2240 size_t phnum, shnum, shstrndx;
2241 int i;
2242
2243 printf("ELF Header:\n");
2244
2245 /* e_ident[]. */
2246 printf(" Magic: ");
2247 for (i = 0; i < EI_NIDENT; i++)
2248 printf("%.2x ", re->ehdr.e_ident[i]);
2249 putchar('\n');
2250
2251 /* EI_CLASS. */
2252 printf("%-37s%s\n", " Class:", elf_class(re->ehdr.e_ident[EI_CLASS]));
2253
2254 /* EI_DATA. */
2255 printf("%-37s%s\n", " Data:", elf_endian(re->ehdr.e_ident[EI_DATA]));
2256
2257 /* EI_VERSION. */
2258 printf("%-37s%d %s\n", " Version:", re->ehdr.e_ident[EI_VERSION],
2259 elf_ver(re->ehdr.e_ident[EI_VERSION]));
2260
2261 /* EI_OSABI. */
2262 printf("%-37s%s\n", " OS/ABI:", elf_osabi(re->ehdr.e_ident[EI_OSABI]));
2263
2264 /* EI_ABIVERSION. */
2265 printf("%-37s%d\n", " ABI Version:", re->ehdr.e_ident[EI_ABIVERSION]);
2266
2267 /* e_type. */
2268 printf("%-37s%s\n", " Type:", elf_type(re->ehdr.e_type));
2269
2270 /* e_machine. */
2271 printf("%-37s%s\n", " Machine:", elf_machine(re->ehdr.e_machine));
2272
2273 /* e_version. */
2274 printf("%-37s%#x\n", " Version:", re->ehdr.e_version);
2275
2276 /* e_entry. */
2277 printf("%-37s%#jx\n", " Entry point address:",
2278 (uintmax_t)re->ehdr.e_entry);
2279
2280 /* e_phoff. */
2281 printf("%-37s%ju (bytes into file)\n", " Start of program headers:",
2282 (uintmax_t)re->ehdr.e_phoff);
2283
2284 /* e_shoff. */
2285 printf("%-37s%ju (bytes into file)\n", " Start of section headers:",
2286 (uintmax_t)re->ehdr.e_shoff);
2287
2288 /* e_flags. */
2289 printf("%-37s%#x", " Flags:", re->ehdr.e_flags);
2290 dump_eflags(re, re->ehdr.e_flags);
2291 putchar('\n');
2292
2293 /* e_ehsize. */
2294 printf("%-37s%u (bytes)\n", " Size of this header:",
2295 re->ehdr.e_ehsize);
2296
2297 /* e_phentsize. */
2298 printf("%-37s%u (bytes)\n", " Size of program headers:",
2299 re->ehdr.e_phentsize);
2300
2301 /* e_phnum. */
2302 printf("%-37s%u", " Number of program headers:", re->ehdr.e_phnum);
2303 if (re->ehdr.e_phnum == PN_XNUM) {
2304 /* Extended program header numbering is in use. */
2305 if (elf_getphnum(re->elf, &phnum))
2306 printf(" (%zu)", phnum);
2307 }
2308 putchar('\n');
2309
2310 /* e_shentsize. */
2311 printf("%-37s%u (bytes)\n", " Size of section headers:",
2312 re->ehdr.e_shentsize);
2313
2314 /* e_shnum. */
2315 printf("%-37s%u", " Number of section headers:", re->ehdr.e_shnum);
2316 if (re->ehdr.e_shnum == SHN_UNDEF) {
2317 /* Extended section numbering is in use. */
2318 if (elf_getshnum(re->elf, &shnum))
2319 printf(" (%ju)", (uintmax_t)shnum);
2320 }
2321 putchar('\n');
2322
2323 /* e_shstrndx. */
2324 printf("%-37s%u", " Section header string table index:",
2325 re->ehdr.e_shstrndx);
2326 if (re->ehdr.e_shstrndx == SHN_XINDEX) {
2327 /* Extended section numbering is in use. */
2328 if (elf_getshstrndx(re->elf, &shstrndx))
2329 printf(" (%ju)", (uintmax_t)shstrndx);
2330 }
2331 putchar('\n');
2332 }
2333
2334 static void
dump_eflags(struct readelf * re,uint64_t e_flags)2335 dump_eflags(struct readelf *re, uint64_t e_flags)
2336 {
2337 struct eflags_desc *edesc;
2338 int arm_eabi;
2339
2340 edesc = NULL;
2341 switch (re->ehdr.e_machine) {
2342 case EM_ARM:
2343 arm_eabi = (e_flags & EF_ARM_EABIMASK) >> 24;
2344 if (arm_eabi == 0)
2345 printf(", GNU EABI");
2346 else if (arm_eabi <= 5)
2347 printf(", Version%d EABI", arm_eabi);
2348 edesc = arm_eflags_desc;
2349 break;
2350 case EM_MIPS:
2351 case EM_MIPS_RS3_LE:
2352 switch ((e_flags & EF_MIPS_ARCH) >> 28) {
2353 case 0: printf(", mips1"); break;
2354 case 1: printf(", mips2"); break;
2355 case 2: printf(", mips3"); break;
2356 case 3: printf(", mips4"); break;
2357 case 4: printf(", mips5"); break;
2358 case 5: printf(", mips32"); break;
2359 case 6: printf(", mips64"); break;
2360 case 7: printf(", mips32r2"); break;
2361 case 8: printf(", mips64r2"); break;
2362 default: break;
2363 }
2364 switch ((e_flags & 0x00FF0000) >> 16) {
2365 case 0x81: printf(", 3900"); break;
2366 case 0x82: printf(", 4010"); break;
2367 case 0x83: printf(", 4100"); break;
2368 case 0x85: printf(", 4650"); break;
2369 case 0x87: printf(", 4120"); break;
2370 case 0x88: printf(", 4111"); break;
2371 case 0x8a: printf(", sb1"); break;
2372 case 0x8b: printf(", octeon"); break;
2373 case 0x8c: printf(", xlr"); break;
2374 case 0x91: printf(", 5400"); break;
2375 case 0x98: printf(", 5500"); break;
2376 case 0x99: printf(", 9000"); break;
2377 case 0xa0: printf(", loongson-2e"); break;
2378 case 0xa1: printf(", loongson-2f"); break;
2379 default: break;
2380 }
2381 switch ((e_flags & 0x0000F000) >> 12) {
2382 case 1: printf(", o32"); break;
2383 case 2: printf(", o64"); break;
2384 case 3: printf(", eabi32"); break;
2385 case 4: printf(", eabi64"); break;
2386 default: break;
2387 }
2388 edesc = mips_eflags_desc;
2389 break;
2390 case EM_PPC64:
2391 switch (e_flags) {
2392 case 0: printf(", Unspecified or Power ELF V1 ABI"); break;
2393 case 1: printf(", Power ELF V1 ABI"); break;
2394 case 2: printf(", OpenPOWER ELF V2 ABI"); break;
2395 default: break;
2396 }
2397 /* FALLTHROUGH */
2398 case EM_PPC:
2399 edesc = powerpc_eflags_desc;
2400 break;
2401 case EM_RISCV:
2402 switch (e_flags & EF_RISCV_FLOAT_ABI_MASK) {
2403 case EF_RISCV_FLOAT_ABI_SOFT:
2404 printf(", soft-float ABI");
2405 break;
2406 case EF_RISCV_FLOAT_ABI_SINGLE:
2407 printf(", single-float ABI");
2408 break;
2409 case EF_RISCV_FLOAT_ABI_DOUBLE:
2410 printf(", double-float ABI");
2411 break;
2412 case EF_RISCV_FLOAT_ABI_QUAD:
2413 printf(", quad-float ABI");
2414 break;
2415 }
2416 edesc = riscv_eflags_desc;
2417 break;
2418 case EM_SPARC:
2419 case EM_SPARC32PLUS:
2420 case EM_SPARCV9:
2421 switch ((e_flags & EF_SPARCV9_MM)) {
2422 case EF_SPARCV9_TSO: printf(", tso"); break;
2423 case EF_SPARCV9_PSO: printf(", pso"); break;
2424 case EF_SPARCV9_MM: printf(", rmo"); break;
2425 default: break;
2426 }
2427 edesc = sparc_eflags_desc;
2428 break;
2429 default:
2430 break;
2431 }
2432
2433 if (edesc != NULL) {
2434 while (edesc->desc != NULL) {
2435 if (e_flags & edesc->flag)
2436 printf(", %s", edesc->desc);
2437 edesc++;
2438 }
2439 }
2440 }
2441
2442 static void
dump_phdr(struct readelf * re)2443 dump_phdr(struct readelf *re)
2444 {
2445 const char *rawfile;
2446 GElf_Phdr phdr;
2447 size_t phnum, size;
2448 int i, j;
2449
2450 #define PH_HDR "Type", "Offset", "VirtAddr", "PhysAddr", "FileSiz", \
2451 "MemSiz", "Flg", "Align"
2452 #define PH_CT phdr_type(re->ehdr.e_machine, phdr.p_type), \
2453 (uintmax_t)phdr.p_offset, (uintmax_t)phdr.p_vaddr, \
2454 (uintmax_t)phdr.p_paddr, (uintmax_t)phdr.p_filesz, \
2455 (uintmax_t)phdr.p_memsz, \
2456 phdr.p_flags & PF_R ? 'R' : ' ', \
2457 phdr.p_flags & PF_W ? 'W' : ' ', \
2458 phdr.p_flags & PF_X ? 'E' : ' ', \
2459 (uintmax_t)phdr.p_align
2460
2461 if (elf_getphnum(re->elf, &phnum) == 0) {
2462 warnx("elf_getphnum failed: %s", elf_errmsg(-1));
2463 return;
2464 }
2465 if (phnum == 0) {
2466 printf("\nThere are no program headers in this file.\n");
2467 return;
2468 }
2469
2470 printf("\nElf file type is %s", elf_type(re->ehdr.e_type));
2471 printf("\nEntry point 0x%jx\n", (uintmax_t)re->ehdr.e_entry);
2472 printf("There are %ju program headers, starting at offset %ju\n",
2473 (uintmax_t)phnum, (uintmax_t)re->ehdr.e_phoff);
2474
2475 /* Dump program headers. */
2476 printf("\nProgram Headers:\n");
2477 if (re->ec == ELFCLASS32)
2478 printf(" %-15s%-9s%-11s%-11s%-8s%-8s%-4s%s\n", PH_HDR);
2479 else if (re->options & RE_WW)
2480 printf(" %-15s%-9s%-19s%-19s%-9s%-9s%-4s%s\n", PH_HDR);
2481 else
2482 printf(" %-15s%-19s%-19s%s\n %-19s%-20s"
2483 "%-7s%s\n", PH_HDR);
2484 for (i = 0; (size_t) i < phnum; i++) {
2485 if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
2486 warnx("gelf_getphdr failed: %s", elf_errmsg(-1));
2487 continue;
2488 }
2489 /* TODO: Add arch-specific segment type dump. */
2490 if (re->ec == ELFCLASS32)
2491 printf(" %-14.14s 0x%6.6jx 0x%8.8jx 0x%8.8jx "
2492 "0x%5.5jx 0x%5.5jx %c%c%c %#jx\n", PH_CT);
2493 else if (re->options & RE_WW)
2494 printf(" %-14.14s 0x%6.6jx 0x%16.16jx 0x%16.16jx "
2495 "0x%6.6jx 0x%6.6jx %c%c%c %#jx\n", PH_CT);
2496 else
2497 printf(" %-14.14s 0x%16.16jx 0x%16.16jx 0x%16.16jx\n"
2498 " 0x%16.16jx 0x%16.16jx %c%c%c"
2499 " %#jx\n", PH_CT);
2500 if (phdr.p_type == PT_INTERP) {
2501 if ((rawfile = elf_rawfile(re->elf, &size)) == NULL) {
2502 warnx("elf_rawfile failed: %s", elf_errmsg(-1));
2503 continue;
2504 }
2505 if (phdr.p_offset >= size) {
2506 warnx("invalid program header offset");
2507 continue;
2508 }
2509 printf(" [Requesting program interpreter: %s]\n",
2510 rawfile + phdr.p_offset);
2511 }
2512 }
2513
2514 /* Dump section to segment mapping. */
2515 if (re->shnum == 0)
2516 return;
2517 printf("\n Section to Segment mapping:\n");
2518 printf(" Segment Sections...\n");
2519 for (i = 0; (size_t)i < phnum; i++) {
2520 if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
2521 warnx("gelf_getphdr failed: %s", elf_errmsg(-1));
2522 continue;
2523 }
2524 printf(" %2.2d ", i);
2525 /* skip NULL section. */
2526 for (j = 1; (size_t)j < re->shnum; j++) {
2527 if (re->sl[j].off < phdr.p_offset)
2528 continue;
2529 if (re->sl[j].off + re->sl[j].sz >
2530 phdr.p_offset + phdr.p_filesz &&
2531 re->sl[j].type != SHT_NOBITS)
2532 continue;
2533 if (re->sl[j].addr < phdr.p_vaddr ||
2534 re->sl[j].addr + re->sl[j].sz >
2535 phdr.p_vaddr + phdr.p_memsz)
2536 continue;
2537 if (phdr.p_type == PT_TLS &&
2538 (re->sl[j].flags & SHF_TLS) == 0)
2539 continue;
2540 printf("%s ", re->sl[j].name);
2541 }
2542 printf("\n");
2543 }
2544 #undef PH_HDR
2545 #undef PH_CT
2546 }
2547
2548 static char *
section_flags(struct readelf * re,struct section * s)2549 section_flags(struct readelf *re, struct section *s)
2550 {
2551 #define BUF_SZ 256
2552 static char buf[BUF_SZ];
2553 int i, p, nb;
2554
2555 p = 0;
2556 nb = re->ec == ELFCLASS32 ? 8 : 16;
2557 if (re->options & RE_T) {
2558 snprintf(buf, BUF_SZ, "[%*.*jx]: ", nb, nb,
2559 (uintmax_t)s->flags);
2560 p += nb + 4;
2561 }
2562 for (i = 0; section_flag[i].ln != NULL; i++) {
2563 if ((s->flags & section_flag[i].value) == 0)
2564 continue;
2565 if (re->options & RE_T) {
2566 snprintf(&buf[p], BUF_SZ - p, "%s, ",
2567 section_flag[i].ln);
2568 p += strlen(section_flag[i].ln) + 2;
2569 } else
2570 buf[p++] = section_flag[i].sn;
2571 }
2572 if (re->options & RE_T && p > nb + 4)
2573 p -= 2;
2574 buf[p] = '\0';
2575
2576 return (buf);
2577 }
2578
2579 static void
dump_shdr(struct readelf * re)2580 dump_shdr(struct readelf *re)
2581 {
2582 struct section *s;
2583 int i;
2584
2585 #define S_HDR "[Nr] Name", "Type", "Addr", "Off", "Size", "ES", \
2586 "Flg", "Lk", "Inf", "Al"
2587 #define S_HDRL "[Nr] Name", "Type", "Address", "Offset", "Size", \
2588 "EntSize", "Flags", "Link", "Info", "Align"
2589 #define ST_HDR "[Nr] Name", "Type", "Addr", "Off", "Size", "ES", \
2590 "Lk", "Inf", "Al", "Flags"
2591 #define ST_HDRL "[Nr] Name", "Type", "Address", "Offset", "Link", \
2592 "Size", "EntSize", "Info", "Align", "Flags"
2593 #define S_CT i, s->name, section_type(re->ehdr.e_machine, s->type), \
2594 (uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\
2595 (uintmax_t)s->entsize, section_flags(re, s), \
2596 s->link, s->info, (uintmax_t)s->align
2597 #define ST_CT i, s->name, section_type(re->ehdr.e_machine, s->type), \
2598 (uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\
2599 (uintmax_t)s->entsize, s->link, s->info, \
2600 (uintmax_t)s->align, section_flags(re, s)
2601 #define ST_CTL i, s->name, section_type(re->ehdr.e_machine, s->type), \
2602 (uintmax_t)s->addr, (uintmax_t)s->off, s->link, \
2603 (uintmax_t)s->sz, (uintmax_t)s->entsize, s->info, \
2604 (uintmax_t)s->align, section_flags(re, s)
2605
2606 if (re->shnum == 0) {
2607 printf("\nThere are no sections in this file.\n");
2608 return;
2609 }
2610 printf("There are %ju section headers, starting at offset 0x%jx:\n",
2611 (uintmax_t)re->shnum, (uintmax_t)re->ehdr.e_shoff);
2612 printf("\nSection Headers:\n");
2613 if (re->ec == ELFCLASS32) {
2614 if (re->options & RE_T)
2615 printf(" %s\n %-16s%-9s%-7s%-7s%-5s%-3s%-4s%s\n"
2616 "%12s\n", ST_HDR);
2617 else
2618 printf(" %-23s%-16s%-9s%-7s%-7s%-3s%-4s%-3s%-4s%s\n",
2619 S_HDR);
2620 } else if (re->options & RE_WW) {
2621 if (re->options & RE_T)
2622 printf(" %s\n %-16s%-17s%-7s%-7s%-5s%-3s%-4s%s\n"
2623 "%12s\n", ST_HDR);
2624 else
2625 printf(" %-23s%-16s%-17s%-7s%-7s%-3s%-4s%-3s%-4s%s\n",
2626 S_HDR);
2627 } else {
2628 if (re->options & RE_T)
2629 printf(" %s\n %-18s%-17s%-18s%s\n %-18s"
2630 "%-17s%-18s%s\n%12s\n", ST_HDRL);
2631 else
2632 printf(" %-23s%-17s%-18s%s\n %-18s%-17s%-7s%"
2633 "-6s%-6s%s\n", S_HDRL);
2634 }
2635 for (i = 0; (size_t)i < re->shnum; i++) {
2636 s = &re->sl[i];
2637 if (re->ec == ELFCLASS32) {
2638 if (re->options & RE_T)
2639 printf(" [%2d] %s\n %-15.15s %8.8jx"
2640 " %6.6jx %6.6jx %2.2jx %2u %3u %2ju\n"
2641 " %s\n", ST_CT);
2642 else
2643 printf(" [%2d] %-17.17s %-15.15s %8.8jx"
2644 " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n",
2645 S_CT);
2646 } else if (re->options & RE_WW) {
2647 if (re->options & RE_T)
2648 printf(" [%2d] %s\n %-15.15s %16.16jx"
2649 " %6.6jx %6.6jx %2.2jx %2u %3u %2ju\n"
2650 " %s\n", ST_CT);
2651 else
2652 printf(" [%2d] %-17.17s %-15.15s %16.16jx"
2653 " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n",
2654 S_CT);
2655 } else {
2656 if (re->options & RE_T)
2657 printf(" [%2d] %s\n %-15.15s %16.16jx"
2658 " %16.16jx %u\n %16.16jx %16.16jx"
2659 " %-16u %ju\n %s\n", ST_CTL);
2660 else
2661 printf(" [%2d] %-17.17s %-15.15s %16.16jx"
2662 " %8.8jx\n %16.16jx %16.16jx "
2663 "%3s %2u %3u %ju\n", S_CT);
2664 }
2665 }
2666 if ((re->options & RE_T) == 0)
2667 printf("Key to Flags:\n W (write), A (alloc),"
2668 " X (execute), M (merge), S (strings)\n"
2669 " I (info), L (link order), G (group), x (unknown)\n"
2670 " O (extra OS processing required)"
2671 " o (OS specific), p (processor specific)\n");
2672
2673 #undef S_HDR
2674 #undef S_HDRL
2675 #undef ST_HDR
2676 #undef ST_HDRL
2677 #undef S_CT
2678 #undef ST_CT
2679 #undef ST_CTL
2680 }
2681
2682 /*
2683 * Return number of entries in the given section. We'd prefer ent_count be a
2684 * size_t *, but libelf APIs already use int for section indices.
2685 */
2686 static int
get_ent_count(struct section * s,int * ent_count)2687 get_ent_count(struct section *s, int *ent_count)
2688 {
2689 if (s->entsize == 0) {
2690 warnx("section %s has entry size 0", s->name);
2691 return (0);
2692 } else if (s->sz / s->entsize > INT_MAX) {
2693 warnx("section %s has invalid section count", s->name);
2694 return (0);
2695 }
2696 *ent_count = (int)(s->sz / s->entsize);
2697 return (1);
2698 }
2699
2700 static void
dump_dynamic(struct readelf * re)2701 dump_dynamic(struct readelf *re)
2702 {
2703 GElf_Dyn dyn;
2704 Elf_Data *d;
2705 struct section *s;
2706 int elferr, i, is_dynamic, j, jmax, nentries;
2707
2708 is_dynamic = 0;
2709
2710 for (i = 0; (size_t)i < re->shnum; i++) {
2711 s = &re->sl[i];
2712 if (s->type != SHT_DYNAMIC)
2713 continue;
2714 (void) elf_errno();
2715 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
2716 elferr = elf_errno();
2717 if (elferr != 0)
2718 warnx("elf_getdata failed: %s", elf_errmsg(-1));
2719 continue;
2720 }
2721 if (d->d_size <= 0)
2722 continue;
2723
2724 is_dynamic = 1;
2725
2726 /* Determine the actual number of table entries. */
2727 nentries = 0;
2728 if (!get_ent_count(s, &jmax))
2729 continue;
2730 for (j = 0; j < jmax; j++) {
2731 if (gelf_getdyn(d, j, &dyn) != &dyn) {
2732 warnx("gelf_getdyn failed: %s",
2733 elf_errmsg(-1));
2734 continue;
2735 }
2736 nentries ++;
2737 if (dyn.d_tag == DT_NULL)
2738 break;
2739 }
2740
2741 printf("\nDynamic section at offset 0x%jx", (uintmax_t)s->off);
2742 printf(" contains %u entries:\n", nentries);
2743
2744 if (re->ec == ELFCLASS32)
2745 printf("%5s%12s%28s\n", "Tag", "Type", "Name/Value");
2746 else
2747 printf("%5s%20s%28s\n", "Tag", "Type", "Name/Value");
2748
2749 for (j = 0; j < nentries; j++) {
2750 if (gelf_getdyn(d, j, &dyn) != &dyn)
2751 continue;
2752 /* Dump dynamic entry type. */
2753 if (re->ec == ELFCLASS32)
2754 printf(" 0x%8.8jx", (uintmax_t)dyn.d_tag);
2755 else
2756 printf(" 0x%16.16jx", (uintmax_t)dyn.d_tag);
2757 printf(" %-20s", dt_type(re->ehdr.e_machine,
2758 dyn.d_tag));
2759 /* Dump dynamic entry value. */
2760 dump_dyn_val(re, &dyn, s->link);
2761 }
2762 }
2763
2764 if (!is_dynamic)
2765 printf("\nThere is no dynamic section in this file.\n");
2766 }
2767
2768 static char *
timestamp(time_t ti)2769 timestamp(time_t ti)
2770 {
2771 static char ts[32];
2772 struct tm *t;
2773
2774 t = gmtime(&ti);
2775 snprintf(ts, sizeof(ts), "%04d-%02d-%02dT%02d:%02d:%02d",
2776 t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
2777 t->tm_min, t->tm_sec);
2778
2779 return (ts);
2780 }
2781
2782 static const char *
dyn_str(struct readelf * re,uint32_t stab,uint64_t d_val)2783 dyn_str(struct readelf *re, uint32_t stab, uint64_t d_val)
2784 {
2785 const char *name;
2786
2787 if (stab == SHN_UNDEF)
2788 name = "ERROR";
2789 else if ((name = elf_strptr(re->elf, stab, d_val)) == NULL) {
2790 (void) elf_errno(); /* clear error */
2791 name = "ERROR";
2792 }
2793
2794 return (name);
2795 }
2796
2797 static void
dump_arch_dyn_val(struct readelf * re,GElf_Dyn * dyn)2798 dump_arch_dyn_val(struct readelf *re, GElf_Dyn *dyn)
2799 {
2800 switch (re->ehdr.e_machine) {
2801 case EM_MIPS:
2802 case EM_MIPS_RS3_LE:
2803 switch (dyn->d_tag) {
2804 case DT_MIPS_RLD_VERSION:
2805 case DT_MIPS_LOCAL_GOTNO:
2806 case DT_MIPS_CONFLICTNO:
2807 case DT_MIPS_LIBLISTNO:
2808 case DT_MIPS_SYMTABNO:
2809 case DT_MIPS_UNREFEXTNO:
2810 case DT_MIPS_GOTSYM:
2811 case DT_MIPS_HIPAGENO:
2812 case DT_MIPS_DELTA_CLASS_NO:
2813 case DT_MIPS_DELTA_INSTANCE_NO:
2814 case DT_MIPS_DELTA_RELOC_NO:
2815 case DT_MIPS_DELTA_SYM_NO:
2816 case DT_MIPS_DELTA_CLASSSYM_NO:
2817 case DT_MIPS_LOCALPAGE_GOTIDX:
2818 case DT_MIPS_LOCAL_GOTIDX:
2819 case DT_MIPS_HIDDEN_GOTIDX:
2820 case DT_MIPS_PROTECTED_GOTIDX:
2821 printf(" %ju\n", (uintmax_t) dyn->d_un.d_val);
2822 break;
2823 case DT_MIPS_ICHECKSUM:
2824 case DT_MIPS_FLAGS:
2825 case DT_MIPS_BASE_ADDRESS:
2826 case DT_MIPS_CONFLICT:
2827 case DT_MIPS_LIBLIST:
2828 case DT_MIPS_RLD_MAP:
2829 case DT_MIPS_DELTA_CLASS:
2830 case DT_MIPS_DELTA_INSTANCE:
2831 case DT_MIPS_DELTA_RELOC:
2832 case DT_MIPS_DELTA_SYM:
2833 case DT_MIPS_DELTA_CLASSSYM:
2834 case DT_MIPS_CXX_FLAGS:
2835 case DT_MIPS_PIXIE_INIT:
2836 case DT_MIPS_SYMBOL_LIB:
2837 case DT_MIPS_OPTIONS:
2838 case DT_MIPS_INTERFACE:
2839 case DT_MIPS_DYNSTR_ALIGN:
2840 case DT_MIPS_INTERFACE_SIZE:
2841 case DT_MIPS_RLD_TEXT_RESOLVE_ADDR:
2842 case DT_MIPS_COMPACT_SIZE:
2843 case DT_MIPS_GP_VALUE:
2844 case DT_MIPS_AUX_DYNAMIC:
2845 case DT_MIPS_PLTGOT:
2846 case DT_MIPS_RLD_OBJ_UPDATE:
2847 case DT_MIPS_RWPLT:
2848 printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val);
2849 break;
2850 case DT_MIPS_IVERSION:
2851 case DT_MIPS_PERF_SUFFIX:
2852 case DT_MIPS_TIME_STAMP:
2853 printf(" %s\n", timestamp(dyn->d_un.d_val));
2854 break;
2855 default:
2856 printf("\n");
2857 break;
2858 }
2859 break;
2860 default:
2861 printf("\n");
2862 break;
2863 }
2864 }
2865
2866 static void
dump_flags(struct flag_desc * desc,uint64_t val)2867 dump_flags(struct flag_desc *desc, uint64_t val)
2868 {
2869 struct flag_desc *fd;
2870
2871 for (fd = desc; fd->flag != 0; fd++) {
2872 if (val & fd->flag) {
2873 val &= ~fd->flag;
2874 printf(" %s", fd->desc);
2875 }
2876 }
2877 if (val != 0)
2878 printf(" unknown (0x%jx)", (uintmax_t)val);
2879 printf("\n");
2880 }
2881
2882 static struct flag_desc dt_flags[] = {
2883 { DF_ORIGIN, "ORIGIN" },
2884 { DF_SYMBOLIC, "SYMBOLIC" },
2885 { DF_TEXTREL, "TEXTREL" },
2886 { DF_BIND_NOW, "BIND_NOW" },
2887 { DF_STATIC_TLS, "STATIC_TLS" },
2888 { 0, NULL }
2889 };
2890
2891 static struct flag_desc dt_flags_1[] = {
2892 { DF_1_BIND_NOW, "NOW" },
2893 { DF_1_GLOBAL, "GLOBAL" },
2894 { 0x4, "GROUP" },
2895 { DF_1_NODELETE, "NODELETE" },
2896 { DF_1_LOADFLTR, "LOADFLTR" },
2897 { 0x20, "INITFIRST" },
2898 { DF_1_NOOPEN, "NOOPEN" },
2899 { DF_1_ORIGIN, "ORIGIN" },
2900 { 0x100, "DIRECT" },
2901 { DF_1_INTERPOSE, "INTERPOSE" },
2902 { DF_1_NODEFLIB, "NODEFLIB" },
2903 { 0x1000, "NODUMP" },
2904 { 0x2000, "CONFALT" },
2905 { 0x4000, "ENDFILTEE" },
2906 { 0x8000, "DISPRELDNE" },
2907 { 0x10000, "DISPRELPND" },
2908 { 0x20000, "NODIRECT" },
2909 { 0x40000, "IGNMULDEF" },
2910 { 0x80000, "NOKSYMS" },
2911 { 0x100000, "NOHDR" },
2912 { 0x200000, "EDITED" },
2913 { 0x400000, "NORELOC" },
2914 { 0x800000, "SYMINTPOSE" },
2915 { 0x1000000, "GLOBAUDIT" },
2916 { 0x02000000, "SINGLETON" },
2917 { 0x04000000, "STUB" },
2918 { DF_1_PIE, "PIE" },
2919 { 0, NULL }
2920 };
2921
2922 static void
dump_dyn_val(struct readelf * re,GElf_Dyn * dyn,uint32_t stab)2923 dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab)
2924 {
2925 const char *name;
2926
2927 if (dyn->d_tag >= DT_LOPROC && dyn->d_tag <= DT_HIPROC &&
2928 dyn->d_tag != DT_AUXILIARY && dyn->d_tag != DT_FILTER) {
2929 dump_arch_dyn_val(re, dyn);
2930 return;
2931 }
2932
2933 /* These entry values are index into the string table. */
2934 name = NULL;
2935 if (dyn->d_tag == DT_AUXILIARY || dyn->d_tag == DT_FILTER ||
2936 dyn->d_tag == DT_NEEDED || dyn->d_tag == DT_SONAME ||
2937 dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH)
2938 name = dyn_str(re, stab, dyn->d_un.d_val);
2939
2940 switch(dyn->d_tag) {
2941 case DT_NULL:
2942 case DT_PLTGOT:
2943 case DT_HASH:
2944 case DT_STRTAB:
2945 case DT_SYMTAB:
2946 case DT_RELA:
2947 case DT_INIT:
2948 case DT_SYMBOLIC:
2949 case DT_REL:
2950 case DT_DEBUG:
2951 case DT_TEXTREL:
2952 case DT_JMPREL:
2953 case DT_FINI:
2954 case DT_VERDEF:
2955 case DT_VERNEED:
2956 case DT_VERSYM:
2957 case DT_GNU_HASH:
2958 case DT_GNU_LIBLIST:
2959 case DT_GNU_CONFLICT:
2960 printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val);
2961 break;
2962 case DT_PLTRELSZ:
2963 case DT_RELASZ:
2964 case DT_RELAENT:
2965 case DT_STRSZ:
2966 case DT_SYMENT:
2967 case DT_RELSZ:
2968 case DT_RELENT:
2969 case DT_PREINIT_ARRAYSZ:
2970 case DT_INIT_ARRAYSZ:
2971 case DT_FINI_ARRAYSZ:
2972 case DT_GNU_CONFLICTSZ:
2973 case DT_GNU_LIBLISTSZ:
2974 printf(" %ju (bytes)\n", (uintmax_t) dyn->d_un.d_val);
2975 break;
2976 case DT_RELACOUNT:
2977 case DT_RELCOUNT:
2978 case DT_VERDEFNUM:
2979 case DT_VERNEEDNUM:
2980 printf(" %ju\n", (uintmax_t) dyn->d_un.d_val);
2981 break;
2982 case DT_AUXILIARY:
2983 printf(" Auxiliary library: [%s]\n", name);
2984 break;
2985 case DT_FILTER:
2986 printf(" Filter library: [%s]\n", name);
2987 break;
2988 case DT_NEEDED:
2989 printf(" Shared library: [%s]\n", name);
2990 break;
2991 case DT_SONAME:
2992 printf(" Library soname: [%s]\n", name);
2993 break;
2994 case DT_RPATH:
2995 printf(" Library rpath: [%s]\n", name);
2996 break;
2997 case DT_RUNPATH:
2998 printf(" Library runpath: [%s]\n", name);
2999 break;
3000 case DT_PLTREL:
3001 printf(" %s\n", dt_type(re->ehdr.e_machine, dyn->d_un.d_val));
3002 break;
3003 case DT_GNU_PRELINKED:
3004 printf(" %s\n", timestamp(dyn->d_un.d_val));
3005 break;
3006 case DT_FLAGS:
3007 dump_flags(dt_flags, dyn->d_un.d_val);
3008 break;
3009 case DT_FLAGS_1:
3010 dump_flags(dt_flags_1, dyn->d_un.d_val);
3011 break;
3012 default:
3013 printf("\n");
3014 }
3015 }
3016
3017 static void
dump_rel(struct readelf * re,struct section * s,Elf_Data * d)3018 dump_rel(struct readelf *re, struct section *s, Elf_Data *d)
3019 {
3020 GElf_Rel r;
3021 const char *symname;
3022 uint64_t symval;
3023 int i, len;
3024 uint32_t type;
3025 uint8_t type2, type3;
3026
3027 if (s->link >= re->shnum)
3028 return;
3029
3030 #define REL_HDR "r_offset", "r_info", "r_type", "st_value", "st_name"
3031 #define REL_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \
3032 elftc_reloc_type_str(re->ehdr.e_machine, \
3033 ELF32_R_TYPE(r.r_info)), (uintmax_t)symval, symname
3034 #define REL_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \
3035 elftc_reloc_type_str(re->ehdr.e_machine, type), \
3036 (uintmax_t)symval, symname
3037
3038 printf("\nRelocation section (%s):\n", s->name);
3039 if (re->ec == ELFCLASS32)
3040 printf("%-8s %-8s %-19s %-8s %s\n", REL_HDR);
3041 else {
3042 if (re->options & RE_WW)
3043 printf("%-16s %-16s %-24s %-16s %s\n", REL_HDR);
3044 else
3045 printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR);
3046 }
3047 assert(d->d_size == s->sz);
3048 if (!get_ent_count(s, &len))
3049 return;
3050 for (i = 0; i < len; i++) {
3051 if (gelf_getrel(d, i, &r) != &r) {
3052 warnx("gelf_getrel failed: %s", elf_errmsg(-1));
3053 continue;
3054 }
3055 symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info));
3056 symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info));
3057 if (re->ec == ELFCLASS32) {
3058 r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info),
3059 ELF64_R_TYPE(r.r_info));
3060 printf("%8.8jx %8.8jx %-19.19s %8.8jx %s\n", REL_CT32);
3061 } else {
3062 type = ELF64_R_TYPE(r.r_info);
3063 if (re->ehdr.e_machine == EM_MIPS) {
3064 type2 = (type >> 8) & 0xFF;
3065 type3 = (type >> 16) & 0xFF;
3066 type = type & 0xFF;
3067 } else {
3068 type2 = type3 = 0;
3069 }
3070 if (re->options & RE_WW)
3071 printf("%16.16jx %16.16jx %-24.24s"
3072 " %16.16jx %s\n", REL_CT64);
3073 else
3074 printf("%12.12jx %12.12jx %-19.19s"
3075 " %16.16jx %s\n", REL_CT64);
3076 if (re->ehdr.e_machine == EM_MIPS) {
3077 if (re->options & RE_WW) {
3078 printf("%32s: %s\n", "Type2",
3079 elftc_reloc_type_str(EM_MIPS,
3080 type2));
3081 printf("%32s: %s\n", "Type3",
3082 elftc_reloc_type_str(EM_MIPS,
3083 type3));
3084 } else {
3085 printf("%24s: %s\n", "Type2",
3086 elftc_reloc_type_str(EM_MIPS,
3087 type2));
3088 printf("%24s: %s\n", "Type3",
3089 elftc_reloc_type_str(EM_MIPS,
3090 type3));
3091 }
3092 }
3093 }
3094 }
3095
3096 #undef REL_HDR
3097 #undef REL_CT
3098 }
3099
3100 static void
dump_rela(struct readelf * re,struct section * s,Elf_Data * d)3101 dump_rela(struct readelf *re, struct section *s, Elf_Data *d)
3102 {
3103 GElf_Rela r;
3104 const char *symname;
3105 uint64_t symval;
3106 int i, len;
3107 uint32_t type;
3108 uint8_t type2, type3;
3109
3110 if (s->link >= re->shnum)
3111 return;
3112
3113 #define RELA_HDR "r_offset", "r_info", "r_type", "st_value", \
3114 "st_name + r_addend"
3115 #define RELA_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \
3116 elftc_reloc_type_str(re->ehdr.e_machine, \
3117 ELF32_R_TYPE(r.r_info)), (uintmax_t)symval, symname
3118 #define RELA_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \
3119 elftc_reloc_type_str(re->ehdr.e_machine, type), \
3120 (uintmax_t)symval, symname
3121
3122 printf("\nRelocation section with addend (%s):\n", s->name);
3123 if (re->ec == ELFCLASS32)
3124 printf("%-8s %-8s %-19s %-8s %s\n", RELA_HDR);
3125 else {
3126 if (re->options & RE_WW)
3127 printf("%-16s %-16s %-24s %-16s %s\n", RELA_HDR);
3128 else
3129 printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR);
3130 }
3131 assert(d->d_size == s->sz);
3132 if (!get_ent_count(s, &len))
3133 return;
3134 for (i = 0; i < len; i++) {
3135 if (gelf_getrela(d, i, &r) != &r) {
3136 warnx("gelf_getrel failed: %s", elf_errmsg(-1));
3137 continue;
3138 }
3139 symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info));
3140 symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info));
3141 if (re->ec == ELFCLASS32) {
3142 r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info),
3143 ELF64_R_TYPE(r.r_info));
3144 printf("%8.8jx %8.8jx %-19.19s %8.8jx %s", RELA_CT32);
3145 printf(" + %x\n", (uint32_t) r.r_addend);
3146 } else {
3147 type = ELF64_R_TYPE(r.r_info);
3148 if (re->ehdr.e_machine == EM_MIPS) {
3149 type2 = (type >> 8) & 0xFF;
3150 type3 = (type >> 16) & 0xFF;
3151 type = type & 0xFF;
3152 } else {
3153 type2 = type3 = 0;
3154 }
3155 if (re->options & RE_WW)
3156 printf("%16.16jx %16.16jx %-24.24s"
3157 " %16.16jx %s", RELA_CT64);
3158 else
3159 printf("%12.12jx %12.12jx %-19.19s"
3160 " %16.16jx %s", RELA_CT64);
3161 printf(" + %jx\n", (uintmax_t) r.r_addend);
3162 if (re->ehdr.e_machine == EM_MIPS) {
3163 if (re->options & RE_WW) {
3164 printf("%32s: %s\n", "Type2",
3165 elftc_reloc_type_str(EM_MIPS,
3166 type2));
3167 printf("%32s: %s\n", "Type3",
3168 elftc_reloc_type_str(EM_MIPS,
3169 type3));
3170 } else {
3171 printf("%24s: %s\n", "Type2",
3172 elftc_reloc_type_str(EM_MIPS,
3173 type2));
3174 printf("%24s: %s\n", "Type3",
3175 elftc_reloc_type_str(EM_MIPS,
3176 type3));
3177 }
3178 }
3179 }
3180 }
3181
3182 #undef RELA_HDR
3183 #undef RELA_CT
3184 }
3185
3186 static void
dump_reloc(struct readelf * re)3187 dump_reloc(struct readelf *re)
3188 {
3189 struct section *s;
3190 Elf_Data *d;
3191 int i, elferr;
3192
3193 for (i = 0; (size_t)i < re->shnum; i++) {
3194 s = &re->sl[i];
3195 if (s->type == SHT_REL || s->type == SHT_RELA) {
3196 (void) elf_errno();
3197 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3198 elferr = elf_errno();
3199 if (elferr != 0)
3200 warnx("elf_getdata failed: %s",
3201 elf_errmsg(elferr));
3202 continue;
3203 }
3204 if (s->type == SHT_REL)
3205 dump_rel(re, s, d);
3206 else
3207 dump_rela(re, s, d);
3208 }
3209 }
3210 }
3211
3212 static void
dump_symtab(struct readelf * re,int i)3213 dump_symtab(struct readelf *re, int i)
3214 {
3215 struct section *s;
3216 Elf_Data *d;
3217 GElf_Sym sym;
3218 const char *name;
3219 uint32_t stab;
3220 int elferr, j, len;
3221 uint16_t vs;
3222
3223 s = &re->sl[i];
3224 if (s->link >= re->shnum)
3225 return;
3226 stab = s->link;
3227 (void) elf_errno();
3228 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3229 elferr = elf_errno();
3230 if (elferr != 0)
3231 warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3232 return;
3233 }
3234 if (d->d_size <= 0)
3235 return;
3236 if (!get_ent_count(s, &len))
3237 return;
3238 printf("\nSymbol table '%s' contains %d entries:\n", s->name, len);
3239 printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type",
3240 "Bind", "Vis", "Ndx", "Name");
3241
3242 for (j = 0; j < len; j++) {
3243 if (gelf_getsym(d, j, &sym) != &sym) {
3244 warnx("gelf_getsym failed: %s", elf_errmsg(-1));
3245 continue;
3246 }
3247 printf("%6d:", j);
3248 printf(" %16.16jx", (uintmax_t) sym.st_value);
3249 printf(" %5ju", (uintmax_t) sym.st_size);
3250 printf(" %-7s", st_type(re->ehdr.e_machine,
3251 re->ehdr.e_ident[EI_OSABI], GELF_ST_TYPE(sym.st_info)));
3252 printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info)));
3253 printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other)));
3254 printf(" %3s", st_shndx(sym.st_shndx));
3255 if ((name = elf_strptr(re->elf, stab, sym.st_name)) != NULL)
3256 printf(" %s", name);
3257 /* Append symbol version string for SHT_DYNSYM symbol table. */
3258 if (s->type == SHT_DYNSYM && re->ver != NULL &&
3259 re->vs != NULL && re->vs[j] > 1) {
3260 vs = re->vs[j] & VERSYM_VERSION;
3261 if (vs >= re->ver_sz || re->ver[vs].name == NULL) {
3262 warnx("invalid versym version index %u", vs);
3263 break;
3264 }
3265 if (re->vs[j] & VERSYM_HIDDEN || re->ver[vs].type == 0)
3266 printf("@%s (%d)", re->ver[vs].name, vs);
3267 else
3268 printf("@@%s (%d)", re->ver[vs].name, vs);
3269 }
3270 putchar('\n');
3271 }
3272
3273 }
3274
3275 static void
dump_symtabs(struct readelf * re)3276 dump_symtabs(struct readelf *re)
3277 {
3278 GElf_Dyn dyn;
3279 Elf_Data *d;
3280 struct section *s;
3281 uint64_t dyn_off;
3282 int elferr, i, len;
3283
3284 /*
3285 * If -D is specified, only dump the symbol table specified by
3286 * the DT_SYMTAB entry in the .dynamic section.
3287 */
3288 dyn_off = 0;
3289 if (re->options & RE_DD) {
3290 s = NULL;
3291 for (i = 0; (size_t)i < re->shnum; i++)
3292 if (re->sl[i].type == SHT_DYNAMIC) {
3293 s = &re->sl[i];
3294 break;
3295 }
3296 if (s == NULL)
3297 return;
3298 (void) elf_errno();
3299 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3300 elferr = elf_errno();
3301 if (elferr != 0)
3302 warnx("elf_getdata failed: %s", elf_errmsg(-1));
3303 return;
3304 }
3305 if (d->d_size <= 0)
3306 return;
3307 if (!get_ent_count(s, &len))
3308 return;
3309
3310 for (i = 0; i < len; i++) {
3311 if (gelf_getdyn(d, i, &dyn) != &dyn) {
3312 warnx("gelf_getdyn failed: %s", elf_errmsg(-1));
3313 continue;
3314 }
3315 if (dyn.d_tag == DT_SYMTAB) {
3316 dyn_off = dyn.d_un.d_val;
3317 break;
3318 }
3319 }
3320 }
3321
3322 /* Find and dump symbol tables. */
3323 for (i = 0; (size_t)i < re->shnum; i++) {
3324 s = &re->sl[i];
3325 if (s->type == SHT_SYMTAB || s->type == SHT_DYNSYM) {
3326 if (re->options & RE_DD) {
3327 if (dyn_off == s->addr) {
3328 dump_symtab(re, i);
3329 break;
3330 }
3331 } else
3332 dump_symtab(re, i);
3333 }
3334 }
3335 }
3336
3337 static void
dump_svr4_hash(struct section * s)3338 dump_svr4_hash(struct section *s)
3339 {
3340 Elf_Data *d;
3341 uint32_t *buf;
3342 uint32_t nbucket, nchain;
3343 uint32_t *bucket, *chain;
3344 uint32_t *bl, *c, maxl, total;
3345 int elferr, i, j;
3346
3347 /* Read and parse the content of .hash section. */
3348 (void) elf_errno();
3349 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3350 elferr = elf_errno();
3351 if (elferr != 0)
3352 warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3353 return;
3354 }
3355 if (d->d_size < 2 * sizeof(uint32_t)) {
3356 warnx(".hash section too small");
3357 return;
3358 }
3359 buf = d->d_buf;
3360 nbucket = buf[0];
3361 nchain = buf[1];
3362 if (nbucket <= 0 || nchain <= 0) {
3363 warnx("Malformed .hash section");
3364 return;
3365 }
3366 if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
3367 warnx("Malformed .hash section");
3368 return;
3369 }
3370 bucket = &buf[2];
3371 chain = &buf[2 + nbucket];
3372
3373 maxl = 0;
3374 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
3375 errx(EXIT_FAILURE, "calloc failed");
3376 for (i = 0; (uint32_t)i < nbucket; i++)
3377 for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j])
3378 if (++bl[i] > maxl)
3379 maxl = bl[i];
3380 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
3381 errx(EXIT_FAILURE, "calloc failed");
3382 for (i = 0; (uint32_t)i < nbucket; i++)
3383 c[bl[i]]++;
3384 printf("\nHistogram for bucket list length (total of %u buckets):\n",
3385 nbucket);
3386 printf(" Length\tNumber\t\t%% of total\tCoverage\n");
3387 total = 0;
3388 for (i = 0; (uint32_t)i <= maxl; i++) {
3389 total += c[i] * i;
3390 printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i],
3391 c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
3392 }
3393 free(c);
3394 free(bl);
3395 }
3396
3397 static void
dump_svr4_hash64(struct readelf * re,struct section * s)3398 dump_svr4_hash64(struct readelf *re, struct section *s)
3399 {
3400 Elf_Data *d, dst;
3401 uint64_t *buf;
3402 uint64_t nbucket, nchain;
3403 uint64_t *bucket, *chain;
3404 uint64_t *bl, *c, maxl, total;
3405 int elferr, i, j;
3406
3407 /*
3408 * ALPHA uses 64-bit hash entries. Since libelf assumes that
3409 * .hash section contains only 32-bit entry, an explicit
3410 * gelf_xlatetom is needed here.
3411 */
3412 (void) elf_errno();
3413 if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
3414 elferr = elf_errno();
3415 if (elferr != 0)
3416 warnx("elf_rawdata failed: %s",
3417 elf_errmsg(elferr));
3418 return;
3419 }
3420 d->d_type = ELF_T_XWORD;
3421 memcpy(&dst, d, sizeof(Elf_Data));
3422 if (gelf_xlatetom(re->elf, &dst, d,
3423 re->ehdr.e_ident[EI_DATA]) != &dst) {
3424 warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
3425 return;
3426 }
3427 if (dst.d_size < 2 * sizeof(uint64_t)) {
3428 warnx(".hash section too small");
3429 return;
3430 }
3431 buf = dst.d_buf;
3432 nbucket = buf[0];
3433 nchain = buf[1];
3434 if (nbucket <= 0 || nchain <= 0) {
3435 warnx("Malformed .hash section");
3436 return;
3437 }
3438 if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
3439 warnx("Malformed .hash section");
3440 return;
3441 }
3442 bucket = &buf[2];
3443 chain = &buf[2 + nbucket];
3444
3445 maxl = 0;
3446 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
3447 errx(EXIT_FAILURE, "calloc failed");
3448 for (i = 0; (uint32_t)i < nbucket; i++)
3449 for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j])
3450 if (++bl[i] > maxl)
3451 maxl = bl[i];
3452 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
3453 errx(EXIT_FAILURE, "calloc failed");
3454 for (i = 0; (uint64_t)i < nbucket; i++)
3455 c[bl[i]]++;
3456 printf("Histogram for bucket list length (total of %ju buckets):\n",
3457 (uintmax_t)nbucket);
3458 printf(" Length\tNumber\t\t%% of total\tCoverage\n");
3459 total = 0;
3460 for (i = 0; (uint64_t)i <= maxl; i++) {
3461 total += c[i] * i;
3462 printf("%7u\t%-10ju\t(%5.1f%%)\t%5.1f%%\n", i, (uintmax_t)c[i],
3463 c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
3464 }
3465 free(c);
3466 free(bl);
3467 }
3468
3469 static void
dump_gnu_hash(struct readelf * re,struct section * s)3470 dump_gnu_hash(struct readelf *re, struct section *s)
3471 {
3472 struct section *ds;
3473 Elf_Data *d;
3474 uint32_t *buf;
3475 uint32_t *bucket, *chain;
3476 uint32_t nbucket, nchain, symndx, maskwords;
3477 uint32_t *bl, *c, maxl, total;
3478 int elferr, dynsymcount, i, j;
3479
3480 (void) elf_errno();
3481 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3482 elferr = elf_errno();
3483 if (elferr != 0)
3484 warnx("elf_getdata failed: %s",
3485 elf_errmsg(elferr));
3486 return;
3487 }
3488 if (d->d_size < 4 * sizeof(uint32_t)) {
3489 warnx(".gnu.hash section too small");
3490 return;
3491 }
3492 buf = d->d_buf;
3493 nbucket = buf[0];
3494 symndx = buf[1];
3495 maskwords = buf[2];
3496 buf += 4;
3497 if (s->link >= re->shnum)
3498 return;
3499 ds = &re->sl[s->link];
3500 if (!get_ent_count(ds, &dynsymcount))
3501 return;
3502 if (symndx >= (uint32_t)dynsymcount) {
3503 warnx("Malformed .gnu.hash section (symndx out of range)");
3504 return;
3505 }
3506 nchain = dynsymcount - symndx;
3507 if (d->d_size != 4 * sizeof(uint32_t) + maskwords *
3508 (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) +
3509 (nbucket + nchain) * sizeof(uint32_t)) {
3510 warnx("Malformed .gnu.hash section");
3511 return;
3512 }
3513 bucket = buf + (re->ec == ELFCLASS32 ? maskwords : maskwords * 2);
3514 chain = bucket + nbucket;
3515
3516 maxl = 0;
3517 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
3518 errx(EXIT_FAILURE, "calloc failed");
3519 for (i = 0; (uint32_t)i < nbucket; i++)
3520 for (j = bucket[i]; j > 0 && (uint32_t)j - symndx < nchain;
3521 j++) {
3522 if (++bl[i] > maxl)
3523 maxl = bl[i];
3524 if (chain[j - symndx] & 1)
3525 break;
3526 }
3527 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
3528 errx(EXIT_FAILURE, "calloc failed");
3529 for (i = 0; (uint32_t)i < nbucket; i++)
3530 c[bl[i]]++;
3531 printf("Histogram for bucket list length (total of %u buckets):\n",
3532 nbucket);
3533 printf(" Length\tNumber\t\t%% of total\tCoverage\n");
3534 total = 0;
3535 for (i = 0; (uint32_t)i <= maxl; i++) {
3536 total += c[i] * i;
3537 printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i],
3538 c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1));
3539 }
3540 free(c);
3541 free(bl);
3542 }
3543
3544 static struct flag_desc gnu_property_x86_feature_1_and_bits[] = {
3545 { GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT" },
3546 { GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK" },
3547 { 0, NULL }
3548 };
3549
3550 static void
dump_gnu_property_type_0(struct readelf * re,const char * buf,size_t sz)3551 dump_gnu_property_type_0(struct readelf *re, const char *buf, size_t sz)
3552 {
3553 size_t i;
3554 uint32_t type, prop_sz;
3555
3556 printf(" Properties: ");
3557 while (sz > 0) {
3558 if (sz < 8)
3559 goto bad;
3560
3561 type = *(const uint32_t *)(const void *)buf;
3562 prop_sz = *(const uint32_t *)(const void *)(buf + 4);
3563 buf += 8;
3564 sz -= 8;
3565
3566 if (prop_sz > sz)
3567 goto bad;
3568
3569 if (type >= GNU_PROPERTY_LOPROC &&
3570 type <= GNU_PROPERTY_HIPROC) {
3571 if (re->ehdr.e_machine != EM_X86_64) {
3572 printf("machine type %x unknown\n",
3573 re->ehdr.e_machine);
3574 goto unknown;
3575 }
3576 switch (type) {
3577 case GNU_PROPERTY_X86_FEATURE_1_AND:
3578 printf("x86 features:");
3579 if (prop_sz != 4)
3580 goto bad;
3581 dump_flags(gnu_property_x86_feature_1_and_bits,
3582 *(const uint32_t *)(const void *)buf);
3583 break;
3584 }
3585 }
3586
3587 buf += roundup2(prop_sz, 8);
3588 sz -= roundup2(prop_sz, 8);
3589 }
3590 return;
3591 bad:
3592 printf("corrupt GNU property\n");
3593 unknown:
3594 printf("remaining description data:");
3595 for (i = 0; i < sz; i++)
3596 printf(" %02x", (unsigned char)buf[i]);
3597 printf("\n");
3598 }
3599
3600 static void
dump_hash(struct readelf * re)3601 dump_hash(struct readelf *re)
3602 {
3603 struct section *s;
3604 int i;
3605
3606 for (i = 0; (size_t) i < re->shnum; i++) {
3607 s = &re->sl[i];
3608 if (s->type == SHT_HASH || s->type == SHT_GNU_HASH) {
3609 if (s->type == SHT_GNU_HASH)
3610 dump_gnu_hash(re, s);
3611 else if (re->ehdr.e_machine == EM_ALPHA &&
3612 s->entsize == 8)
3613 dump_svr4_hash64(re, s);
3614 else
3615 dump_svr4_hash(s);
3616 }
3617 }
3618 }
3619
3620 static void
dump_notes(struct readelf * re)3621 dump_notes(struct readelf *re)
3622 {
3623 struct section *s;
3624 const char *rawfile;
3625 GElf_Phdr phdr;
3626 Elf_Data *d;
3627 size_t filesize, phnum;
3628 int i, elferr;
3629
3630 if (re->ehdr.e_type == ET_CORE) {
3631 /*
3632 * Search program headers in the core file for
3633 * PT_NOTE entry.
3634 */
3635 if (elf_getphnum(re->elf, &phnum) == 0) {
3636 warnx("elf_getphnum failed: %s", elf_errmsg(-1));
3637 return;
3638 }
3639 if (phnum == 0)
3640 return;
3641 if ((rawfile = elf_rawfile(re->elf, &filesize)) == NULL) {
3642 warnx("elf_rawfile failed: %s", elf_errmsg(-1));
3643 return;
3644 }
3645 for (i = 0; (size_t) i < phnum; i++) {
3646 if (gelf_getphdr(re->elf, i, &phdr) != &phdr) {
3647 warnx("gelf_getphdr failed: %s",
3648 elf_errmsg(-1));
3649 continue;
3650 }
3651 if (phdr.p_type == PT_NOTE) {
3652 if (phdr.p_offset >= filesize ||
3653 phdr.p_filesz > filesize - phdr.p_offset) {
3654 warnx("invalid PHDR offset");
3655 continue;
3656 }
3657 dump_notes_content(re, rawfile + phdr.p_offset,
3658 phdr.p_filesz, phdr.p_offset);
3659 }
3660 }
3661
3662 } else {
3663 /*
3664 * For objects other than core files, Search for
3665 * SHT_NOTE sections.
3666 */
3667 for (i = 0; (size_t) i < re->shnum; i++) {
3668 s = &re->sl[i];
3669 if (s->type == SHT_NOTE) {
3670 (void) elf_errno();
3671 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3672 elferr = elf_errno();
3673 if (elferr != 0)
3674 warnx("elf_getdata failed: %s",
3675 elf_errmsg(elferr));
3676 continue;
3677 }
3678 dump_notes_content(re, d->d_buf, d->d_size,
3679 s->off);
3680 }
3681 }
3682 }
3683 }
3684
3685 static struct flag_desc note_feature_ctl_flags[] = {
3686 { NT_FREEBSD_FCTL_ASLR_DISABLE, "ASLR_DISABLE" },
3687 { NT_FREEBSD_FCTL_PROTMAX_DISABLE, "PROTMAX_DISABLE" },
3688 { NT_FREEBSD_FCTL_STKGAP_DISABLE, "STKGAP_DISABLE" },
3689 { NT_FREEBSD_FCTL_WXNEEDED, "WXNEEDED" },
3690 { NT_FREEBSD_FCTL_LA48, "LA48" },
3691 { NT_FREEBSD_FCTL_ASG_DISABLE, "ASG_DISABLE" },
3692 { 0, NULL }
3693 };
3694
3695 static bool
dump_note_string(const char * description,const char * s,size_t len)3696 dump_note_string(const char *description, const char *s, size_t len)
3697 {
3698 size_t i;
3699
3700 if (len == 0 || s[--len] != '\0') {
3701 return (false);
3702 } else {
3703 for (i = 0; i < len; i++)
3704 if (!isprint(s[i]))
3705 return (false);
3706 }
3707
3708 printf(" %s: %s\n", description, s);
3709 return (true);
3710 }
3711
3712 struct note_desc {
3713 uint32_t type;
3714 const char *description;
3715 bool (*fp)(const char *, const char *, size_t);
3716 };
3717
3718 static struct note_desc xen_notes[] = {
3719 { 5, "Xen version", dump_note_string },
3720 { 6, "Guest OS", dump_note_string },
3721 { 7, "Guest version", dump_note_string },
3722 { 8, "Loader", dump_note_string },
3723 { 9, "PAE mode", dump_note_string },
3724 { 10, "Features", dump_note_string },
3725 { 11, "BSD symtab", dump_note_string },
3726 { 0, NULL, NULL }
3727 };
3728
3729 static void
dump_notes_data(struct readelf * re,const char * name,uint32_t type,const char * buf,size_t sz)3730 dump_notes_data(struct readelf *re, const char *name, uint32_t type,
3731 const char *buf, size_t sz)
3732 {
3733 struct note_desc *nd;
3734 size_t i;
3735 const uint32_t *ubuf;
3736
3737 /* Note data is at least 4-byte aligned. */
3738 if (((uintptr_t)buf & 3) != 0) {
3739 warnx("bad note data alignment");
3740 goto unknown;
3741 }
3742 ubuf = (const uint32_t *)(const void *)buf;
3743
3744 if (strcmp(name, "FreeBSD") == 0) {
3745 switch (type) {
3746 case NT_FREEBSD_ABI_TAG:
3747 if (sz != 4)
3748 goto unknown;
3749 printf(" ABI tag: %u\n", ubuf[0]);
3750 return;
3751 /* NT_FREEBSD_NOINIT_TAG carries no data, treat as unknown. */
3752 case NT_FREEBSD_ARCH_TAG:
3753 if (sz != 4)
3754 goto unknown;
3755 printf(" Arch tag: %x\n", ubuf[0]);
3756 return;
3757 case NT_FREEBSD_FEATURE_CTL:
3758 if (sz != 4)
3759 goto unknown;
3760 printf(" Features:");
3761 dump_flags(note_feature_ctl_flags, ubuf[0]);
3762 return;
3763 }
3764 } else if (strcmp(name, "Go") == 0) {
3765 if (type == 4) {
3766 printf(" Build ID: ");
3767 for (i = 0; i < sz; i++) {
3768 printf(isprint(buf[i]) ? "%c" : "<%02x>",
3769 buf[i]);
3770 }
3771 printf("\n");
3772 return;
3773 }
3774 } else if (strcmp(name, "GNU") == 0) {
3775 switch (type) {
3776 case NT_GNU_PROPERTY_TYPE_0:
3777 dump_gnu_property_type_0(re, buf, sz);
3778 return;
3779 case NT_GNU_BUILD_ID:
3780 printf(" Build ID: ");
3781 for (i = 0; i < sz; i++)
3782 printf("%02x", (unsigned char)buf[i]);
3783 printf("\n");
3784 return;
3785 }
3786 } else if (strcmp(name, "Xen") == 0) {
3787 for (nd = xen_notes; nd->description != NULL; nd++) {
3788 if (nd->type == type) {
3789 if (nd->fp(nd->description, buf, sz))
3790 return;
3791 else
3792 break;
3793 }
3794 }
3795 }
3796 unknown:
3797 printf(" description data:");
3798 for (i = 0; i < sz; i++)
3799 printf(" %02x", (unsigned char)buf[i]);
3800 printf("\n");
3801 }
3802
3803 static void
dump_notes_content(struct readelf * re,const char * buf,size_t sz,off_t off)3804 dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off)
3805 {
3806 Elf_Note *note;
3807 const char *end, *name;
3808 uint32_t namesz, descsz;
3809
3810 printf("\nNotes at offset %#010jx with length %#010jx:\n",
3811 (uintmax_t) off, (uintmax_t) sz);
3812 printf(" %-13s %-15s %s\n", "Owner", "Data size", "Description");
3813 end = buf + sz;
3814 while (buf < end) {
3815 if (buf + sizeof(*note) > end) {
3816 warnx("invalid note header");
3817 return;
3818 }
3819 note = (Elf_Note *)(uintptr_t) buf;
3820 namesz = roundup2(note->n_namesz, 4);
3821 descsz = roundup2(note->n_descsz, 4);
3822 if (namesz < note->n_namesz || descsz < note->n_descsz ||
3823 buf + namesz + descsz > end) {
3824 warnx("invalid note header");
3825 return;
3826 }
3827 buf += sizeof(Elf_Note);
3828 name = buf;
3829 buf += namesz;
3830 /*
3831 * The name field is required to be nul-terminated, and
3832 * n_namesz includes the terminating nul in observed
3833 * implementations (contrary to the ELF-64 spec). A special
3834 * case is needed for cores generated by some older Linux
3835 * versions, which write a note named "CORE" without a nul
3836 * terminator and n_namesz = 4.
3837 */
3838 if (note->n_namesz == 0)
3839 name = "";
3840 else if (note->n_namesz == 4 && strncmp(name, "CORE", 4) == 0)
3841 name = "CORE";
3842 else if (strnlen(name, note->n_namesz) >= note->n_namesz)
3843 name = "<invalid>";
3844 printf(" %-13s %#010jx", name, (uintmax_t) note->n_descsz);
3845 printf(" %s\n", note_type(name, re->ehdr.e_type,
3846 note->n_type));
3847 dump_notes_data(re, name, note->n_type, buf, note->n_descsz);
3848 buf += descsz;
3849 }
3850 }
3851
3852 /*
3853 * Symbol versioning sections are the same for 32bit and 64bit
3854 * ELF objects.
3855 */
3856 #define Elf_Verdef Elf32_Verdef
3857 #define Elf_Verdaux Elf32_Verdaux
3858 #define Elf_Verneed Elf32_Verneed
3859 #define Elf_Vernaux Elf32_Vernaux
3860
3861 #define SAVE_VERSION_NAME(x, n, t) \
3862 do { \
3863 while (x >= re->ver_sz) { \
3864 nv = realloc(re->ver, \
3865 sizeof(*re->ver) * re->ver_sz * 2); \
3866 if (nv == NULL) { \
3867 warn("realloc failed"); \
3868 free(re->ver); \
3869 return; \
3870 } \
3871 re->ver = nv; \
3872 for (i = re->ver_sz; i < re->ver_sz * 2; i++) { \
3873 re->ver[i].name = NULL; \
3874 re->ver[i].type = 0; \
3875 } \
3876 re->ver_sz *= 2; \
3877 } \
3878 if (x > 1) { \
3879 re->ver[x].name = n; \
3880 re->ver[x].type = t; \
3881 } \
3882 } while (0)
3883
3884
3885 static void
dump_verdef(struct readelf * re,int dump)3886 dump_verdef(struct readelf *re, int dump)
3887 {
3888 struct section *s;
3889 struct symver *nv;
3890 Elf_Data *d;
3891 Elf_Verdef *vd;
3892 Elf_Verdaux *vda;
3893 uint8_t *buf, *end, *buf2;
3894 const char *name;
3895 int elferr, i, j;
3896
3897 if ((s = re->vd_s) == NULL)
3898 return;
3899 if (s->link >= re->shnum)
3900 return;
3901
3902 if (re->ver == NULL) {
3903 re->ver_sz = 16;
3904 if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) ==
3905 NULL) {
3906 warn("calloc failed");
3907 return;
3908 }
3909 re->ver[0].name = "*local*";
3910 re->ver[1].name = "*global*";
3911 }
3912
3913 if (dump)
3914 printf("\nVersion definition section (%s):\n", s->name);
3915 (void) elf_errno();
3916 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3917 elferr = elf_errno();
3918 if (elferr != 0)
3919 warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3920 return;
3921 }
3922 if (d->d_size == 0)
3923 return;
3924
3925 buf = d->d_buf;
3926 end = buf + d->d_size;
3927 while (buf + sizeof(Elf_Verdef) <= end) {
3928 vd = (Elf_Verdef *) (uintptr_t) buf;
3929 if (dump) {
3930 printf(" 0x%4.4lx", (unsigned long)
3931 (buf - (uint8_t *)d->d_buf));
3932 printf(" vd_version: %u vd_flags: %d"
3933 " vd_ndx: %u vd_cnt: %u", vd->vd_version,
3934 vd->vd_flags, vd->vd_ndx, vd->vd_cnt);
3935 }
3936 buf2 = buf + vd->vd_aux;
3937 j = 0;
3938 while (buf2 + sizeof(Elf_Verdaux) <= end && j < vd->vd_cnt) {
3939 vda = (Elf_Verdaux *) (uintptr_t) buf2;
3940 name = get_string(re, s->link, vda->vda_name);
3941 if (j == 0) {
3942 if (dump)
3943 printf(" vda_name: %s\n", name);
3944 SAVE_VERSION_NAME((int)vd->vd_ndx, name, 1);
3945 } else if (dump)
3946 printf(" 0x%4.4lx parent: %s\n",
3947 (unsigned long) (buf2 -
3948 (uint8_t *)d->d_buf), name);
3949 if (vda->vda_next == 0)
3950 break;
3951 buf2 += vda->vda_next;
3952 j++;
3953 }
3954 if (vd->vd_next == 0)
3955 break;
3956 buf += vd->vd_next;
3957 }
3958 }
3959
3960 static void
dump_verneed(struct readelf * re,int dump)3961 dump_verneed(struct readelf *re, int dump)
3962 {
3963 struct section *s;
3964 struct symver *nv;
3965 Elf_Data *d;
3966 Elf_Verneed *vn;
3967 Elf_Vernaux *vna;
3968 uint8_t *buf, *end, *buf2;
3969 const char *name;
3970 int elferr, i, j;
3971
3972 if ((s = re->vn_s) == NULL)
3973 return;
3974 if (s->link >= re->shnum)
3975 return;
3976
3977 if (re->ver == NULL) {
3978 re->ver_sz = 16;
3979 if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) ==
3980 NULL) {
3981 warn("calloc failed");
3982 return;
3983 }
3984 re->ver[0].name = "*local*";
3985 re->ver[1].name = "*global*";
3986 }
3987
3988 if (dump)
3989 printf("\nVersion needed section (%s):\n", s->name);
3990 (void) elf_errno();
3991 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
3992 elferr = elf_errno();
3993 if (elferr != 0)
3994 warnx("elf_getdata failed: %s", elf_errmsg(elferr));
3995 return;
3996 }
3997 if (d->d_size == 0)
3998 return;
3999
4000 buf = d->d_buf;
4001 end = buf + d->d_size;
4002 while (buf + sizeof(Elf_Verneed) <= end) {
4003 vn = (Elf_Verneed *) (uintptr_t) buf;
4004 if (dump) {
4005 printf(" 0x%4.4lx", (unsigned long)
4006 (buf - (uint8_t *)d->d_buf));
4007 printf(" vn_version: %u vn_file: %s vn_cnt: %u\n",
4008 vn->vn_version,
4009 get_string(re, s->link, vn->vn_file),
4010 vn->vn_cnt);
4011 }
4012 buf2 = buf + vn->vn_aux;
4013 j = 0;
4014 while (buf2 + sizeof(Elf_Vernaux) <= end && j < vn->vn_cnt) {
4015 vna = (Elf32_Vernaux *) (uintptr_t) buf2;
4016 if (dump)
4017 printf(" 0x%4.4lx", (unsigned long)
4018 (buf2 - (uint8_t *)d->d_buf));
4019 name = get_string(re, s->link, vna->vna_name);
4020 if (dump)
4021 printf(" vna_name: %s vna_flags: %u"
4022 " vna_other: %u\n", name,
4023 vna->vna_flags, vna->vna_other);
4024 SAVE_VERSION_NAME((int)vna->vna_other, name, 0);
4025 if (vna->vna_next == 0)
4026 break;
4027 buf2 += vna->vna_next;
4028 j++;
4029 }
4030 if (vn->vn_next == 0)
4031 break;
4032 buf += vn->vn_next;
4033 }
4034 }
4035
4036 static void
dump_versym(struct readelf * re)4037 dump_versym(struct readelf *re)
4038 {
4039 int i;
4040 uint16_t vs;
4041
4042 if (re->vs_s == NULL || re->ver == NULL || re->vs == NULL)
4043 return;
4044 printf("\nVersion symbol section (%s):\n", re->vs_s->name);
4045 for (i = 0; i < re->vs_sz; i++) {
4046 if ((i & 3) == 0) {
4047 if (i > 0)
4048 putchar('\n');
4049 printf(" %03x:", i);
4050 }
4051 vs = re->vs[i] & VERSYM_VERSION;
4052 if (vs >= re->ver_sz || re->ver[vs].name == NULL) {
4053 warnx("invalid versym version index %u", re->vs[i]);
4054 break;
4055 }
4056 if (re->vs[i] & VERSYM_HIDDEN)
4057 printf(" %3xh %-12s ", vs,
4058 re->ver[re->vs[i] & VERSYM_VERSION].name);
4059 else
4060 printf(" %3x %-12s ", vs, re->ver[re->vs[i]].name);
4061 }
4062 putchar('\n');
4063 }
4064
4065 static void
dump_ver(struct readelf * re)4066 dump_ver(struct readelf *re)
4067 {
4068
4069 if (re->vs_s && re->ver && re->vs)
4070 dump_versym(re);
4071 if (re->vd_s)
4072 dump_verdef(re, 1);
4073 if (re->vn_s)
4074 dump_verneed(re, 1);
4075 }
4076
4077 static void
search_ver(struct readelf * re)4078 search_ver(struct readelf *re)
4079 {
4080 struct section *s;
4081 Elf_Data *d;
4082 int elferr, i;
4083
4084 for (i = 0; (size_t) i < re->shnum; i++) {
4085 s = &re->sl[i];
4086 if (s->type == SHT_SUNW_versym)
4087 re->vs_s = s;
4088 if (s->type == SHT_SUNW_verneed)
4089 re->vn_s = s;
4090 if (s->type == SHT_SUNW_verdef)
4091 re->vd_s = s;
4092 }
4093 if (re->vd_s)
4094 dump_verdef(re, 0);
4095 if (re->vn_s)
4096 dump_verneed(re, 0);
4097 if (re->vs_s && re->ver != NULL) {
4098 (void) elf_errno();
4099 if ((d = elf_getdata(re->vs_s->scn, NULL)) == NULL) {
4100 elferr = elf_errno();
4101 if (elferr != 0)
4102 warnx("elf_getdata failed: %s",
4103 elf_errmsg(elferr));
4104 return;
4105 }
4106 if (d->d_size == 0)
4107 return;
4108 re->vs = d->d_buf;
4109 re->vs_sz = d->d_size / sizeof(Elf32_Half);
4110 }
4111 }
4112
4113 #undef Elf_Verdef
4114 #undef Elf_Verdaux
4115 #undef Elf_Verneed
4116 #undef Elf_Vernaux
4117 #undef SAVE_VERSION_NAME
4118
4119 /*
4120 * Elf32_Lib and Elf64_Lib are identical.
4121 */
4122 #define Elf_Lib Elf32_Lib
4123
4124 static void
dump_liblist(struct readelf * re)4125 dump_liblist(struct readelf *re)
4126 {
4127 struct section *s;
4128 struct tm *t;
4129 time_t ti;
4130 char tbuf[20];
4131 Elf_Data *d;
4132 Elf_Lib *lib;
4133 int i, j, k, elferr, first, len;
4134
4135 for (i = 0; (size_t) i < re->shnum; i++) {
4136 s = &re->sl[i];
4137 if (s->type != SHT_GNU_LIBLIST)
4138 continue;
4139 if (s->link >= re->shnum)
4140 continue;
4141 (void) elf_errno();
4142 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
4143 elferr = elf_errno();
4144 if (elferr != 0)
4145 warnx("elf_getdata failed: %s",
4146 elf_errmsg(elferr));
4147 continue;
4148 }
4149 if (d->d_size <= 0)
4150 continue;
4151 lib = d->d_buf;
4152 if (!get_ent_count(s, &len))
4153 continue;
4154 printf("\nLibrary list section '%s' ", s->name);
4155 printf("contains %d entries:\n", len);
4156 printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp",
4157 "Checksum", "Version", "Flags");
4158 for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) {
4159 printf("%3d: ", j);
4160 printf("%-20.20s ",
4161 get_string(re, s->link, lib->l_name));
4162 ti = lib->l_time_stamp;
4163 t = gmtime(&ti);
4164 snprintf(tbuf, sizeof(tbuf), "%04d-%02d-%02dT%02d:%02d"
4165 ":%2d", t->tm_year + 1900, t->tm_mon + 1,
4166 t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
4167 printf("%-19.19s ", tbuf);
4168 printf("0x%08x ", lib->l_checksum);
4169 printf("%-7d %#x", lib->l_version, lib->l_flags);
4170 if (lib->l_flags != 0) {
4171 first = 1;
4172 putchar('(');
4173 for (k = 0; l_flag[k].name != NULL; k++) {
4174 if ((l_flag[k].value & lib->l_flags) ==
4175 0)
4176 continue;
4177 if (!first)
4178 putchar(',');
4179 else
4180 first = 0;
4181 printf("%s", l_flag[k].name);
4182 }
4183 putchar(')');
4184 }
4185 putchar('\n');
4186 lib++;
4187 }
4188 }
4189 }
4190
4191 #undef Elf_Lib
4192
4193 static void
dump_section_groups(struct readelf * re)4194 dump_section_groups(struct readelf *re)
4195 {
4196 struct section *s;
4197 const char *symname;
4198 Elf_Data *d;
4199 uint32_t *w;
4200 int i, j, elferr;
4201 size_t n;
4202
4203 for (i = 0; (size_t) i < re->shnum; i++) {
4204 s = &re->sl[i];
4205 if (s->type != SHT_GROUP)
4206 continue;
4207 if (s->link >= re->shnum)
4208 continue;
4209 (void) elf_errno();
4210 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
4211 elferr = elf_errno();
4212 if (elferr != 0)
4213 warnx("elf_getdata failed: %s",
4214 elf_errmsg(elferr));
4215 continue;
4216 }
4217 if (d->d_size <= 0)
4218 continue;
4219
4220 w = d->d_buf;
4221
4222 /* We only support COMDAT section. */
4223 #ifndef GRP_COMDAT
4224 #define GRP_COMDAT 0x1
4225 #endif
4226 if ((*w++ & GRP_COMDAT) == 0)
4227 return;
4228
4229 if (s->entsize == 0)
4230 s->entsize = 4;
4231
4232 symname = get_symbol_name(re, s->link, s->info);
4233 n = s->sz / s->entsize;
4234 if (n-- < 1)
4235 return;
4236
4237 printf("\nCOMDAT group section [%5d] `%s' [%s] contains %ju"
4238 " sections:\n", i, s->name, symname, (uintmax_t)n);
4239 printf(" %-10.10s %s\n", "[Index]", "Name");
4240 for (j = 0; (size_t) j < n; j++, w++) {
4241 if (*w >= re->shnum) {
4242 warnx("invalid section index: %u", *w);
4243 continue;
4244 }
4245 printf(" [%5u] %s\n", *w, re->sl[*w].name);
4246 }
4247 }
4248 }
4249
4250 static uint8_t *
dump_unknown_tag(uint64_t tag,uint8_t * p,uint8_t * pe)4251 dump_unknown_tag(uint64_t tag, uint8_t *p, uint8_t *pe)
4252 {
4253 uint64_t val;
4254
4255 /*
4256 * According to ARM EABI: For tags > 32, even numbered tags have
4257 * a ULEB128 param and odd numbered ones have NUL-terminated
4258 * string param. This rule probably also applies for tags <= 32
4259 * if the object arch is not ARM.
4260 */
4261
4262 printf(" Tag_unknown_%ju: ", (uintmax_t) tag);
4263
4264 if (tag & 1) {
4265 printf("%s\n", (char *) p);
4266 p += strlen((char *) p) + 1;
4267 } else {
4268 val = _decode_uleb128(&p, pe);
4269 printf("%ju\n", (uintmax_t) val);
4270 }
4271
4272 return (p);
4273 }
4274
4275 static uint8_t *
dump_compatibility_tag(uint8_t * p,uint8_t * pe)4276 dump_compatibility_tag(uint8_t *p, uint8_t *pe)
4277 {
4278 uint64_t val;
4279
4280 val = _decode_uleb128(&p, pe);
4281 printf("flag = %ju, vendor = %s\n", (uintmax_t) val, p);
4282 p += strlen((char *) p) + 1;
4283
4284 return (p);
4285 }
4286
4287 static void
dump_arm_attributes(struct readelf * re,uint8_t * p,uint8_t * pe)4288 dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe)
4289 {
4290 uint64_t tag, val;
4291 size_t i;
4292 int found, desc;
4293
4294 (void) re;
4295
4296 while (p < pe) {
4297 tag = _decode_uleb128(&p, pe);
4298 found = desc = 0;
4299 for (i = 0; i < sizeof(aeabi_tags) / sizeof(aeabi_tags[0]);
4300 i++) {
4301 if (tag == aeabi_tags[i].tag) {
4302 found = 1;
4303 printf(" %s: ", aeabi_tags[i].s_tag);
4304 if (aeabi_tags[i].get_desc) {
4305 desc = 1;
4306 val = _decode_uleb128(&p, pe);
4307 printf("%s\n",
4308 aeabi_tags[i].get_desc(val));
4309 }
4310 break;
4311 }
4312 if (tag < aeabi_tags[i].tag)
4313 break;
4314 }
4315 if (!found) {
4316 p = dump_unknown_tag(tag, p, pe);
4317 continue;
4318 }
4319 if (desc)
4320 continue;
4321
4322 switch (tag) {
4323 case 4: /* Tag_CPU_raw_name */
4324 case 5: /* Tag_CPU_name */
4325 case 67: /* Tag_conformance */
4326 printf("%s\n", (char *) p);
4327 p += strlen((char *) p) + 1;
4328 break;
4329 case 32: /* Tag_compatibility */
4330 p = dump_compatibility_tag(p, pe);
4331 break;
4332 case 64: /* Tag_nodefaults */
4333 /* ignored, written as 0. */
4334 (void) _decode_uleb128(&p, pe);
4335 printf("True\n");
4336 break;
4337 case 65: /* Tag_also_compatible_with */
4338 val = _decode_uleb128(&p, pe);
4339 /* Must be Tag_CPU_arch */
4340 if (val != 6) {
4341 printf("unknown\n");
4342 break;
4343 }
4344 val = _decode_uleb128(&p, pe);
4345 printf("%s\n", aeabi_cpu_arch(val));
4346 /* Skip NUL terminator. */
4347 p++;
4348 break;
4349 default:
4350 putchar('\n');
4351 break;
4352 }
4353 }
4354 }
4355
4356 #ifndef Tag_GNU_MIPS_ABI_FP
4357 #define Tag_GNU_MIPS_ABI_FP 4
4358 #endif
4359
4360 static void
dump_mips_attributes(struct readelf * re,uint8_t * p,uint8_t * pe)4361 dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe)
4362 {
4363 uint64_t tag, val;
4364
4365 (void) re;
4366
4367 while (p < pe) {
4368 tag = _decode_uleb128(&p, pe);
4369 switch (tag) {
4370 case Tag_GNU_MIPS_ABI_FP:
4371 val = _decode_uleb128(&p, pe);
4372 printf(" Tag_GNU_MIPS_ABI_FP: %s\n", mips_abi_fp(val));
4373 break;
4374 case 32: /* Tag_compatibility */
4375 p = dump_compatibility_tag(p, pe);
4376 break;
4377 default:
4378 p = dump_unknown_tag(tag, p, pe);
4379 break;
4380 }
4381 }
4382 }
4383
4384 #ifndef Tag_GNU_Power_ABI_FP
4385 #define Tag_GNU_Power_ABI_FP 4
4386 #endif
4387
4388 #ifndef Tag_GNU_Power_ABI_Vector
4389 #define Tag_GNU_Power_ABI_Vector 8
4390 #endif
4391
4392 static void
dump_ppc_attributes(uint8_t * p,uint8_t * pe)4393 dump_ppc_attributes(uint8_t *p, uint8_t *pe)
4394 {
4395 uint64_t tag, val;
4396
4397 while (p < pe) {
4398 tag = _decode_uleb128(&p, pe);
4399 switch (tag) {
4400 case Tag_GNU_Power_ABI_FP:
4401 val = _decode_uleb128(&p, pe);
4402 printf(" Tag_GNU_Power_ABI_FP: %s\n", ppc_abi_fp(val));
4403 break;
4404 case Tag_GNU_Power_ABI_Vector:
4405 val = _decode_uleb128(&p, pe);
4406 printf(" Tag_GNU_Power_ABI_Vector: %s\n",
4407 ppc_abi_vector(val));
4408 break;
4409 case 32: /* Tag_compatibility */
4410 p = dump_compatibility_tag(p, pe);
4411 break;
4412 default:
4413 p = dump_unknown_tag(tag, p, pe);
4414 break;
4415 }
4416 }
4417 }
4418
4419 static void
dump_attributes(struct readelf * re)4420 dump_attributes(struct readelf *re)
4421 {
4422 struct section *s;
4423 Elf_Data *d;
4424 uint8_t *p, *pe, *sp;
4425 size_t len, seclen, nlen, sublen;
4426 uint64_t val;
4427 int tag, i, elferr;
4428
4429 for (i = 0; (size_t) i < re->shnum; i++) {
4430 s = &re->sl[i];
4431 if (s->type != SHT_GNU_ATTRIBUTES &&
4432 (re->ehdr.e_machine != EM_ARM || s->type != SHT_LOPROC + 3))
4433 continue;
4434 (void) elf_errno();
4435 if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4436 elferr = elf_errno();
4437 if (elferr != 0)
4438 warnx("elf_rawdata failed: %s",
4439 elf_errmsg(elferr));
4440 continue;
4441 }
4442 if (d->d_size <= 0)
4443 continue;
4444 p = d->d_buf;
4445 pe = p + d->d_size;
4446 if (*p != 'A') {
4447 printf("Unknown Attribute Section Format: %c\n",
4448 (char) *p);
4449 continue;
4450 }
4451 len = d->d_size - 1;
4452 p++;
4453 while (len > 0) {
4454 if (len < 4) {
4455 warnx("truncated attribute section length");
4456 return;
4457 }
4458 seclen = re->dw_decode(&p, 4);
4459 if (seclen > len) {
4460 warnx("invalid attribute section length");
4461 return;
4462 }
4463 len -= seclen;
4464 nlen = strlen((char *) p) + 1;
4465 if (nlen + 4 > seclen) {
4466 warnx("invalid attribute section name");
4467 return;
4468 }
4469 printf("Attribute Section: %s\n", (char *) p);
4470 p += nlen;
4471 seclen -= nlen + 4;
4472 while (seclen > 0) {
4473 sp = p;
4474 tag = *p++;
4475 sublen = re->dw_decode(&p, 4);
4476 if (sublen > seclen) {
4477 warnx("invalid attribute sub-section"
4478 " length");
4479 return;
4480 }
4481 seclen -= sublen;
4482 printf("%s", top_tag(tag));
4483 if (tag == 2 || tag == 3) {
4484 putchar(':');
4485 for (;;) {
4486 val = _decode_uleb128(&p, pe);
4487 if (val == 0)
4488 break;
4489 printf(" %ju", (uintmax_t) val);
4490 }
4491 }
4492 putchar('\n');
4493 if (re->ehdr.e_machine == EM_ARM &&
4494 s->type == SHT_LOPROC + 3)
4495 dump_arm_attributes(re, p, sp + sublen);
4496 else if (re->ehdr.e_machine == EM_MIPS ||
4497 re->ehdr.e_machine == EM_MIPS_RS3_LE)
4498 dump_mips_attributes(re, p,
4499 sp + sublen);
4500 else if (re->ehdr.e_machine == EM_PPC)
4501 dump_ppc_attributes(p, sp + sublen);
4502 p = sp + sublen;
4503 }
4504 }
4505 }
4506 }
4507
4508 static void
dump_mips_specific_info(struct readelf * re)4509 dump_mips_specific_info(struct readelf *re)
4510 {
4511 struct section *s;
4512 int i;
4513
4514 s = NULL;
4515 for (i = 0; (size_t) i < re->shnum; i++) {
4516 s = &re->sl[i];
4517 if (s->name != NULL && (!strcmp(s->name, ".MIPS.options") ||
4518 (s->type == SHT_MIPS_OPTIONS))) {
4519 dump_mips_options(re, s);
4520 }
4521 }
4522
4523 if (s->name != NULL && (!strcmp(s->name, ".MIPS.abiflags") ||
4524 (s->type == SHT_MIPS_ABIFLAGS)))
4525 dump_mips_abiflags(re, s);
4526
4527 /*
4528 * Dump .reginfo if present (although it will be ignored by an OS if a
4529 * .MIPS.options section is present, according to SGI mips64 spec).
4530 */
4531 for (i = 0; (size_t) i < re->shnum; i++) {
4532 s = &re->sl[i];
4533 if (s->name != NULL && (!strcmp(s->name, ".reginfo") ||
4534 (s->type == SHT_MIPS_REGINFO)))
4535 dump_mips_reginfo(re, s);
4536 }
4537 }
4538
4539 static void
dump_mips_abiflags(struct readelf * re,struct section * s)4540 dump_mips_abiflags(struct readelf *re, struct section *s)
4541 {
4542 Elf_Data *d;
4543 uint8_t *p;
4544 int elferr;
4545 uint32_t isa_ext, ases, flags1, flags2;
4546 uint16_t version;
4547 uint8_t isa_level, isa_rev, gpr_size, cpr1_size, cpr2_size, fp_abi;
4548
4549 if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4550 elferr = elf_errno();
4551 if (elferr != 0)
4552 warnx("elf_rawdata failed: %s",
4553 elf_errmsg(elferr));
4554 return;
4555 }
4556 if (d->d_size != 24) {
4557 warnx("invalid MIPS abiflags section size");
4558 return;
4559 }
4560
4561 p = d->d_buf;
4562 version = re->dw_decode(&p, 2);
4563 printf("MIPS ABI Flags Version: %u", version);
4564 if (version != 0) {
4565 printf(" (unknown)\n\n");
4566 return;
4567 }
4568 printf("\n\n");
4569
4570 isa_level = re->dw_decode(&p, 1);
4571 isa_rev = re->dw_decode(&p, 1);
4572 gpr_size = re->dw_decode(&p, 1);
4573 cpr1_size = re->dw_decode(&p, 1);
4574 cpr2_size = re->dw_decode(&p, 1);
4575 fp_abi = re->dw_decode(&p, 1);
4576 isa_ext = re->dw_decode(&p, 4);
4577 ases = re->dw_decode(&p, 4);
4578 flags1 = re->dw_decode(&p, 4);
4579 flags2 = re->dw_decode(&p, 4);
4580
4581 printf("ISA: ");
4582 if (isa_rev <= 1)
4583 printf("MIPS%u\n", isa_level);
4584 else
4585 printf("MIPS%ur%u\n", isa_level, isa_rev);
4586 printf("GPR size: %d\n", get_mips_register_size(gpr_size));
4587 printf("CPR1 size: %d\n", get_mips_register_size(cpr1_size));
4588 printf("CPR2 size: %d\n", get_mips_register_size(cpr2_size));
4589 printf("FP ABI: ");
4590 switch (fp_abi) {
4591 case 3:
4592 printf("Soft float");
4593 break;
4594 default:
4595 printf("%u", fp_abi);
4596 break;
4597 }
4598 printf("\nISA Extension: %u\n", isa_ext);
4599 printf("ASEs: %u\n", ases);
4600 printf("FLAGS 1: %08x\n", flags1);
4601 printf("FLAGS 2: %08x\n", flags2);
4602 }
4603
4604 static int
get_mips_register_size(uint8_t flag)4605 get_mips_register_size(uint8_t flag)
4606 {
4607 switch (flag) {
4608 case 0: return 0;
4609 case 1: return 32;
4610 case 2: return 64;
4611 case 3: return 128;
4612 default: return -1;
4613 }
4614 }
4615 static void
dump_mips_reginfo(struct readelf * re,struct section * s)4616 dump_mips_reginfo(struct readelf *re, struct section *s)
4617 {
4618 Elf_Data *d;
4619 int elferr, len;
4620
4621 (void) elf_errno();
4622 if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4623 elferr = elf_errno();
4624 if (elferr != 0)
4625 warnx("elf_rawdata failed: %s",
4626 elf_errmsg(elferr));
4627 return;
4628 }
4629 if (d->d_size <= 0)
4630 return;
4631 if (!get_ent_count(s, &len))
4632 return;
4633
4634 printf("\nSection '%s' contains %d entries:\n", s->name, len);
4635 dump_mips_odk_reginfo(re, d->d_buf, d->d_size);
4636 }
4637
4638 static void
dump_mips_options(struct readelf * re,struct section * s)4639 dump_mips_options(struct readelf *re, struct section *s)
4640 {
4641 Elf_Data *d;
4642 uint32_t info;
4643 uint16_t sndx;
4644 uint8_t *p, *pe;
4645 uint8_t kind, size;
4646 int elferr;
4647
4648 (void) elf_errno();
4649 if ((d = elf_rawdata(s->scn, NULL)) == NULL) {
4650 elferr = elf_errno();
4651 if (elferr != 0)
4652 warnx("elf_rawdata failed: %s",
4653 elf_errmsg(elferr));
4654 return;
4655 }
4656 if (d->d_size == 0)
4657 return;
4658
4659 printf("\nSection %s contains:\n", s->name);
4660 p = d->d_buf;
4661 pe = p + d->d_size;
4662 while (p < pe) {
4663 if (pe - p < 8) {
4664 warnx("Truncated MIPS option header");
4665 return;
4666 }
4667 kind = re->dw_decode(&p, 1);
4668 size = re->dw_decode(&p, 1);
4669 sndx = re->dw_decode(&p, 2);
4670 info = re->dw_decode(&p, 4);
4671 if (size < 8 || size - 8 > pe - p) {
4672 warnx("Malformed MIPS option header");
4673 return;
4674 }
4675 size -= 8;
4676 switch (kind) {
4677 case ODK_REGINFO:
4678 dump_mips_odk_reginfo(re, p, size);
4679 break;
4680 case ODK_EXCEPTIONS:
4681 printf(" EXCEPTIONS FPU_MIN: %#x\n",
4682 info & OEX_FPU_MIN);
4683 printf("%11.11s FPU_MAX: %#x\n", "",
4684 info & OEX_FPU_MAX);
4685 dump_mips_option_flags("", mips_exceptions_option,
4686 info);
4687 break;
4688 case ODK_PAD:
4689 printf(" %-10.10s section: %ju\n", "OPAD",
4690 (uintmax_t) sndx);
4691 dump_mips_option_flags("", mips_pad_option, info);
4692 break;
4693 case ODK_HWPATCH:
4694 dump_mips_option_flags("HWPATCH", mips_hwpatch_option,
4695 info);
4696 break;
4697 case ODK_HWAND:
4698 dump_mips_option_flags("HWAND", mips_hwa_option, info);
4699 break;
4700 case ODK_HWOR:
4701 dump_mips_option_flags("HWOR", mips_hwo_option, info);
4702 break;
4703 case ODK_FILL:
4704 printf(" %-10.10s %#jx\n", "FILL", (uintmax_t) info);
4705 break;
4706 case ODK_TAGS:
4707 printf(" %-10.10s\n", "TAGS");
4708 break;
4709 case ODK_GP_GROUP:
4710 printf(" %-10.10s GP group number: %#x\n", "GP_GROUP",
4711 info & 0xFFFF);
4712 if (info & 0x10000)
4713 printf(" %-10.10s GP group is "
4714 "self-contained\n", "");
4715 break;
4716 case ODK_IDENT:
4717 printf(" %-10.10s default GP group number: %#x\n",
4718 "IDENT", info & 0xFFFF);
4719 if (info & 0x10000)
4720 printf(" %-10.10s default GP group is "
4721 "self-contained\n", "");
4722 break;
4723 case ODK_PAGESIZE:
4724 printf(" %-10.10s\n", "PAGESIZE");
4725 break;
4726 default:
4727 break;
4728 }
4729 p += size;
4730 }
4731 }
4732
4733 static void
dump_mips_option_flags(const char * name,struct mips_option * opt,uint64_t info)4734 dump_mips_option_flags(const char *name, struct mips_option *opt, uint64_t info)
4735 {
4736 int first;
4737
4738 first = 1;
4739 for (; opt->desc != NULL; opt++) {
4740 if (info & opt->flag) {
4741 printf(" %-10.10s %s\n", first ? name : "",
4742 opt->desc);
4743 first = 0;
4744 }
4745 }
4746 }
4747
4748 static void
dump_mips_odk_reginfo(struct readelf * re,uint8_t * p,size_t sz)4749 dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz)
4750 {
4751 uint32_t ri_gprmask;
4752 uint32_t ri_cprmask[4];
4753 uint64_t ri_gp_value;
4754 uint8_t *pe;
4755 int i;
4756
4757 pe = p + sz;
4758 while (p < pe) {
4759 ri_gprmask = re->dw_decode(&p, 4);
4760 /* Skip ri_pad padding field for mips64. */
4761 if (re->ec == ELFCLASS64)
4762 re->dw_decode(&p, 4);
4763 for (i = 0; i < 4; i++)
4764 ri_cprmask[i] = re->dw_decode(&p, 4);
4765 if (re->ec == ELFCLASS32)
4766 ri_gp_value = re->dw_decode(&p, 4);
4767 else
4768 ri_gp_value = re->dw_decode(&p, 8);
4769 printf(" %s ", option_kind(ODK_REGINFO));
4770 printf("ri_gprmask: 0x%08jx\n", (uintmax_t) ri_gprmask);
4771 for (i = 0; i < 4; i++)
4772 printf("%11.11s ri_cprmask[%d]: 0x%08jx\n", "", i,
4773 (uintmax_t) ri_cprmask[i]);
4774 printf("%12.12s", "");
4775 printf("ri_gp_value: %#jx\n", (uintmax_t) ri_gp_value);
4776 }
4777 }
4778
4779 static void
dump_arch_specific_info(struct readelf * re)4780 dump_arch_specific_info(struct readelf *re)
4781 {
4782
4783 dump_liblist(re);
4784 dump_attributes(re);
4785
4786 switch (re->ehdr.e_machine) {
4787 case EM_MIPS:
4788 case EM_MIPS_RS3_LE:
4789 dump_mips_specific_info(re);
4790 default:
4791 break;
4792 }
4793 }
4794
4795 static const char *
dwarf_regname(struct readelf * re,unsigned int num)4796 dwarf_regname(struct readelf *re, unsigned int num)
4797 {
4798 static char rx[32];
4799 const char *rn;
4800
4801 if ((rn = dwarf_reg(re->ehdr.e_machine, num)) != NULL)
4802 return (rn);
4803
4804 snprintf(rx, sizeof(rx), "r%u", num);
4805
4806 return (rx);
4807 }
4808
4809 static void
dump_dwarf_line(struct readelf * re)4810 dump_dwarf_line(struct readelf *re)
4811 {
4812 struct section *s;
4813 Dwarf_Die die;
4814 Dwarf_Error de;
4815 Dwarf_Half tag, version, pointer_size;
4816 Dwarf_Unsigned offset, endoff, length, hdrlen, dirndx, mtime, fsize;
4817 Dwarf_Small minlen, defstmt, lrange, opbase, oplen;
4818 Elf_Data *d;
4819 char *pn;
4820 uint64_t address, file, line, column, isa, opsize, udelta;
4821 int64_t sdelta;
4822 uint8_t *p, *pe;
4823 int8_t lbase;
4824 int i, is_stmt, dwarf_size, elferr, ret;
4825
4826 printf("\nDump of debug contents of section .debug_line:\n");
4827
4828 s = NULL;
4829 for (i = 0; (size_t) i < re->shnum; i++) {
4830 s = &re->sl[i];
4831 if (s->name != NULL && !strcmp(s->name, ".debug_line"))
4832 break;
4833 }
4834 if ((size_t) i >= re->shnum)
4835 return;
4836
4837 (void) elf_errno();
4838 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
4839 elferr = elf_errno();
4840 if (elferr != 0)
4841 warnx("elf_getdata failed: %s", elf_errmsg(-1));
4842 return;
4843 }
4844 if (d->d_size <= 0)
4845 return;
4846
4847 while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
4848 NULL, &de)) == DW_DLV_OK) {
4849 die = NULL;
4850 while (dwarf_siblingof(re->dbg, die, &die, &de) == DW_DLV_OK) {
4851 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
4852 warnx("dwarf_tag failed: %s",
4853 dwarf_errmsg(de));
4854 return;
4855 }
4856 /* XXX: What about DW_TAG_partial_unit? */
4857 if (tag == DW_TAG_compile_unit)
4858 break;
4859 }
4860 if (die == NULL) {
4861 warnx("could not find DW_TAG_compile_unit die");
4862 return;
4863 }
4864 if (dwarf_attrval_unsigned(die, DW_AT_stmt_list, &offset,
4865 &de) != DW_DLV_OK)
4866 continue;
4867
4868 length = re->dw_read(d, &offset, 4);
4869 if (length == 0xffffffff) {
4870 dwarf_size = 8;
4871 length = re->dw_read(d, &offset, 8);
4872 } else
4873 dwarf_size = 4;
4874
4875 if (length > d->d_size - offset) {
4876 warnx("invalid .dwarf_line section");
4877 continue;
4878 }
4879
4880 endoff = offset + length;
4881 pe = (uint8_t *) d->d_buf + endoff;
4882 version = re->dw_read(d, &offset, 2);
4883 hdrlen = re->dw_read(d, &offset, dwarf_size);
4884 minlen = re->dw_read(d, &offset, 1);
4885 defstmt = re->dw_read(d, &offset, 1);
4886 lbase = re->dw_read(d, &offset, 1);
4887 lrange = re->dw_read(d, &offset, 1);
4888 opbase = re->dw_read(d, &offset, 1);
4889
4890 printf("\n");
4891 printf(" Length:\t\t\t%ju\n", (uintmax_t) length);
4892 printf(" DWARF version:\t\t%u\n", version);
4893 printf(" Prologue Length:\t\t%ju\n", (uintmax_t) hdrlen);
4894 printf(" Minimum Instruction Length:\t%u\n", minlen);
4895 printf(" Initial value of 'is_stmt':\t%u\n", defstmt);
4896 printf(" Line Base:\t\t\t%d\n", lbase);
4897 printf(" Line Range:\t\t\t%u\n", lrange);
4898 printf(" Opcode Base:\t\t\t%u\n", opbase);
4899 (void) dwarf_get_address_size(re->dbg, &pointer_size, &de);
4900 printf(" (Pointer size:\t\t%u)\n", pointer_size);
4901
4902 printf("\n");
4903 printf(" Opcodes:\n");
4904 for (i = 1; i < opbase; i++) {
4905 oplen = re->dw_read(d, &offset, 1);
4906 printf(" Opcode %d has %u args\n", i, oplen);
4907 }
4908
4909 printf("\n");
4910 printf(" The Directory Table:\n");
4911 p = (uint8_t *) d->d_buf + offset;
4912 while (*p != '\0') {
4913 printf(" %s\n", (char *) p);
4914 p += strlen((char *) p) + 1;
4915 }
4916
4917 p++;
4918 printf("\n");
4919 printf(" The File Name Table:\n");
4920 printf(" Entry\tDir\tTime\tSize\tName\n");
4921 i = 0;
4922 while (*p != '\0') {
4923 i++;
4924 pn = (char *) p;
4925 p += strlen(pn) + 1;
4926 dirndx = _decode_uleb128(&p, pe);
4927 mtime = _decode_uleb128(&p, pe);
4928 fsize = _decode_uleb128(&p, pe);
4929 printf(" %d\t%ju\t%ju\t%ju\t%s\n", i,
4930 (uintmax_t) dirndx, (uintmax_t) mtime,
4931 (uintmax_t) fsize, pn);
4932 }
4933
4934 #define RESET_REGISTERS \
4935 do { \
4936 address = 0; \
4937 file = 1; \
4938 line = 1; \
4939 column = 0; \
4940 is_stmt = defstmt; \
4941 } while(0)
4942
4943 #define LINE(x) (lbase + (((x) - opbase) % lrange))
4944 #define ADDRESS(x) ((((x) - opbase) / lrange) * minlen)
4945
4946 p++;
4947 printf("\n");
4948 printf(" Line Number Statements:\n");
4949
4950 RESET_REGISTERS;
4951
4952 while (p < pe) {
4953
4954 if (*p == 0) {
4955 /*
4956 * Extended Opcodes.
4957 */
4958 p++;
4959 opsize = _decode_uleb128(&p, pe);
4960 printf(" Extended opcode %u: ", *p);
4961 switch (*p) {
4962 case DW_LNE_end_sequence:
4963 p++;
4964 RESET_REGISTERS;
4965 printf("End of Sequence\n");
4966 break;
4967 case DW_LNE_set_address:
4968 p++;
4969 address = re->dw_decode(&p,
4970 pointer_size);
4971 printf("set Address to %#jx\n",
4972 (uintmax_t) address);
4973 break;
4974 case DW_LNE_define_file:
4975 p++;
4976 pn = (char *) p;
4977 p += strlen(pn) + 1;
4978 dirndx = _decode_uleb128(&p, pe);
4979 mtime = _decode_uleb128(&p, pe);
4980 fsize = _decode_uleb128(&p, pe);
4981 printf("define new file: %s\n", pn);
4982 break;
4983 default:
4984 /* Unrecognized extened opcodes. */
4985 p += opsize;
4986 printf("unknown opcode\n");
4987 }
4988 } else if (*p > 0 && *p < opbase) {
4989 /*
4990 * Standard Opcodes.
4991 */
4992 switch(*p++) {
4993 case DW_LNS_copy:
4994 printf(" Copy\n");
4995 break;
4996 case DW_LNS_advance_pc:
4997 udelta = _decode_uleb128(&p, pe) *
4998 minlen;
4999 address += udelta;
5000 printf(" Advance PC by %ju to %#jx\n",
5001 (uintmax_t) udelta,
5002 (uintmax_t) address);
5003 break;
5004 case DW_LNS_advance_line:
5005 sdelta = _decode_sleb128(&p, pe);
5006 line += sdelta;
5007 printf(" Advance Line by %jd to %ju\n",
5008 (intmax_t) sdelta,
5009 (uintmax_t) line);
5010 break;
5011 case DW_LNS_set_file:
5012 file = _decode_uleb128(&p, pe);
5013 printf(" Set File to %ju\n",
5014 (uintmax_t) file);
5015 break;
5016 case DW_LNS_set_column:
5017 column = _decode_uleb128(&p, pe);
5018 printf(" Set Column to %ju\n",
5019 (uintmax_t) column);
5020 break;
5021 case DW_LNS_negate_stmt:
5022 is_stmt = !is_stmt;
5023 printf(" Set is_stmt to %d\n", is_stmt);
5024 break;
5025 case DW_LNS_set_basic_block:
5026 printf(" Set basic block flag\n");
5027 break;
5028 case DW_LNS_const_add_pc:
5029 address += ADDRESS(255);
5030 printf(" Advance PC by constant %ju"
5031 " to %#jx\n",
5032 (uintmax_t) ADDRESS(255),
5033 (uintmax_t) address);
5034 break;
5035 case DW_LNS_fixed_advance_pc:
5036 udelta = re->dw_decode(&p, 2);
5037 address += udelta;
5038 printf(" Advance PC by fixed value "
5039 "%ju to %#jx\n",
5040 (uintmax_t) udelta,
5041 (uintmax_t) address);
5042 break;
5043 case DW_LNS_set_prologue_end:
5044 printf(" Set prologue end flag\n");
5045 break;
5046 case DW_LNS_set_epilogue_begin:
5047 printf(" Set epilogue begin flag\n");
5048 break;
5049 case DW_LNS_set_isa:
5050 isa = _decode_uleb128(&p, pe);
5051 printf(" Set isa to %ju\n",
5052 (uintmax_t) isa);
5053 break;
5054 default:
5055 /* Unrecognized extended opcodes. */
5056 printf(" Unknown extended opcode %u\n",
5057 *(p - 1));
5058 break;
5059 }
5060
5061 } else {
5062 /*
5063 * Special Opcodes.
5064 */
5065 line += LINE(*p);
5066 address += ADDRESS(*p);
5067 printf(" Special opcode %u: advance Address "
5068 "by %ju to %#jx and Line by %jd to %ju\n",
5069 *p - opbase, (uintmax_t) ADDRESS(*p),
5070 (uintmax_t) address, (intmax_t) LINE(*p),
5071 (uintmax_t) line);
5072 p++;
5073 }
5074
5075
5076 }
5077 }
5078 if (ret == DW_DLV_ERROR)
5079 warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
5080
5081 #undef RESET_REGISTERS
5082 #undef LINE
5083 #undef ADDRESS
5084 }
5085
5086 static void
dump_dwarf_line_decoded(struct readelf * re)5087 dump_dwarf_line_decoded(struct readelf *re)
5088 {
5089 Dwarf_Die die;
5090 Dwarf_Line *linebuf, ln;
5091 Dwarf_Addr lineaddr;
5092 Dwarf_Signed linecount, srccount;
5093 Dwarf_Unsigned lineno, fn;
5094 Dwarf_Error de;
5095 const char *dir, *file;
5096 char **srcfiles;
5097 int i, ret;
5098
5099 printf("Decoded dump of debug contents of section .debug_line:\n\n");
5100 while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
5101 NULL, &de)) == DW_DLV_OK) {
5102 if (dwarf_siblingof(re->dbg, NULL, &die, &de) != DW_DLV_OK)
5103 continue;
5104 if (dwarf_attrval_string(die, DW_AT_name, &file, &de) !=
5105 DW_DLV_OK)
5106 file = NULL;
5107 if (dwarf_attrval_string(die, DW_AT_comp_dir, &dir, &de) !=
5108 DW_DLV_OK)
5109 dir = NULL;
5110 printf("CU: ");
5111 if (dir && file && file[0] != '/')
5112 printf("%s/", dir);
5113 if (file)
5114 printf("%s", file);
5115 putchar('\n');
5116 printf("%-37s %11s %s\n", "Filename", "Line Number",
5117 "Starting Address");
5118 if (dwarf_srclines(die, &linebuf, &linecount, &de) != DW_DLV_OK)
5119 continue;
5120 if (dwarf_srcfiles(die, &srcfiles, &srccount, &de) != DW_DLV_OK)
5121 continue;
5122 for (i = 0; i < linecount; i++) {
5123 ln = linebuf[i];
5124 if (dwarf_line_srcfileno(ln, &fn, &de) != DW_DLV_OK)
5125 continue;
5126 if (dwarf_lineno(ln, &lineno, &de) != DW_DLV_OK)
5127 continue;
5128 if (dwarf_lineaddr(ln, &lineaddr, &de) != DW_DLV_OK)
5129 continue;
5130 printf("%-37s %11ju %#18jx\n",
5131 basename(srcfiles[fn - 1]), (uintmax_t) lineno,
5132 (uintmax_t) lineaddr);
5133 }
5134 putchar('\n');
5135 }
5136 }
5137
5138 static void
dump_dwarf_die(struct readelf * re,Dwarf_Die die,int level)5139 dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level)
5140 {
5141 Dwarf_Attribute *attr_list;
5142 Dwarf_Die ret_die;
5143 Dwarf_Off dieoff, cuoff, culen, attroff;
5144 Dwarf_Unsigned ate, lang, v_udata, v_sig;
5145 Dwarf_Signed attr_count, v_sdata;
5146 Dwarf_Off v_off;
5147 Dwarf_Addr v_addr;
5148 Dwarf_Half tag, attr, form;
5149 Dwarf_Block *v_block;
5150 Dwarf_Bool v_bool, is_info;
5151 Dwarf_Sig8 v_sig8;
5152 Dwarf_Error de;
5153 Dwarf_Ptr v_expr;
5154 const char *tag_str, *attr_str, *ate_str, *lang_str;
5155 char unk_tag[32], unk_attr[32];
5156 char *v_str;
5157 uint8_t *b, *p;
5158 int i, j, abc, ret;
5159
5160 if (dwarf_dieoffset(die, &dieoff, &de) != DW_DLV_OK) {
5161 warnx("dwarf_dieoffset failed: %s", dwarf_errmsg(de));
5162 goto cont_search;
5163 }
5164
5165 printf(" <%d><%jx>: ", level, (uintmax_t) dieoff);
5166
5167 if (dwarf_die_CU_offset_range(die, &cuoff, &culen, &de) != DW_DLV_OK) {
5168 warnx("dwarf_die_CU_offset_range failed: %s",
5169 dwarf_errmsg(de));
5170 cuoff = 0;
5171 }
5172
5173 abc = dwarf_die_abbrev_code(die);
5174 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
5175 warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
5176 goto cont_search;
5177 }
5178 if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) {
5179 snprintf(unk_tag, sizeof(unk_tag), "[Unknown Tag: %#x]", tag);
5180 tag_str = unk_tag;
5181 }
5182
5183 printf("Abbrev Number: %d (%s)\n", abc, tag_str);
5184
5185 if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
5186 DW_DLV_OK) {
5187 if (ret == DW_DLV_ERROR)
5188 warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
5189 goto cont_search;
5190 }
5191
5192 for (i = 0; i < attr_count; i++) {
5193 if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) {
5194 warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
5195 continue;
5196 }
5197 if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
5198 warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
5199 continue;
5200 }
5201 if (dwarf_get_AT_name(attr, &attr_str) != DW_DLV_OK) {
5202 snprintf(unk_attr, sizeof(unk_attr),
5203 "[Unknown AT: %#x]", attr);
5204 attr_str = unk_attr;
5205 }
5206 if (dwarf_attroffset(attr_list[i], &attroff, &de) !=
5207 DW_DLV_OK) {
5208 warnx("dwarf_attroffset failed: %s", dwarf_errmsg(de));
5209 attroff = 0;
5210 }
5211 printf(" <%jx> %-18s: ", (uintmax_t) attroff, attr_str);
5212 switch (form) {
5213 case DW_FORM_ref_addr:
5214 case DW_FORM_sec_offset:
5215 if (dwarf_global_formref(attr_list[i], &v_off, &de) !=
5216 DW_DLV_OK) {
5217 warnx("dwarf_global_formref failed: %s",
5218 dwarf_errmsg(de));
5219 continue;
5220 }
5221 if (form == DW_FORM_ref_addr)
5222 printf("<0x%jx>", (uintmax_t) v_off);
5223 else
5224 printf("0x%jx", (uintmax_t) v_off);
5225 break;
5226
5227 case DW_FORM_ref1:
5228 case DW_FORM_ref2:
5229 case DW_FORM_ref4:
5230 case DW_FORM_ref8:
5231 case DW_FORM_ref_udata:
5232 if (dwarf_formref(attr_list[i], &v_off, &de) !=
5233 DW_DLV_OK) {
5234 warnx("dwarf_formref failed: %s",
5235 dwarf_errmsg(de));
5236 continue;
5237 }
5238 v_off += cuoff;
5239 printf("<0x%jx>", (uintmax_t) v_off);
5240 break;
5241
5242 case DW_FORM_addr:
5243 if (dwarf_formaddr(attr_list[i], &v_addr, &de) !=
5244 DW_DLV_OK) {
5245 warnx("dwarf_formaddr failed: %s",
5246 dwarf_errmsg(de));
5247 continue;
5248 }
5249 printf("%#jx", (uintmax_t) v_addr);
5250 break;
5251
5252 case DW_FORM_data1:
5253 case DW_FORM_data2:
5254 case DW_FORM_data4:
5255 case DW_FORM_data8:
5256 case DW_FORM_udata:
5257 if (dwarf_formudata(attr_list[i], &v_udata, &de) !=
5258 DW_DLV_OK) {
5259 warnx("dwarf_formudata failed: %s",
5260 dwarf_errmsg(de));
5261 continue;
5262 }
5263 if (attr == DW_AT_high_pc)
5264 printf("0x%jx", (uintmax_t) v_udata);
5265 else
5266 printf("%ju", (uintmax_t) v_udata);
5267 break;
5268
5269 case DW_FORM_sdata:
5270 if (dwarf_formsdata(attr_list[i], &v_sdata, &de) !=
5271 DW_DLV_OK) {
5272 warnx("dwarf_formudata failed: %s",
5273 dwarf_errmsg(de));
5274 continue;
5275 }
5276 printf("%jd", (intmax_t) v_sdata);
5277 break;
5278
5279 case DW_FORM_flag:
5280 if (dwarf_formflag(attr_list[i], &v_bool, &de) !=
5281 DW_DLV_OK) {
5282 warnx("dwarf_formflag failed: %s",
5283 dwarf_errmsg(de));
5284 continue;
5285 }
5286 printf("%jd", (intmax_t) v_bool);
5287 break;
5288
5289 case DW_FORM_flag_present:
5290 putchar('1');
5291 break;
5292
5293 case DW_FORM_string:
5294 case DW_FORM_strp:
5295 if (dwarf_formstring(attr_list[i], &v_str, &de) !=
5296 DW_DLV_OK) {
5297 warnx("dwarf_formstring failed: %s",
5298 dwarf_errmsg(de));
5299 continue;
5300 }
5301 if (form == DW_FORM_string)
5302 printf("%s", v_str);
5303 else
5304 printf("(indirect string) %s", v_str);
5305 break;
5306
5307 case DW_FORM_block:
5308 case DW_FORM_block1:
5309 case DW_FORM_block2:
5310 case DW_FORM_block4:
5311 if (dwarf_formblock(attr_list[i], &v_block, &de) !=
5312 DW_DLV_OK) {
5313 warnx("dwarf_formblock failed: %s",
5314 dwarf_errmsg(de));
5315 continue;
5316 }
5317 printf("%ju byte block:", (uintmax_t) v_block->bl_len);
5318 b = v_block->bl_data;
5319 for (j = 0; (Dwarf_Unsigned) j < v_block->bl_len; j++)
5320 printf(" %x", b[j]);
5321 printf("\t(");
5322 dump_dwarf_block(re, v_block->bl_data, v_block->bl_len);
5323 putchar(')');
5324 break;
5325
5326 case DW_FORM_exprloc:
5327 if (dwarf_formexprloc(attr_list[i], &v_udata, &v_expr,
5328 &de) != DW_DLV_OK) {
5329 warnx("dwarf_formexprloc failed: %s",
5330 dwarf_errmsg(de));
5331 continue;
5332 }
5333 printf("%ju byte block:", (uintmax_t) v_udata);
5334 b = v_expr;
5335 for (j = 0; (Dwarf_Unsigned) j < v_udata; j++)
5336 printf(" %x", b[j]);
5337 printf("\t(");
5338 dump_dwarf_block(re, v_expr, v_udata);
5339 putchar(')');
5340 break;
5341
5342 case DW_FORM_ref_sig8:
5343 if (dwarf_formsig8(attr_list[i], &v_sig8, &de) !=
5344 DW_DLV_OK) {
5345 warnx("dwarf_formsig8 failed: %s",
5346 dwarf_errmsg(de));
5347 continue;
5348 }
5349 p = (uint8_t *)(uintptr_t) &v_sig8.signature[0];
5350 v_sig = re->dw_decode(&p, 8);
5351 printf("signature: 0x%jx", (uintmax_t) v_sig);
5352 }
5353 switch (attr) {
5354 case DW_AT_encoding:
5355 if (dwarf_attrval_unsigned(die, attr, &ate, &de) !=
5356 DW_DLV_OK)
5357 break;
5358 if (dwarf_get_ATE_name(ate, &ate_str) != DW_DLV_OK)
5359 ate_str = "DW_ATE_UNKNOWN";
5360 printf("\t(%s)", &ate_str[strlen("DW_ATE_")]);
5361 break;
5362
5363 case DW_AT_language:
5364 if (dwarf_attrval_unsigned(die, attr, &lang, &de) !=
5365 DW_DLV_OK)
5366 break;
5367 if (dwarf_get_LANG_name(lang, &lang_str) != DW_DLV_OK)
5368 break;
5369 printf("\t(%s)", &lang_str[strlen("DW_LANG_")]);
5370 break;
5371
5372 case DW_AT_location:
5373 case DW_AT_string_length:
5374 case DW_AT_return_addr:
5375 case DW_AT_data_member_location:
5376 case DW_AT_frame_base:
5377 case DW_AT_segment:
5378 case DW_AT_static_link:
5379 case DW_AT_use_location:
5380 case DW_AT_vtable_elem_location:
5381 switch (form) {
5382 case DW_FORM_data4:
5383 case DW_FORM_data8:
5384 case DW_FORM_sec_offset:
5385 printf("\t(location list)");
5386 break;
5387 default:
5388 break;
5389 }
5390
5391 default:
5392 break;
5393 }
5394 putchar('\n');
5395 }
5396
5397
5398 cont_search:
5399 /* Search children. */
5400 ret = dwarf_child(die, &ret_die, &de);
5401 if (ret == DW_DLV_ERROR)
5402 warnx("dwarf_child: %s", dwarf_errmsg(de));
5403 else if (ret == DW_DLV_OK)
5404 dump_dwarf_die(re, ret_die, level + 1);
5405
5406 /* Search sibling. */
5407 is_info = dwarf_get_die_infotypes_flag(die);
5408 ret = dwarf_siblingof_b(re->dbg, die, &ret_die, is_info, &de);
5409 if (ret == DW_DLV_ERROR)
5410 warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
5411 else if (ret == DW_DLV_OK)
5412 dump_dwarf_die(re, ret_die, level);
5413
5414 dwarf_dealloc(re->dbg, die, DW_DLA_DIE);
5415 }
5416
5417 static void
set_cu_context(struct readelf * re,Dwarf_Half psize,Dwarf_Half osize,Dwarf_Half ver)5418 set_cu_context(struct readelf *re, Dwarf_Half psize, Dwarf_Half osize,
5419 Dwarf_Half ver)
5420 {
5421
5422 re->cu_psize = psize;
5423 re->cu_osize = osize;
5424 re->cu_ver = ver;
5425 }
5426
5427 static void
dump_dwarf_info(struct readelf * re,Dwarf_Bool is_info)5428 dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info)
5429 {
5430 struct section *s;
5431 Dwarf_Die die;
5432 Dwarf_Error de;
5433 Dwarf_Half tag, version, pointer_size, off_size;
5434 Dwarf_Off cu_offset, cu_length;
5435 Dwarf_Off aboff;
5436 Dwarf_Unsigned typeoff;
5437 Dwarf_Sig8 sig8;
5438 Dwarf_Unsigned sig;
5439 uint8_t *p;
5440 const char *sn;
5441 int i, ret;
5442
5443 sn = is_info ? ".debug_info" : ".debug_types";
5444
5445 s = NULL;
5446 for (i = 0; (size_t) i < re->shnum; i++) {
5447 s = &re->sl[i];
5448 if (s->name != NULL && !strcmp(s->name, sn))
5449 break;
5450 }
5451 if ((size_t) i >= re->shnum)
5452 return;
5453
5454 do {
5455 printf("\nDump of debug contents of section %s:\n", sn);
5456
5457 while ((ret = dwarf_next_cu_header_c(re->dbg, is_info, NULL,
5458 &version, &aboff, &pointer_size, &off_size, NULL, &sig8,
5459 &typeoff, NULL, &de)) == DW_DLV_OK) {
5460 set_cu_context(re, pointer_size, off_size, version);
5461 die = NULL;
5462 while (dwarf_siblingof_b(re->dbg, die, &die, is_info,
5463 &de) == DW_DLV_OK) {
5464 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
5465 warnx("dwarf_tag failed: %s",
5466 dwarf_errmsg(de));
5467 continue;
5468 }
5469 /* XXX: What about DW_TAG_partial_unit? */
5470 if ((is_info && tag == DW_TAG_compile_unit) ||
5471 (!is_info && tag == DW_TAG_type_unit))
5472 break;
5473 }
5474 if (die == NULL && is_info) {
5475 warnx("could not find DW_TAG_compile_unit "
5476 "die");
5477 continue;
5478 } else if (die == NULL && !is_info) {
5479 warnx("could not find DW_TAG_type_unit die");
5480 continue;
5481 }
5482
5483 if (dwarf_die_CU_offset_range(die, &cu_offset,
5484 &cu_length, &de) != DW_DLV_OK) {
5485 warnx("dwarf_die_CU_offset failed: %s",
5486 dwarf_errmsg(de));
5487 continue;
5488 }
5489
5490 cu_length -= off_size == 4 ? 4 : 12;
5491
5492 sig = 0;
5493 if (!is_info) {
5494 p = (uint8_t *)(uintptr_t) &sig8.signature[0];
5495 sig = re->dw_decode(&p, 8);
5496 }
5497
5498 printf("\n Type Unit @ offset 0x%jx:\n",
5499 (uintmax_t) cu_offset);
5500 printf(" Length:\t\t%#jx (%d-bit)\n",
5501 (uintmax_t) cu_length, off_size == 4 ? 32 : 64);
5502 printf(" Version:\t\t%u\n", version);
5503 printf(" Abbrev Offset:\t0x%jx\n",
5504 (uintmax_t) aboff);
5505 printf(" Pointer Size:\t%u\n", pointer_size);
5506 if (!is_info) {
5507 printf(" Signature:\t\t0x%016jx\n",
5508 (uintmax_t) sig);
5509 printf(" Type Offset:\t0x%jx\n",
5510 (uintmax_t) typeoff);
5511 }
5512
5513 dump_dwarf_die(re, die, 0);
5514 }
5515 if (ret == DW_DLV_ERROR)
5516 warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
5517 if (is_info)
5518 break;
5519 } while (dwarf_next_types_section(re->dbg, &de) == DW_DLV_OK);
5520 }
5521
5522 static void
dump_dwarf_abbrev(struct readelf * re)5523 dump_dwarf_abbrev(struct readelf *re)
5524 {
5525 Dwarf_Abbrev ab;
5526 Dwarf_Off aboff, atoff;
5527 Dwarf_Unsigned length, attr_count;
5528 Dwarf_Signed flag, form;
5529 Dwarf_Half tag, attr;
5530 Dwarf_Error de;
5531 const char *tag_str, *attr_str, *form_str;
5532 char unk_tag[32], unk_attr[32], unk_form[32];
5533 int i, j, ret;
5534
5535 printf("\nContents of section .debug_abbrev:\n\n");
5536
5537 while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, &aboff,
5538 NULL, NULL, &de)) == DW_DLV_OK) {
5539 printf(" Number TAG\n");
5540 i = 0;
5541 while ((ret = dwarf_get_abbrev(re->dbg, aboff, &ab, &length,
5542 &attr_count, &de)) == DW_DLV_OK) {
5543 if (length == 1) {
5544 dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV);
5545 break;
5546 }
5547 aboff += length;
5548 printf("%4d", ++i);
5549 if (dwarf_get_abbrev_tag(ab, &tag, &de) != DW_DLV_OK) {
5550 warnx("dwarf_get_abbrev_tag failed: %s",
5551 dwarf_errmsg(de));
5552 goto next_abbrev;
5553 }
5554 if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) {
5555 snprintf(unk_tag, sizeof(unk_tag),
5556 "[Unknown Tag: %#x]", tag);
5557 tag_str = unk_tag;
5558 }
5559 if (dwarf_get_abbrev_children_flag(ab, &flag, &de) !=
5560 DW_DLV_OK) {
5561 warnx("dwarf_get_abbrev_children_flag failed:"
5562 " %s", dwarf_errmsg(de));
5563 goto next_abbrev;
5564 }
5565 printf(" %s %s\n", tag_str,
5566 flag ? "[has children]" : "[no children]");
5567 for (j = 0; (Dwarf_Unsigned) j < attr_count; j++) {
5568 if (dwarf_get_abbrev_entry(ab, (Dwarf_Signed) j,
5569 &attr, &form, &atoff, &de) != DW_DLV_OK) {
5570 warnx("dwarf_get_abbrev_entry failed:"
5571 " %s", dwarf_errmsg(de));
5572 continue;
5573 }
5574 if (dwarf_get_AT_name(attr, &attr_str) !=
5575 DW_DLV_OK) {
5576 snprintf(unk_attr, sizeof(unk_attr),
5577 "[Unknown AT: %#x]", attr);
5578 attr_str = unk_attr;
5579 }
5580 if (dwarf_get_FORM_name(form, &form_str) !=
5581 DW_DLV_OK) {
5582 snprintf(unk_form, sizeof(unk_form),
5583 "[Unknown Form: %#x]",
5584 (Dwarf_Half) form);
5585 form_str = unk_form;
5586 }
5587 printf(" %-18s %s\n", attr_str, form_str);
5588 }
5589 next_abbrev:
5590 dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV);
5591 }
5592 if (ret != DW_DLV_OK)
5593 warnx("dwarf_get_abbrev: %s", dwarf_errmsg(de));
5594 }
5595 if (ret == DW_DLV_ERROR)
5596 warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
5597 }
5598
5599 static void
dump_dwarf_pubnames(struct readelf * re)5600 dump_dwarf_pubnames(struct readelf *re)
5601 {
5602 struct section *s;
5603 Dwarf_Off die_off;
5604 Dwarf_Unsigned offset, length, nt_cu_offset, nt_cu_length;
5605 Dwarf_Signed cnt;
5606 Dwarf_Global *globs;
5607 Dwarf_Half nt_version;
5608 Dwarf_Error de;
5609 Elf_Data *d;
5610 char *glob_name;
5611 int i, dwarf_size, elferr;
5612
5613 printf("\nContents of the .debug_pubnames section:\n");
5614
5615 s = NULL;
5616 for (i = 0; (size_t) i < re->shnum; i++) {
5617 s = &re->sl[i];
5618 if (s->name != NULL && !strcmp(s->name, ".debug_pubnames"))
5619 break;
5620 }
5621 if ((size_t) i >= re->shnum)
5622 return;
5623
5624 (void) elf_errno();
5625 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
5626 elferr = elf_errno();
5627 if (elferr != 0)
5628 warnx("elf_getdata failed: %s", elf_errmsg(-1));
5629 return;
5630 }
5631 if (d->d_size <= 0)
5632 return;
5633
5634 /* Read in .debug_pubnames section table header. */
5635 offset = 0;
5636 length = re->dw_read(d, &offset, 4);
5637 if (length == 0xffffffff) {
5638 dwarf_size = 8;
5639 length = re->dw_read(d, &offset, 8);
5640 } else
5641 dwarf_size = 4;
5642
5643 if (length > d->d_size - offset) {
5644 warnx("invalid .dwarf_pubnames section");
5645 return;
5646 }
5647
5648 nt_version = re->dw_read(d, &offset, 2);
5649 nt_cu_offset = re->dw_read(d, &offset, dwarf_size);
5650 nt_cu_length = re->dw_read(d, &offset, dwarf_size);
5651 printf(" Length:\t\t\t\t%ju\n", (uintmax_t) length);
5652 printf(" Version:\t\t\t\t%u\n", nt_version);
5653 printf(" Offset into .debug_info section:\t%ju\n",
5654 (uintmax_t) nt_cu_offset);
5655 printf(" Size of area in .debug_info section:\t%ju\n",
5656 (uintmax_t) nt_cu_length);
5657
5658 if (dwarf_get_globals(re->dbg, &globs, &cnt, &de) != DW_DLV_OK) {
5659 warnx("dwarf_get_globals failed: %s", dwarf_errmsg(de));
5660 return;
5661 }
5662
5663 printf("\n Offset Name\n");
5664 for (i = 0; i < cnt; i++) {
5665 if (dwarf_globname(globs[i], &glob_name, &de) != DW_DLV_OK) {
5666 warnx("dwarf_globname failed: %s", dwarf_errmsg(de));
5667 continue;
5668 }
5669 if (dwarf_global_die_offset(globs[i], &die_off, &de) !=
5670 DW_DLV_OK) {
5671 warnx("dwarf_global_die_offset failed: %s",
5672 dwarf_errmsg(de));
5673 continue;
5674 }
5675 printf(" %-11ju %s\n", (uintmax_t) die_off, glob_name);
5676 }
5677 }
5678
5679 static void
dump_dwarf_aranges(struct readelf * re)5680 dump_dwarf_aranges(struct readelf *re)
5681 {
5682 struct section *s;
5683 Dwarf_Arange *aranges;
5684 Dwarf_Addr start;
5685 Dwarf_Unsigned offset, length, as_cu_offset;
5686 Dwarf_Off die_off;
5687 Dwarf_Signed cnt;
5688 Dwarf_Half as_version, as_addrsz, as_segsz;
5689 Dwarf_Error de;
5690 Elf_Data *d;
5691 int i, dwarf_size, elferr;
5692
5693 printf("\nContents of section .debug_aranges:\n");
5694
5695 s = NULL;
5696 for (i = 0; (size_t) i < re->shnum; i++) {
5697 s = &re->sl[i];
5698 if (s->name != NULL && !strcmp(s->name, ".debug_aranges"))
5699 break;
5700 }
5701 if ((size_t) i >= re->shnum)
5702 return;
5703
5704 (void) elf_errno();
5705 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
5706 elferr = elf_errno();
5707 if (elferr != 0)
5708 warnx("elf_getdata failed: %s", elf_errmsg(-1));
5709 return;
5710 }
5711 if (d->d_size <= 0)
5712 return;
5713
5714 /* Read in the .debug_aranges section table header. */
5715 offset = 0;
5716 length = re->dw_read(d, &offset, 4);
5717 if (length == 0xffffffff) {
5718 dwarf_size = 8;
5719 length = re->dw_read(d, &offset, 8);
5720 } else
5721 dwarf_size = 4;
5722
5723 if (length > d->d_size - offset) {
5724 warnx("invalid .dwarf_aranges section");
5725 return;
5726 }
5727
5728 as_version = re->dw_read(d, &offset, 2);
5729 as_cu_offset = re->dw_read(d, &offset, dwarf_size);
5730 as_addrsz = re->dw_read(d, &offset, 1);
5731 as_segsz = re->dw_read(d, &offset, 1);
5732
5733 printf(" Length:\t\t\t%ju\n", (uintmax_t) length);
5734 printf(" Version:\t\t\t%u\n", as_version);
5735 printf(" Offset into .debug_info:\t%ju\n", (uintmax_t) as_cu_offset);
5736 printf(" Pointer Size:\t\t\t%u\n", as_addrsz);
5737 printf(" Segment Size:\t\t\t%u\n", as_segsz);
5738
5739 if (dwarf_get_aranges(re->dbg, &aranges, &cnt, &de) != DW_DLV_OK) {
5740 warnx("dwarf_get_aranges failed: %s", dwarf_errmsg(de));
5741 return;
5742 }
5743
5744 printf("\n Address Length\n");
5745 for (i = 0; i < cnt; i++) {
5746 if (dwarf_get_arange_info(aranges[i], &start, &length,
5747 &die_off, &de) != DW_DLV_OK) {
5748 warnx("dwarf_get_arange_info failed: %s",
5749 dwarf_errmsg(de));
5750 continue;
5751 }
5752 printf(" %08jx %ju\n", (uintmax_t) start,
5753 (uintmax_t) length);
5754 }
5755 }
5756
5757 static void
dump_dwarf_ranges_foreach(struct readelf * re,Dwarf_Die die,Dwarf_Addr base)5758 dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base)
5759 {
5760 Dwarf_Attribute *attr_list;
5761 Dwarf_Ranges *ranges;
5762 Dwarf_Die ret_die;
5763 Dwarf_Error de;
5764 Dwarf_Addr base0;
5765 Dwarf_Half attr;
5766 Dwarf_Signed attr_count, cnt;
5767 Dwarf_Unsigned off, bytecnt;
5768 int i, j, ret;
5769
5770 if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
5771 DW_DLV_OK) {
5772 if (ret == DW_DLV_ERROR)
5773 warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
5774 goto cont_search;
5775 }
5776
5777 for (i = 0; i < attr_count; i++) {
5778 if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
5779 warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
5780 continue;
5781 }
5782 if (attr != DW_AT_ranges)
5783 continue;
5784 if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) {
5785 warnx("dwarf_formudata failed: %s", dwarf_errmsg(de));
5786 continue;
5787 }
5788 if (dwarf_get_ranges(re->dbg, (Dwarf_Off) off, &ranges, &cnt,
5789 &bytecnt, &de) != DW_DLV_OK)
5790 continue;
5791 base0 = base;
5792 for (j = 0; j < cnt; j++) {
5793 printf(" %08jx ", (uintmax_t) off);
5794 if (ranges[j].dwr_type == DW_RANGES_END) {
5795 printf("%s\n", "<End of list>");
5796 continue;
5797 } else if (ranges[j].dwr_type ==
5798 DW_RANGES_ADDRESS_SELECTION) {
5799 base0 = ranges[j].dwr_addr2;
5800 continue;
5801 }
5802 if (re->ec == ELFCLASS32)
5803 printf("%08jx %08jx\n",
5804 (uintmax_t) (ranges[j].dwr_addr1 + base0),
5805 (uintmax_t) (ranges[j].dwr_addr2 + base0));
5806 else
5807 printf("%016jx %016jx\n",
5808 (uintmax_t) (ranges[j].dwr_addr1 + base0),
5809 (uintmax_t) (ranges[j].dwr_addr2 + base0));
5810 }
5811 }
5812
5813 cont_search:
5814 /* Search children. */
5815 ret = dwarf_child(die, &ret_die, &de);
5816 if (ret == DW_DLV_ERROR)
5817 warnx("dwarf_child: %s", dwarf_errmsg(de));
5818 else if (ret == DW_DLV_OK)
5819 dump_dwarf_ranges_foreach(re, ret_die, base);
5820
5821 /* Search sibling. */
5822 ret = dwarf_siblingof(re->dbg, die, &ret_die, &de);
5823 if (ret == DW_DLV_ERROR)
5824 warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
5825 else if (ret == DW_DLV_OK)
5826 dump_dwarf_ranges_foreach(re, ret_die, base);
5827 }
5828
5829 static void
dump_dwarf_ranges(struct readelf * re)5830 dump_dwarf_ranges(struct readelf *re)
5831 {
5832 Dwarf_Ranges *ranges;
5833 Dwarf_Die die;
5834 Dwarf_Signed cnt;
5835 Dwarf_Unsigned bytecnt;
5836 Dwarf_Half tag;
5837 Dwarf_Error de;
5838 Dwarf_Unsigned lowpc;
5839 int ret;
5840
5841 if (dwarf_get_ranges(re->dbg, 0, &ranges, &cnt, &bytecnt, &de) !=
5842 DW_DLV_OK)
5843 return;
5844
5845 printf("Contents of the .debug_ranges section:\n\n");
5846 if (re->ec == ELFCLASS32)
5847 printf(" %-8s %-8s %s\n", "Offset", "Begin", "End");
5848 else
5849 printf(" %-8s %-16s %s\n", "Offset", "Begin", "End");
5850
5851 while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL,
5852 NULL, &de)) == DW_DLV_OK) {
5853 die = NULL;
5854 if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK)
5855 continue;
5856 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
5857 warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
5858 continue;
5859 }
5860 /* XXX: What about DW_TAG_partial_unit? */
5861 lowpc = 0;
5862 if (tag == DW_TAG_compile_unit) {
5863 if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc,
5864 &de) != DW_DLV_OK)
5865 lowpc = 0;
5866 }
5867
5868 dump_dwarf_ranges_foreach(re, die, (Dwarf_Addr) lowpc);
5869 }
5870 putchar('\n');
5871 }
5872
5873 static void
dump_dwarf_macinfo(struct readelf * re)5874 dump_dwarf_macinfo(struct readelf *re)
5875 {
5876 Dwarf_Unsigned offset;
5877 Dwarf_Signed cnt;
5878 Dwarf_Macro_Details *md;
5879 Dwarf_Error de;
5880 const char *mi_str;
5881 char unk_mi[32];
5882 int i;
5883
5884 #define _MAX_MACINFO_ENTRY 65535
5885
5886 printf("\nContents of section .debug_macinfo:\n\n");
5887
5888 offset = 0;
5889 while (dwarf_get_macro_details(re->dbg, offset, _MAX_MACINFO_ENTRY,
5890 &cnt, &md, &de) == DW_DLV_OK) {
5891 for (i = 0; i < cnt; i++) {
5892 offset = md[i].dmd_offset + 1;
5893 if (md[i].dmd_type == 0)
5894 break;
5895 if (dwarf_get_MACINFO_name(md[i].dmd_type, &mi_str) !=
5896 DW_DLV_OK) {
5897 snprintf(unk_mi, sizeof(unk_mi),
5898 "[Unknown MACINFO: %#x]", md[i].dmd_type);
5899 mi_str = unk_mi;
5900 }
5901 printf(" %s", mi_str);
5902 switch (md[i].dmd_type) {
5903 case DW_MACINFO_define:
5904 case DW_MACINFO_undef:
5905 printf(" - lineno : %jd macro : %s\n",
5906 (intmax_t) md[i].dmd_lineno,
5907 md[i].dmd_macro);
5908 break;
5909 case DW_MACINFO_start_file:
5910 printf(" - lineno : %jd filenum : %jd\n",
5911 (intmax_t) md[i].dmd_lineno,
5912 (intmax_t) md[i].dmd_fileindex);
5913 break;
5914 default:
5915 putchar('\n');
5916 break;
5917 }
5918 }
5919 }
5920
5921 #undef _MAX_MACINFO_ENTRY
5922 }
5923
5924 static void
dump_dwarf_frame_inst(struct readelf * re,Dwarf_Cie cie,uint8_t * insts,Dwarf_Unsigned len,Dwarf_Unsigned caf,Dwarf_Signed daf,Dwarf_Addr pc,Dwarf_Debug dbg)5925 dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie, uint8_t *insts,
5926 Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf, Dwarf_Addr pc,
5927 Dwarf_Debug dbg)
5928 {
5929 Dwarf_Frame_Op *oplist;
5930 Dwarf_Signed opcnt, delta;
5931 Dwarf_Small op;
5932 Dwarf_Error de;
5933 const char *op_str;
5934 char unk_op[32];
5935 int i;
5936
5937 if (dwarf_expand_frame_instructions(cie, insts, len, &oplist,
5938 &opcnt, &de) != DW_DLV_OK) {
5939 warnx("dwarf_expand_frame_instructions failed: %s",
5940 dwarf_errmsg(de));
5941 return;
5942 }
5943
5944 for (i = 0; i < opcnt; i++) {
5945 if (oplist[i].fp_base_op != 0)
5946 op = oplist[i].fp_base_op << 6;
5947 else
5948 op = oplist[i].fp_extended_op;
5949 if (dwarf_get_CFA_name(op, &op_str) != DW_DLV_OK) {
5950 snprintf(unk_op, sizeof(unk_op), "[Unknown CFA: %#x]",
5951 op);
5952 op_str = unk_op;
5953 }
5954 printf(" %s", op_str);
5955 switch (op) {
5956 case DW_CFA_advance_loc:
5957 delta = oplist[i].fp_offset * caf;
5958 pc += delta;
5959 printf(": %ju to %08jx", (uintmax_t) delta,
5960 (uintmax_t) pc);
5961 break;
5962 case DW_CFA_offset:
5963 case DW_CFA_offset_extended:
5964 case DW_CFA_offset_extended_sf:
5965 delta = oplist[i].fp_offset * daf;
5966 printf(": r%u (%s) at cfa%+jd", oplist[i].fp_register,
5967 dwarf_regname(re, oplist[i].fp_register),
5968 (intmax_t) delta);
5969 break;
5970 case DW_CFA_restore:
5971 printf(": r%u (%s)", oplist[i].fp_register,
5972 dwarf_regname(re, oplist[i].fp_register));
5973 break;
5974 case DW_CFA_set_loc:
5975 pc = oplist[i].fp_offset;
5976 printf(": to %08jx", (uintmax_t) pc);
5977 break;
5978 case DW_CFA_advance_loc1:
5979 case DW_CFA_advance_loc2:
5980 case DW_CFA_advance_loc4:
5981 pc += oplist[i].fp_offset;
5982 printf(": %jd to %08jx", (intmax_t) oplist[i].fp_offset,
5983 (uintmax_t) pc);
5984 break;
5985 case DW_CFA_def_cfa:
5986 printf(": r%u (%s) ofs %ju", oplist[i].fp_register,
5987 dwarf_regname(re, oplist[i].fp_register),
5988 (uintmax_t) oplist[i].fp_offset);
5989 break;
5990 case DW_CFA_def_cfa_sf:
5991 printf(": r%u (%s) ofs %jd", oplist[i].fp_register,
5992 dwarf_regname(re, oplist[i].fp_register),
5993 (intmax_t) (oplist[i].fp_offset * daf));
5994 break;
5995 case DW_CFA_def_cfa_register:
5996 printf(": r%u (%s)", oplist[i].fp_register,
5997 dwarf_regname(re, oplist[i].fp_register));
5998 break;
5999 case DW_CFA_def_cfa_offset:
6000 printf(": %ju", (uintmax_t) oplist[i].fp_offset);
6001 break;
6002 case DW_CFA_def_cfa_offset_sf:
6003 printf(": %jd", (intmax_t) (oplist[i].fp_offset * daf));
6004 break;
6005 default:
6006 break;
6007 }
6008 putchar('\n');
6009 }
6010
6011 dwarf_dealloc(dbg, oplist, DW_DLA_FRAME_BLOCK);
6012 }
6013
6014 static char *
get_regoff_str(struct readelf * re,Dwarf_Half reg,Dwarf_Addr off)6015 get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off)
6016 {
6017 static char rs[16];
6018
6019 if (reg == DW_FRAME_UNDEFINED_VAL || reg == DW_FRAME_REG_INITIAL_VALUE)
6020 snprintf(rs, sizeof(rs), "%c", 'u');
6021 else if (reg == DW_FRAME_CFA_COL)
6022 snprintf(rs, sizeof(rs), "c%+jd", (intmax_t) off);
6023 else
6024 snprintf(rs, sizeof(rs), "%s%+jd", dwarf_regname(re, reg),
6025 (intmax_t) off);
6026
6027 return (rs);
6028 }
6029
6030 static int
dump_dwarf_frame_regtable(struct readelf * re,Dwarf_Fde fde,Dwarf_Addr pc,Dwarf_Unsigned func_len,Dwarf_Half cie_ra)6031 dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde, Dwarf_Addr pc,
6032 Dwarf_Unsigned func_len, Dwarf_Half cie_ra)
6033 {
6034 Dwarf_Regtable rt;
6035 Dwarf_Addr row_pc, end_pc, pre_pc, cur_pc;
6036 Dwarf_Error de;
6037 char *vec;
6038 int i;
6039
6040 #define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7))
6041 #define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7)))
6042 #define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7)))
6043 #define RT(x) rt.rules[(x)]
6044
6045 vec = calloc((DW_REG_TABLE_SIZE + 7) / 8, 1);
6046 if (vec == NULL)
6047 err(EXIT_FAILURE, "calloc failed");
6048
6049 pre_pc = ~((Dwarf_Addr) 0);
6050 cur_pc = pc;
6051 end_pc = pc + func_len;
6052 for (; cur_pc < end_pc; cur_pc++) {
6053 if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc,
6054 &de) != DW_DLV_OK) {
6055 free(vec);
6056 warnx("dwarf_get_fde_info_for_all_regs failed: %s\n",
6057 dwarf_errmsg(de));
6058 return (-1);
6059 }
6060 if (row_pc == pre_pc)
6061 continue;
6062 pre_pc = row_pc;
6063 for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
6064 if (rt.rules[i].dw_regnum != DW_FRAME_REG_INITIAL_VALUE)
6065 BIT_SET(vec, i);
6066 }
6067 }
6068
6069 printf(" LOC CFA ");
6070 for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
6071 if (BIT_ISSET(vec, i)) {
6072 if ((Dwarf_Half) i == cie_ra)
6073 printf("ra ");
6074 else
6075 printf("%-5s",
6076 dwarf_regname(re, (unsigned int) i));
6077 }
6078 }
6079 putchar('\n');
6080
6081 pre_pc = ~((Dwarf_Addr) 0);
6082 cur_pc = pc;
6083 end_pc = pc + func_len;
6084 for (; cur_pc < end_pc; cur_pc++) {
6085 if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc,
6086 &de) != DW_DLV_OK) {
6087 free(vec);
6088 warnx("dwarf_get_fde_info_for_all_regs failed: %s\n",
6089 dwarf_errmsg(de));
6090 return (-1);
6091 }
6092 if (row_pc == pre_pc)
6093 continue;
6094 pre_pc = row_pc;
6095 printf("%08jx ", (uintmax_t) row_pc);
6096 printf("%-8s ", get_regoff_str(re, RT(0).dw_regnum,
6097 RT(0).dw_offset));
6098 for (i = 1; i < DW_REG_TABLE_SIZE; i++) {
6099 if (BIT_ISSET(vec, i)) {
6100 printf("%-5s", get_regoff_str(re,
6101 RT(i).dw_regnum, RT(i).dw_offset));
6102 }
6103 }
6104 putchar('\n');
6105 }
6106
6107 free(vec);
6108
6109 return (0);
6110
6111 #undef BIT_SET
6112 #undef BIT_CLR
6113 #undef BIT_ISSET
6114 #undef RT
6115 }
6116
6117 static void
dump_dwarf_frame_section(struct readelf * re,struct section * s,int alt)6118 dump_dwarf_frame_section(struct readelf *re, struct section *s, int alt)
6119 {
6120 Dwarf_Cie *cie_list, cie, pre_cie;
6121 Dwarf_Fde *fde_list, fde;
6122 Dwarf_Off cie_offset, fde_offset;
6123 Dwarf_Unsigned cie_length, fde_instlen;
6124 Dwarf_Unsigned cie_caf, cie_daf, cie_instlen, func_len, fde_length;
6125 Dwarf_Signed cie_count, fde_count, cie_index;
6126 Dwarf_Addr low_pc;
6127 Dwarf_Half cie_ra;
6128 Dwarf_Small cie_version;
6129 Dwarf_Ptr fde_addr, fde_inst, cie_inst;
6130 char *cie_aug, c;
6131 int i, eh_frame;
6132 Dwarf_Error de;
6133
6134 printf("\nThe section %s contains:\n\n", s->name);
6135
6136 if (!strcmp(s->name, ".debug_frame")) {
6137 eh_frame = 0;
6138 if (dwarf_get_fde_list(re->dbg, &cie_list, &cie_count,
6139 &fde_list, &fde_count, &de) != DW_DLV_OK) {
6140 warnx("dwarf_get_fde_list failed: %s",
6141 dwarf_errmsg(de));
6142 return;
6143 }
6144 } else if (!strcmp(s->name, ".eh_frame")) {
6145 eh_frame = 1;
6146 if (dwarf_get_fde_list_eh(re->dbg, &cie_list, &cie_count,
6147 &fde_list, &fde_count, &de) != DW_DLV_OK) {
6148 warnx("dwarf_get_fde_list_eh failed: %s",
6149 dwarf_errmsg(de));
6150 return;
6151 }
6152 } else
6153 return;
6154
6155 pre_cie = NULL;
6156 for (i = 0; i < fde_count; i++) {
6157 if (dwarf_get_fde_n(fde_list, i, &fde, &de) != DW_DLV_OK) {
6158 warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de));
6159 continue;
6160 }
6161 if (dwarf_get_cie_of_fde(fde, &cie, &de) != DW_DLV_OK) {
6162 warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de));
6163 continue;
6164 }
6165 if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_addr,
6166 &fde_length, &cie_offset, &cie_index, &fde_offset,
6167 &de) != DW_DLV_OK) {
6168 warnx("dwarf_get_fde_range failed: %s",
6169 dwarf_errmsg(de));
6170 continue;
6171 }
6172 if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_instlen,
6173 &de) != DW_DLV_OK) {
6174 warnx("dwarf_get_fde_instr_bytes failed: %s",
6175 dwarf_errmsg(de));
6176 continue;
6177 }
6178 if (pre_cie == NULL || cie != pre_cie) {
6179 pre_cie = cie;
6180 if (dwarf_get_cie_info(cie, &cie_length, &cie_version,
6181 &cie_aug, &cie_caf, &cie_daf, &cie_ra,
6182 &cie_inst, &cie_instlen, &de) != DW_DLV_OK) {
6183 warnx("dwarf_get_cie_info failed: %s",
6184 dwarf_errmsg(de));
6185 continue;
6186 }
6187 printf("%08jx %08jx %8.8jx CIE",
6188 (uintmax_t) cie_offset,
6189 (uintmax_t) cie_length,
6190 (uintmax_t) (eh_frame ? 0 : ~0U));
6191 if (!alt) {
6192 putchar('\n');
6193 printf(" Version:\t\t\t%u\n", cie_version);
6194 printf(" Augmentation:\t\t\t\"");
6195 while ((c = *cie_aug++) != '\0')
6196 putchar(c);
6197 printf("\"\n");
6198 printf(" Code alignment factor:\t%ju\n",
6199 (uintmax_t) cie_caf);
6200 printf(" Data alignment factor:\t%jd\n",
6201 (intmax_t) cie_daf);
6202 printf(" Return address column:\t%ju\n",
6203 (uintmax_t) cie_ra);
6204 putchar('\n');
6205 dump_dwarf_frame_inst(re, cie, cie_inst,
6206 cie_instlen, cie_caf, cie_daf, 0,
6207 re->dbg);
6208 putchar('\n');
6209 } else {
6210 printf(" \"");
6211 while ((c = *cie_aug++) != '\0')
6212 putchar(c);
6213 putchar('"');
6214 printf(" cf=%ju df=%jd ra=%ju\n",
6215 (uintmax_t) cie_caf,
6216 (uintmax_t) cie_daf,
6217 (uintmax_t) cie_ra);
6218 dump_dwarf_frame_regtable(re, fde, low_pc, 1,
6219 cie_ra);
6220 putchar('\n');
6221 }
6222 }
6223 printf("%08jx %08jx %08jx FDE cie=%08jx pc=%08jx..%08jx\n",
6224 (uintmax_t) fde_offset, (uintmax_t) fde_length,
6225 (uintmax_t) cie_offset,
6226 (uintmax_t) (eh_frame ? fde_offset + 4 - cie_offset :
6227 cie_offset),
6228 (uintmax_t) low_pc, (uintmax_t) (low_pc + func_len));
6229 if (!alt)
6230 dump_dwarf_frame_inst(re, cie, fde_inst, fde_instlen,
6231 cie_caf, cie_daf, low_pc, re->dbg);
6232 else
6233 dump_dwarf_frame_regtable(re, fde, low_pc, func_len,
6234 cie_ra);
6235 putchar('\n');
6236 }
6237 }
6238
6239 static void
dump_dwarf_frame(struct readelf * re,int alt)6240 dump_dwarf_frame(struct readelf *re, int alt)
6241 {
6242 struct section *s;
6243 int i;
6244
6245 (void) dwarf_set_frame_cfa_value(re->dbg, DW_FRAME_CFA_COL);
6246
6247 for (i = 0; (size_t) i < re->shnum; i++) {
6248 s = &re->sl[i];
6249 if (s->name != NULL && (!strcmp(s->name, ".debug_frame") ||
6250 !strcmp(s->name, ".eh_frame")))
6251 dump_dwarf_frame_section(re, s, alt);
6252 }
6253 }
6254
6255 static void
dump_dwarf_str(struct readelf * re)6256 dump_dwarf_str(struct readelf *re)
6257 {
6258 struct section *s;
6259 Elf_Data *d;
6260 unsigned char *p;
6261 int elferr, end, i, j;
6262
6263 printf("\nContents of section .debug_str:\n");
6264
6265 s = NULL;
6266 for (i = 0; (size_t) i < re->shnum; i++) {
6267 s = &re->sl[i];
6268 if (s->name != NULL && !strcmp(s->name, ".debug_str"))
6269 break;
6270 }
6271 if ((size_t) i >= re->shnum)
6272 return;
6273
6274 (void) elf_errno();
6275 if ((d = elf_getdata(s->scn, NULL)) == NULL) {
6276 elferr = elf_errno();
6277 if (elferr != 0)
6278 warnx("elf_getdata failed: %s", elf_errmsg(-1));
6279 return;
6280 }
6281 if (d->d_size <= 0)
6282 return;
6283
6284 for (i = 0, p = d->d_buf; (size_t) i < d->d_size; i += 16) {
6285 printf(" 0x%08x", (unsigned int) i);
6286 if ((size_t) i + 16 > d->d_size)
6287 end = d->d_size;
6288 else
6289 end = i + 16;
6290 for (j = i; j < i + 16; j++) {
6291 if ((j - i) % 4 == 0)
6292 putchar(' ');
6293 if (j >= end) {
6294 printf(" ");
6295 continue;
6296 }
6297 printf("%02x", (uint8_t) p[j]);
6298 }
6299 putchar(' ');
6300 for (j = i; j < end; j++) {
6301 if (isprint(p[j]))
6302 putchar(p[j]);
6303 else if (p[j] == 0)
6304 putchar('.');
6305 else
6306 putchar(' ');
6307 }
6308 putchar('\n');
6309 }
6310 }
6311
6312 static int
loc_at_comparator(const void * la1,const void * la2)6313 loc_at_comparator(const void *la1, const void *la2)
6314 {
6315 const struct loc_at *left, *right;
6316
6317 left = (const struct loc_at *)la1;
6318 right = (const struct loc_at *)la2;
6319
6320 if (left->la_off > right->la_off)
6321 return (1);
6322 else if (left->la_off < right->la_off)
6323 return (-1);
6324 else
6325 return (0);
6326 }
6327
6328 static void
search_loclist_at(struct readelf * re,Dwarf_Die die,Dwarf_Unsigned lowpc,struct loc_at ** la_list,size_t * la_list_len,size_t * la_list_cap)6329 search_loclist_at(struct readelf *re, Dwarf_Die die, Dwarf_Unsigned lowpc,
6330 struct loc_at **la_list, size_t *la_list_len, size_t *la_list_cap)
6331 {
6332 struct loc_at *la;
6333 Dwarf_Attribute *attr_list;
6334 Dwarf_Die ret_die;
6335 Dwarf_Unsigned off;
6336 Dwarf_Off ref;
6337 Dwarf_Signed attr_count;
6338 Dwarf_Half attr, form;
6339 Dwarf_Bool is_info;
6340 Dwarf_Error de;
6341 int i, ret;
6342
6343 is_info = dwarf_get_die_infotypes_flag(die);
6344
6345 if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) !=
6346 DW_DLV_OK) {
6347 if (ret == DW_DLV_ERROR)
6348 warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de));
6349 goto cont_search;
6350 }
6351 for (i = 0; i < attr_count; i++) {
6352 if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) {
6353 warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de));
6354 continue;
6355 }
6356 if (attr != DW_AT_location &&
6357 attr != DW_AT_string_length &&
6358 attr != DW_AT_return_addr &&
6359 attr != DW_AT_data_member_location &&
6360 attr != DW_AT_frame_base &&
6361 attr != DW_AT_segment &&
6362 attr != DW_AT_static_link &&
6363 attr != DW_AT_use_location &&
6364 attr != DW_AT_vtable_elem_location)
6365 continue;
6366 if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) {
6367 warnx("dwarf_whatform failed: %s", dwarf_errmsg(de));
6368 continue;
6369 }
6370 if (form == DW_FORM_data4 || form == DW_FORM_data8) {
6371 if (dwarf_formudata(attr_list[i], &off, &de) !=
6372 DW_DLV_OK) {
6373 warnx("dwarf_formudata failed: %s",
6374 dwarf_errmsg(de));
6375 continue;
6376 }
6377 } else if (form == DW_FORM_sec_offset) {
6378 if (dwarf_global_formref(attr_list[i], &ref, &de) !=
6379 DW_DLV_OK) {
6380 warnx("dwarf_global_formref failed: %s",
6381 dwarf_errmsg(de));
6382 continue;
6383 }
6384 off = ref;
6385 } else
6386 continue;
6387
6388 if (*la_list_cap == *la_list_len) {
6389 *la_list = realloc(*la_list,
6390 *la_list_cap * 2 * sizeof(**la_list));
6391 if (*la_list == NULL)
6392 err(EXIT_FAILURE, "realloc failed");
6393 *la_list_cap *= 2;
6394 }
6395 la = &((*la_list)[*la_list_len]);
6396 la->la_at = attr_list[i];
6397 la->la_off = off;
6398 la->la_lowpc = lowpc;
6399 la->la_cu_psize = re->cu_psize;
6400 la->la_cu_osize = re->cu_osize;
6401 la->la_cu_ver = re->cu_ver;
6402 (*la_list_len)++;
6403 }
6404
6405 cont_search:
6406 /* Search children. */
6407 ret = dwarf_child(die, &ret_die, &de);
6408 if (ret == DW_DLV_ERROR)
6409 warnx("dwarf_child: %s", dwarf_errmsg(de));
6410 else if (ret == DW_DLV_OK)
6411 search_loclist_at(re, ret_die, lowpc, la_list,
6412 la_list_len, la_list_cap);
6413
6414 /* Search sibling. */
6415 ret = dwarf_siblingof_b(re->dbg, die, &ret_die, is_info, &de);
6416 if (ret == DW_DLV_ERROR)
6417 warnx("dwarf_siblingof: %s", dwarf_errmsg(de));
6418 else if (ret == DW_DLV_OK)
6419 search_loclist_at(re, ret_die, lowpc, la_list,
6420 la_list_len, la_list_cap);
6421 }
6422
6423 static void
dump_dwarf_loc(struct readelf * re,Dwarf_Loc * lr)6424 dump_dwarf_loc(struct readelf *re, Dwarf_Loc *lr)
6425 {
6426 const char *op_str;
6427 char unk_op[32];
6428 uint8_t *b, n;
6429 int i;
6430
6431 if (dwarf_get_OP_name(lr->lr_atom, &op_str) !=
6432 DW_DLV_OK) {
6433 snprintf(unk_op, sizeof(unk_op),
6434 "[Unknown OP: %#x]", lr->lr_atom);
6435 op_str = unk_op;
6436 }
6437
6438 printf("%s", op_str);
6439
6440 switch (lr->lr_atom) {
6441 case DW_OP_reg0:
6442 case DW_OP_reg1:
6443 case DW_OP_reg2:
6444 case DW_OP_reg3:
6445 case DW_OP_reg4:
6446 case DW_OP_reg5:
6447 case DW_OP_reg6:
6448 case DW_OP_reg7:
6449 case DW_OP_reg8:
6450 case DW_OP_reg9:
6451 case DW_OP_reg10:
6452 case DW_OP_reg11:
6453 case DW_OP_reg12:
6454 case DW_OP_reg13:
6455 case DW_OP_reg14:
6456 case DW_OP_reg15:
6457 case DW_OP_reg16:
6458 case DW_OP_reg17:
6459 case DW_OP_reg18:
6460 case DW_OP_reg19:
6461 case DW_OP_reg20:
6462 case DW_OP_reg21:
6463 case DW_OP_reg22:
6464 case DW_OP_reg23:
6465 case DW_OP_reg24:
6466 case DW_OP_reg25:
6467 case DW_OP_reg26:
6468 case DW_OP_reg27:
6469 case DW_OP_reg28:
6470 case DW_OP_reg29:
6471 case DW_OP_reg30:
6472 case DW_OP_reg31:
6473 printf(" (%s)", dwarf_regname(re, lr->lr_atom - DW_OP_reg0));
6474 break;
6475
6476 case DW_OP_deref:
6477 case DW_OP_lit0:
6478 case DW_OP_lit1:
6479 case DW_OP_lit2:
6480 case DW_OP_lit3:
6481 case DW_OP_lit4:
6482 case DW_OP_lit5:
6483 case DW_OP_lit6:
6484 case DW_OP_lit7:
6485 case DW_OP_lit8:
6486 case DW_OP_lit9:
6487 case DW_OP_lit10:
6488 case DW_OP_lit11:
6489 case DW_OP_lit12:
6490 case DW_OP_lit13:
6491 case DW_OP_lit14:
6492 case DW_OP_lit15:
6493 case DW_OP_lit16:
6494 case DW_OP_lit17:
6495 case DW_OP_lit18:
6496 case DW_OP_lit19:
6497 case DW_OP_lit20:
6498 case DW_OP_lit21:
6499 case DW_OP_lit22:
6500 case DW_OP_lit23:
6501 case DW_OP_lit24:
6502 case DW_OP_lit25:
6503 case DW_OP_lit26:
6504 case DW_OP_lit27:
6505 case DW_OP_lit28:
6506 case DW_OP_lit29:
6507 case DW_OP_lit30:
6508 case DW_OP_lit31:
6509 case DW_OP_dup:
6510 case DW_OP_drop:
6511 case DW_OP_over:
6512 case DW_OP_swap:
6513 case DW_OP_rot:
6514 case DW_OP_xderef:
6515 case DW_OP_abs:
6516 case DW_OP_and:
6517 case DW_OP_div:
6518 case DW_OP_minus:
6519 case DW_OP_mod:
6520 case DW_OP_mul:
6521 case DW_OP_neg:
6522 case DW_OP_not:
6523 case DW_OP_or:
6524 case DW_OP_plus:
6525 case DW_OP_shl:
6526 case DW_OP_shr:
6527 case DW_OP_shra:
6528 case DW_OP_xor:
6529 case DW_OP_eq:
6530 case DW_OP_ge:
6531 case DW_OP_gt:
6532 case DW_OP_le:
6533 case DW_OP_lt:
6534 case DW_OP_ne:
6535 case DW_OP_nop:
6536 case DW_OP_push_object_address:
6537 case DW_OP_form_tls_address:
6538 case DW_OP_call_frame_cfa:
6539 case DW_OP_stack_value:
6540 case DW_OP_GNU_push_tls_address:
6541 case DW_OP_GNU_uninit:
6542 break;
6543
6544 case DW_OP_const1u:
6545 case DW_OP_pick:
6546 case DW_OP_deref_size:
6547 case DW_OP_xderef_size:
6548 case DW_OP_const2u:
6549 case DW_OP_bra:
6550 case DW_OP_skip:
6551 case DW_OP_const4u:
6552 case DW_OP_const8u:
6553 case DW_OP_constu:
6554 case DW_OP_plus_uconst:
6555 case DW_OP_regx:
6556 case DW_OP_piece:
6557 printf(": %ju", (uintmax_t)
6558 lr->lr_number);
6559 break;
6560
6561 case DW_OP_const1s:
6562 case DW_OP_const2s:
6563 case DW_OP_const4s:
6564 case DW_OP_const8s:
6565 case DW_OP_consts:
6566 printf(": %jd", (intmax_t)
6567 lr->lr_number);
6568 break;
6569
6570 case DW_OP_breg0:
6571 case DW_OP_breg1:
6572 case DW_OP_breg2:
6573 case DW_OP_breg3:
6574 case DW_OP_breg4:
6575 case DW_OP_breg5:
6576 case DW_OP_breg6:
6577 case DW_OP_breg7:
6578 case DW_OP_breg8:
6579 case DW_OP_breg9:
6580 case DW_OP_breg10:
6581 case DW_OP_breg11:
6582 case DW_OP_breg12:
6583 case DW_OP_breg13:
6584 case DW_OP_breg14:
6585 case DW_OP_breg15:
6586 case DW_OP_breg16:
6587 case DW_OP_breg17:
6588 case DW_OP_breg18:
6589 case DW_OP_breg19:
6590 case DW_OP_breg20:
6591 case DW_OP_breg21:
6592 case DW_OP_breg22:
6593 case DW_OP_breg23:
6594 case DW_OP_breg24:
6595 case DW_OP_breg25:
6596 case DW_OP_breg26:
6597 case DW_OP_breg27:
6598 case DW_OP_breg28:
6599 case DW_OP_breg29:
6600 case DW_OP_breg30:
6601 case DW_OP_breg31:
6602 printf(" (%s): %jd",
6603 dwarf_regname(re, lr->lr_atom - DW_OP_breg0),
6604 (intmax_t) lr->lr_number);
6605 break;
6606
6607 case DW_OP_fbreg:
6608 printf(": %jd", (intmax_t)
6609 lr->lr_number);
6610 break;
6611
6612 case DW_OP_bregx:
6613 printf(": %ju (%s) %jd",
6614 (uintmax_t) lr->lr_number,
6615 dwarf_regname(re, (unsigned int) lr->lr_number),
6616 (intmax_t) lr->lr_number2);
6617 break;
6618
6619 case DW_OP_addr:
6620 case DW_OP_GNU_encoded_addr:
6621 printf(": %#jx", (uintmax_t)
6622 lr->lr_number);
6623 break;
6624
6625 case DW_OP_GNU_implicit_pointer:
6626 printf(": <0x%jx> %jd", (uintmax_t) lr->lr_number,
6627 (intmax_t) lr->lr_number2);
6628 break;
6629
6630 case DW_OP_implicit_value:
6631 printf(": %ju byte block:", (uintmax_t) lr->lr_number);
6632 b = (uint8_t *)(uintptr_t) lr->lr_number2;
6633 for (i = 0; (Dwarf_Unsigned) i < lr->lr_number; i++)
6634 printf(" %x", b[i]);
6635 break;
6636
6637 case DW_OP_GNU_entry_value:
6638 printf(": (");
6639 dump_dwarf_block(re, (uint8_t *)(uintptr_t) lr->lr_number2,
6640 lr->lr_number);
6641 putchar(')');
6642 break;
6643
6644 case DW_OP_GNU_const_type:
6645 printf(": <0x%jx> ", (uintmax_t) lr->lr_number);
6646 b = (uint8_t *)(uintptr_t) lr->lr_number2;
6647 n = *b;
6648 for (i = 1; (uint8_t) i < n; i++)
6649 printf(" %x", b[i]);
6650 break;
6651
6652 case DW_OP_GNU_regval_type:
6653 printf(": %ju (%s) <0x%jx>", (uintmax_t) lr->lr_number,
6654 dwarf_regname(re, (unsigned int) lr->lr_number),
6655 (uintmax_t) lr->lr_number2);
6656 break;
6657
6658 case DW_OP_GNU_convert:
6659 case DW_OP_GNU_deref_type:
6660 case DW_OP_GNU_parameter_ref:
6661 case DW_OP_GNU_reinterpret:
6662 printf(": <0x%jx>", (uintmax_t) lr->lr_number);
6663 break;
6664
6665 default:
6666 break;
6667 }
6668 }
6669
6670 static void
dump_dwarf_block(struct readelf * re,uint8_t * b,Dwarf_Unsigned len)6671 dump_dwarf_block(struct readelf *re, uint8_t *b, Dwarf_Unsigned len)
6672 {
6673 Dwarf_Locdesc *llbuf;
6674 Dwarf_Signed lcnt;
6675 Dwarf_Error de;
6676 int i;
6677
6678 if (dwarf_loclist_from_expr_b(re->dbg, b, len, re->cu_psize,
6679 re->cu_osize, re->cu_ver, &llbuf, &lcnt, &de) != DW_DLV_OK) {
6680 warnx("dwarf_loclist_form_expr_b: %s", dwarf_errmsg(de));
6681 return;
6682 }
6683
6684 for (i = 0; (Dwarf_Half) i < llbuf->ld_cents; i++) {
6685 dump_dwarf_loc(re, &llbuf->ld_s[i]);
6686 if (i < llbuf->ld_cents - 1)
6687 printf("; ");
6688 }
6689
6690 dwarf_dealloc(re->dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
6691 dwarf_dealloc(re->dbg, llbuf, DW_DLA_LOCDESC);
6692 }
6693
6694 static void
dump_dwarf_loclist(struct readelf * re)6695 dump_dwarf_loclist(struct readelf *re)
6696 {
6697 Dwarf_Die die;
6698 Dwarf_Locdesc **llbuf;
6699 Dwarf_Unsigned lowpc;
6700 Dwarf_Signed lcnt;
6701 Dwarf_Half tag, version, pointer_size, off_size;
6702 Dwarf_Error de;
6703 struct loc_at *la_list, *left, *right, *la;
6704 size_t la_list_len, la_list_cap;
6705 unsigned int duplicates, k;
6706 int i, j, ret, has_content;
6707
6708 la_list_len = 0;
6709 la_list_cap = 200;
6710 if ((la_list = calloc(la_list_cap, sizeof(struct loc_at))) == NULL)
6711 errx(EXIT_FAILURE, "calloc failed");
6712 /* Search .debug_info section. */
6713 while ((ret = dwarf_next_cu_header_b(re->dbg, NULL, &version, NULL,
6714 &pointer_size, &off_size, NULL, NULL, &de)) == DW_DLV_OK) {
6715 set_cu_context(re, pointer_size, off_size, version);
6716 die = NULL;
6717 if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK)
6718 continue;
6719 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
6720 warnx("dwarf_tag failed: %s", dwarf_errmsg(de));
6721 continue;
6722 }
6723 /* XXX: What about DW_TAG_partial_unit? */
6724 lowpc = 0;
6725 if (tag == DW_TAG_compile_unit) {
6726 if (dwarf_attrval_unsigned(die, DW_AT_low_pc,
6727 &lowpc, &de) != DW_DLV_OK)
6728 lowpc = 0;
6729 }
6730
6731 /* Search attributes for reference to .debug_loc section. */
6732 search_loclist_at(re, die, lowpc, &la_list,
6733 &la_list_len, &la_list_cap);
6734 }
6735 if (ret == DW_DLV_ERROR)
6736 warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
6737
6738 /* Search .debug_types section. */
6739 do {
6740 while ((ret = dwarf_next_cu_header_c(re->dbg, 0, NULL,
6741 &version, NULL, &pointer_size, &off_size, NULL, NULL,
6742 NULL, NULL, &de)) == DW_DLV_OK) {
6743 set_cu_context(re, pointer_size, off_size, version);
6744 die = NULL;
6745 if (dwarf_siblingof(re->dbg, die, &die, &de) !=
6746 DW_DLV_OK)
6747 continue;
6748 if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) {
6749 warnx("dwarf_tag failed: %s",
6750 dwarf_errmsg(de));
6751 continue;
6752 }
6753
6754 lowpc = 0;
6755 if (tag == DW_TAG_type_unit) {
6756 if (dwarf_attrval_unsigned(die, DW_AT_low_pc,
6757 &lowpc, &de) != DW_DLV_OK)
6758 lowpc = 0;
6759 }
6760
6761 /*
6762 * Search attributes for reference to .debug_loc
6763 * section.
6764 */
6765 search_loclist_at(re, die, lowpc, &la_list,
6766 &la_list_len, &la_list_cap);
6767 }
6768 if (ret == DW_DLV_ERROR)
6769 warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de));
6770 } while (dwarf_next_types_section(re->dbg, &de) == DW_DLV_OK);
6771
6772 if (la_list_len == 0) {
6773 free(la_list);
6774 return;
6775 }
6776
6777 /* Sort la_list using loc_at_comparator. */
6778 qsort(la_list, la_list_len, sizeof(struct loc_at), loc_at_comparator);
6779
6780 /* Get rid of the duplicates in la_list. */
6781 duplicates = 0;
6782 for (k = 1; k < la_list_len; ++k) {
6783 left = &la_list[k - 1 - duplicates];
6784 right = &la_list[k];
6785
6786 if (left->la_off == right->la_off)
6787 duplicates++;
6788 else
6789 la_list[k - duplicates] = *right;
6790 }
6791 la_list_len -= duplicates;
6792
6793 has_content = 0;
6794 for (k = 0; k < la_list_len; ++k) {
6795 la = &la_list[k];
6796 if ((ret = dwarf_loclist_n(la->la_at, &llbuf, &lcnt, &de)) !=
6797 DW_DLV_OK) {
6798 if (ret != DW_DLV_NO_ENTRY)
6799 warnx("dwarf_loclist_n failed: %s",
6800 dwarf_errmsg(de));
6801 continue;
6802 }
6803 if (!has_content) {
6804 has_content = 1;
6805 printf("\nContents of section .debug_loc:\n");
6806 printf(" Offset Begin End Expression\n");
6807 }
6808 set_cu_context(re, la->la_cu_psize, la->la_cu_osize,
6809 la->la_cu_ver);
6810 for (i = 0; i < lcnt; i++) {
6811 printf(" %8.8jx ", (uintmax_t) la->la_off);
6812 if (llbuf[i]->ld_lopc == 0 && llbuf[i]->ld_hipc == 0) {
6813 printf("<End of list>\n");
6814 continue;
6815 }
6816
6817 /* TODO: handle base selection entry. */
6818
6819 printf("%8.8jx %8.8jx ",
6820 (uintmax_t) (la->la_lowpc + llbuf[i]->ld_lopc),
6821 (uintmax_t) (la->la_lowpc + llbuf[i]->ld_hipc));
6822
6823 putchar('(');
6824 for (j = 0; (Dwarf_Half) j < llbuf[i]->ld_cents; j++) {
6825 dump_dwarf_loc(re, &llbuf[i]->ld_s[j]);
6826 if (j < llbuf[i]->ld_cents - 1)
6827 printf("; ");
6828 }
6829 putchar(')');
6830
6831 if (llbuf[i]->ld_lopc == llbuf[i]->ld_hipc)
6832 printf(" (start == end)");
6833 putchar('\n');
6834 }
6835 for (i = 0; i < lcnt; i++) {
6836 dwarf_dealloc(re->dbg, llbuf[i]->ld_s,
6837 DW_DLA_LOC_BLOCK);
6838 dwarf_dealloc(re->dbg, llbuf[i], DW_DLA_LOCDESC);
6839 }
6840 dwarf_dealloc(re->dbg, llbuf, DW_DLA_LIST);
6841 }
6842
6843 if (!has_content)
6844 printf("\nSection '.debug_loc' has no debugging data.\n");
6845
6846 free(la_list);
6847 }
6848
6849 /*
6850 * Retrieve a string using string table section index and the string offset.
6851 */
6852 static const char*
get_string(struct readelf * re,int strtab,size_t off)6853 get_string(struct readelf *re, int strtab, size_t off)
6854 {
6855 const char *name;
6856
6857 if ((name = elf_strptr(re->elf, strtab, off)) == NULL)
6858 return ("");
6859
6860 return (name);
6861 }
6862
6863 /*
6864 * Retrieve the name of a symbol using the section index of the symbol
6865 * table and the index of the symbol within that table.
6866 */
6867 static const char *
get_symbol_name(struct readelf * re,int symtab,int i)6868 get_symbol_name(struct readelf *re, int symtab, int i)
6869 {
6870 struct section *s;
6871 const char *name;
6872 GElf_Sym sym;
6873 Elf_Data *data;
6874 int elferr;
6875
6876 s = &re->sl[symtab];
6877 if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM)
6878 return ("");
6879 (void) elf_errno();
6880 if ((data = elf_getdata(s->scn, NULL)) == NULL) {
6881 elferr = elf_errno();
6882 if (elferr != 0)
6883 warnx("elf_getdata failed: %s", elf_errmsg(elferr));
6884 return ("");
6885 }
6886 if (gelf_getsym(data, i, &sym) != &sym)
6887 return ("");
6888 /* Return section name for STT_SECTION symbol. */
6889 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) {
6890 if (sym.st_shndx < re->shnum &&
6891 re->sl[sym.st_shndx].name != NULL)
6892 return (re->sl[sym.st_shndx].name);
6893 return ("");
6894 }
6895 if (s->link >= re->shnum ||
6896 (name = elf_strptr(re->elf, s->link, sym.st_name)) == NULL)
6897 return ("");
6898
6899 return (name);
6900 }
6901
6902 static uint64_t
get_symbol_value(struct readelf * re,int symtab,int i)6903 get_symbol_value(struct readelf *re, int symtab, int i)
6904 {
6905 struct section *s;
6906 GElf_Sym sym;
6907 Elf_Data *data;
6908 int elferr;
6909
6910 s = &re->sl[symtab];
6911 if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM)
6912 return (0);
6913 (void) elf_errno();
6914 if ((data = elf_getdata(s->scn, NULL)) == NULL) {
6915 elferr = elf_errno();
6916 if (elferr != 0)
6917 warnx("elf_getdata failed: %s", elf_errmsg(elferr));
6918 return (0);
6919 }
6920 if (gelf_getsym(data, i, &sym) != &sym)
6921 return (0);
6922
6923 return (sym.st_value);
6924 }
6925
6926 /*
6927 * Decompress a data section if needed (using ZLIB).
6928 * Returns true if sucessful, false otherwise.
6929 */
decompress_section(struct section * s,unsigned char * compressed_data_buffer,size_t compressed_size,unsigned char ** ret_buf,size_t * ret_sz)6930 static bool decompress_section(struct section *s,
6931 unsigned char *compressed_data_buffer, size_t compressed_size,
6932 unsigned char **ret_buf, size_t *ret_sz)
6933 {
6934 GElf_Shdr sh;
6935
6936 if (gelf_getshdr(s->scn, &sh) == NULL)
6937 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1));
6938
6939 if (sh.sh_flags & SHF_COMPRESSED) {
6940 int ret;
6941 GElf_Chdr chdr;
6942 Elf64_Xword inflated_size;
6943 unsigned char *uncompressed_data_buffer = NULL;
6944 Elf64_Xword uncompressed_size;
6945 z_stream strm;
6946
6947 if (gelf_getchdr(s->scn, &chdr) == NULL)
6948 errx(EXIT_FAILURE, "gelf_getchdr() failed: %s", elf_errmsg(-1));
6949 if (chdr.ch_type != ELFCOMPRESS_ZLIB) {
6950 warnx("unknown compression type: %d", chdr.ch_type);
6951 return (false);
6952 }
6953
6954 inflated_size = 0;
6955 uncompressed_size = chdr.ch_size;
6956 uncompressed_data_buffer = malloc(uncompressed_size);
6957 compressed_data_buffer += sizeof(chdr);
6958 compressed_size -= sizeof(chdr);
6959
6960 strm.zalloc = Z_NULL;
6961 strm.zfree = Z_NULL;
6962 strm.opaque = Z_NULL;
6963 strm.avail_in = compressed_size;
6964 strm.avail_out = uncompressed_size;
6965 ret = inflateInit(&strm);
6966
6967 if (ret != Z_OK)
6968 goto fail;
6969 /*
6970 * The section can contain several compressed buffers,
6971 * so decompress in a loop until all data is inflated.
6972 */
6973 while (inflated_size < compressed_size) {
6974 strm.next_in = compressed_data_buffer + inflated_size;
6975 strm.next_out = uncompressed_data_buffer + inflated_size;
6976 ret = inflate(&strm, Z_FINISH);
6977 if (ret != Z_STREAM_END)
6978 goto fail;
6979 inflated_size = uncompressed_size - strm.avail_out;
6980 ret = inflateReset(&strm);
6981 if (ret != Z_OK)
6982 goto fail;
6983 }
6984 if (strm.avail_out != 0)
6985 warnx("Warning: wrong info in compression header.");
6986 ret = inflateEnd(&strm);
6987 if (ret != Z_OK)
6988 goto fail;
6989 *ret_buf = uncompressed_data_buffer;
6990 *ret_sz = uncompressed_size;
6991 return (true);
6992 fail:
6993 inflateEnd(&strm);
6994 if (strm.msg)
6995 warnx("%s", strm.msg);
6996 else
6997 warnx("ZLIB error: %d", ret);
6998 free(uncompressed_data_buffer);
6999 return (false);
7000 }
7001 return (false);
7002 }
7003
7004 static void
hex_dump(struct readelf * re)7005 hex_dump(struct readelf *re)
7006 {
7007 struct section *s;
7008 Elf_Data *d;
7009 uint8_t *buf, *new_buf;
7010 size_t sz, nbytes;
7011 uint64_t addr;
7012 int elferr, i, j;
7013
7014 for (i = 1; (size_t) i < re->shnum; i++) {
7015 new_buf = NULL;
7016 s = &re->sl[i];
7017 if (find_dumpop(re, (size_t) i, s->name, HEX_DUMP, -1) == NULL)
7018 continue;
7019 (void) elf_errno();
7020 if ((d = elf_getdata(s->scn, NULL)) == NULL &&
7021 (d = elf_rawdata(s->scn, NULL)) == NULL) {
7022 elferr = elf_errno();
7023 if (elferr != 0)
7024 warnx("elf_getdata failed: %s",
7025 elf_errmsg(elferr));
7026 continue;
7027 }
7028 (void) elf_errno();
7029 if (d->d_size <= 0 || d->d_buf == NULL) {
7030 printf("\nSection '%s' has no data to dump.\n",
7031 s->name);
7032 continue;
7033 }
7034 buf = d->d_buf;
7035 sz = d->d_size;
7036 addr = s->addr;
7037 if (re->options & RE_Z) {
7038 if (decompress_section(s, d->d_buf, d->d_size,
7039 &new_buf, &sz))
7040 buf = new_buf;
7041 }
7042 printf("\nHex dump of section '%s':\n", s->name);
7043 while (sz > 0) {
7044 printf(" 0x%8.8jx ", (uintmax_t)addr);
7045 nbytes = sz > 16? 16 : sz;
7046 for (j = 0; j < 16; j++) {
7047 if ((size_t)j < nbytes)
7048 printf("%2.2x", buf[j]);
7049 else
7050 printf(" ");
7051 if ((j & 3) == 3)
7052 printf(" ");
7053 }
7054 for (j = 0; (size_t)j < nbytes; j++) {
7055 if (isprint(buf[j]))
7056 printf("%c", buf[j]);
7057 else
7058 printf(".");
7059 }
7060 printf("\n");
7061 buf += nbytes;
7062 addr += nbytes;
7063 sz -= nbytes;
7064 }
7065 free(new_buf);
7066 }
7067 }
7068
7069 static void
str_dump(struct readelf * re)7070 str_dump(struct readelf *re)
7071 {
7072 struct section *s;
7073 Elf_Data *d;
7074 unsigned char *start, *end, *buf_end, *new_buf;
7075 unsigned int len;
7076 size_t sz;
7077 int i, j, elferr, found;
7078
7079 for (i = 1; (size_t) i < re->shnum; i++) {
7080 new_buf = NULL;
7081 s = &re->sl[i];
7082 if (find_dumpop(re, (size_t) i, s->name, STR_DUMP, -1) == NULL)
7083 continue;
7084 (void) elf_errno();
7085 if ((d = elf_getdata(s->scn, NULL)) == NULL &&
7086 (d = elf_rawdata(s->scn, NULL)) == NULL) {
7087 elferr = elf_errno();
7088 if (elferr != 0)
7089 warnx("elf_getdata failed: %s",
7090 elf_errmsg(elferr));
7091 continue;
7092 }
7093 (void) elf_errno();
7094 if (d->d_size <= 0 || d->d_buf == NULL) {
7095 printf("\nSection '%s' has no data to dump.\n",
7096 s->name);
7097 continue;
7098 }
7099 found = 0;
7100 start = d->d_buf;
7101 sz = d->d_size;
7102 if (re->options & RE_Z) {
7103 if (decompress_section(s, d->d_buf, d->d_size,
7104 &new_buf, &sz))
7105 start = new_buf;
7106 }
7107 buf_end = start + sz;
7108 printf("\nString dump of section '%s':\n", s->name);
7109 for (;;) {
7110 while (start < buf_end && !isprint(*start))
7111 start++;
7112 if (start >= buf_end)
7113 break;
7114 end = start + 1;
7115 while (end < buf_end && isprint(*end))
7116 end++;
7117 printf(" [%6lx] ",
7118 (long) (start - (unsigned char *) d->d_buf));
7119 len = end - start;
7120 for (j = 0; (unsigned int) j < len; j++)
7121 putchar(start[j]);
7122 putchar('\n');
7123 found = 1;
7124 if (end >= buf_end)
7125 break;
7126 start = end + 1;
7127 }
7128 free(new_buf);
7129 if (!found)
7130 printf(" No strings found in this section.");
7131 putchar('\n');
7132 }
7133 }
7134
7135 static void
load_sections(struct readelf * re)7136 load_sections(struct readelf *re)
7137 {
7138 struct section *s;
7139 const char *name;
7140 Elf_Scn *scn;
7141 GElf_Shdr sh;
7142 size_t shstrndx, ndx;
7143 int elferr;
7144
7145 /* Allocate storage for internal section list. */
7146 if (!elf_getshnum(re->elf, &re->shnum)) {
7147 warnx("elf_getshnum failed: %s", elf_errmsg(-1));
7148 return;
7149 }
7150 if (re->sl != NULL)
7151 free(re->sl);
7152 if ((re->sl = calloc(re->shnum, sizeof(*re->sl))) == NULL)
7153 err(EXIT_FAILURE, "calloc failed");
7154
7155 /* Get the index of .shstrtab section. */
7156 if (!elf_getshstrndx(re->elf, &shstrndx)) {
7157 warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
7158 return;
7159 }
7160
7161 if ((scn = elf_getscn(re->elf, 0)) == NULL)
7162 return;
7163
7164 (void) elf_errno();
7165 do {
7166 if (gelf_getshdr(scn, &sh) == NULL) {
7167 warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
7168 (void) elf_errno();
7169 continue;
7170 }
7171 if ((name = elf_strptr(re->elf, shstrndx, sh.sh_name)) == NULL) {
7172 (void) elf_errno();
7173 name = "<no-name>";
7174 }
7175 if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) {
7176 if ((elferr = elf_errno()) != 0) {
7177 warnx("elf_ndxscn failed: %s",
7178 elf_errmsg(elferr));
7179 continue;
7180 }
7181 }
7182 if (ndx >= re->shnum) {
7183 warnx("section index of '%s' out of range", name);
7184 continue;
7185 }
7186 if (sh.sh_link >= re->shnum)
7187 warnx("section link %llu of '%s' out of range",
7188 (unsigned long long)sh.sh_link, name);
7189 s = &re->sl[ndx];
7190 s->name = name;
7191 s->scn = scn;
7192 s->off = sh.sh_offset;
7193 s->sz = sh.sh_size;
7194 s->entsize = sh.sh_entsize;
7195 s->align = sh.sh_addralign;
7196 s->type = sh.sh_type;
7197 s->flags = sh.sh_flags;
7198 s->addr = sh.sh_addr;
7199 s->link = sh.sh_link;
7200 s->info = sh.sh_info;
7201 } while ((scn = elf_nextscn(re->elf, scn)) != NULL);
7202 elferr = elf_errno();
7203 if (elferr != 0)
7204 warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
7205 }
7206
7207 static void
unload_sections(struct readelf * re)7208 unload_sections(struct readelf *re)
7209 {
7210
7211 if (re->sl != NULL) {
7212 free(re->sl);
7213 re->sl = NULL;
7214 }
7215 re->shnum = 0;
7216 re->vd_s = NULL;
7217 re->vn_s = NULL;
7218 re->vs_s = NULL;
7219 re->vs = NULL;
7220 re->vs_sz = 0;
7221 if (re->ver != NULL) {
7222 free(re->ver);
7223 re->ver = NULL;
7224 re->ver_sz = 0;
7225 }
7226 }
7227
7228 static bool
dump_elf(struct readelf * re)7229 dump_elf(struct readelf *re)
7230 {
7231
7232 /* Fetch ELF header. No need to continue if it fails. */
7233 if (gelf_getehdr(re->elf, &re->ehdr) == NULL) {
7234 warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
7235 return (false);
7236 }
7237 if ((re->ec = gelf_getclass(re->elf)) == ELFCLASSNONE) {
7238 warnx("gelf_getclass failed: %s", elf_errmsg(-1));
7239 return (false);
7240 }
7241 if (re->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) {
7242 re->dw_read = _read_msb;
7243 re->dw_decode = _decode_msb;
7244 } else {
7245 re->dw_read = _read_lsb;
7246 re->dw_decode = _decode_lsb;
7247 }
7248
7249 if (re->options & ~RE_H)
7250 load_sections(re);
7251 if ((re->options & RE_VV) || (re->options & RE_S))
7252 search_ver(re);
7253 if (re->options & RE_H)
7254 dump_ehdr(re);
7255 if (re->options & RE_L)
7256 dump_phdr(re);
7257 if (re->options & RE_SS)
7258 dump_shdr(re);
7259 if (re->options & RE_G)
7260 dump_section_groups(re);
7261 if (re->options & RE_D)
7262 dump_dynamic(re);
7263 if (re->options & RE_R)
7264 dump_reloc(re);
7265 if (re->options & RE_S)
7266 dump_symtabs(re);
7267 if (re->options & RE_N)
7268 dump_notes(re);
7269 if (re->options & RE_II)
7270 dump_hash(re);
7271 if (re->options & RE_X)
7272 hex_dump(re);
7273 if (re->options & RE_P)
7274 str_dump(re);
7275 if (re->options & RE_VV)
7276 dump_ver(re);
7277 if (re->options & RE_AA)
7278 dump_arch_specific_info(re);
7279 if (re->options & RE_W)
7280 dump_dwarf(re);
7281 if (re->options & ~RE_H)
7282 unload_sections(re);
7283 return (true);
7284 }
7285
7286 static void
dump_dwarf(struct readelf * re)7287 dump_dwarf(struct readelf *re)
7288 {
7289 Dwarf_Error de;
7290 int error;
7291
7292 if (dwarf_elf_init(re->elf, DW_DLC_READ, NULL, NULL, &re->dbg, &de)) {
7293 if ((error = dwarf_errno(de)) != DW_DLE_DEBUG_INFO_NULL)
7294 errx(EXIT_FAILURE, "dwarf_elf_init failed: %s",
7295 dwarf_errmsg(de));
7296 return;
7297 }
7298
7299 if (re->dop & DW_A)
7300 dump_dwarf_abbrev(re);
7301 if (re->dop & DW_L)
7302 dump_dwarf_line(re);
7303 if (re->dop & DW_LL)
7304 dump_dwarf_line_decoded(re);
7305 if (re->dop & DW_I) {
7306 dump_dwarf_info(re, 0);
7307 dump_dwarf_info(re, 1);
7308 }
7309 if (re->dop & DW_P)
7310 dump_dwarf_pubnames(re);
7311 if (re->dop & DW_R)
7312 dump_dwarf_aranges(re);
7313 if (re->dop & DW_RR)
7314 dump_dwarf_ranges(re);
7315 if (re->dop & DW_M)
7316 dump_dwarf_macinfo(re);
7317 if (re->dop & DW_F)
7318 dump_dwarf_frame(re, 0);
7319 else if (re->dop & DW_FF)
7320 dump_dwarf_frame(re, 1);
7321 if (re->dop & DW_S)
7322 dump_dwarf_str(re);
7323 if (re->dop & DW_O)
7324 dump_dwarf_loclist(re);
7325
7326 dwarf_finish(re->dbg, &de);
7327 }
7328
7329 static bool
dump_ar(struct readelf * re,int fd)7330 dump_ar(struct readelf *re, int fd)
7331 {
7332 Elf_Arsym *arsym;
7333 Elf_Arhdr *arhdr;
7334 Elf_Cmd cmd;
7335 Elf *e;
7336 size_t sz;
7337 off_t off;
7338 int i;
7339
7340 re->ar = re->elf;
7341
7342 if (re->options & RE_C) {
7343 if ((arsym = elf_getarsym(re->ar, &sz)) == NULL) {
7344 warnx("elf_getarsym() failed: %s", elf_errmsg(-1));
7345 goto process_members;
7346 }
7347 printf("Index of archive %s: (%ju entries)\n", re->filename,
7348 (uintmax_t) sz - 1);
7349 off = 0;
7350 for (i = 0; (size_t) i < sz; i++) {
7351 if (arsym[i].as_name == NULL)
7352 break;
7353 if (arsym[i].as_off != off) {
7354 off = arsym[i].as_off;
7355 if (elf_rand(re->ar, off) != off) {
7356 warnx("elf_rand() failed: %s",
7357 elf_errmsg(-1));
7358 continue;
7359 }
7360 if ((e = elf_begin(fd, ELF_C_READ, re->ar)) ==
7361 NULL) {
7362 warnx("elf_begin() failed: %s",
7363 elf_errmsg(-1));
7364 continue;
7365 }
7366 if ((arhdr = elf_getarhdr(e)) == NULL) {
7367 warnx("elf_getarhdr() failed: %s",
7368 elf_errmsg(-1));
7369 elf_end(e);
7370 continue;
7371 }
7372 printf("Binary %s(%s) contains:\n",
7373 re->filename, arhdr->ar_name);
7374 elf_end(e);
7375 }
7376 printf("\t%s\n", arsym[i].as_name);
7377 }
7378 if (elf_rand(re->ar, SARMAG) != SARMAG) {
7379 warnx("elf_rand() failed: %s", elf_errmsg(-1));
7380 return (false);
7381 }
7382 }
7383
7384 process_members:
7385
7386 if ((re->options & ~RE_C) == 0)
7387 return (true);
7388
7389 cmd = ELF_C_READ;
7390 while ((re->elf = elf_begin(fd, cmd, re->ar)) != NULL) {
7391 if ((arhdr = elf_getarhdr(re->elf)) == NULL) {
7392 warnx("elf_getarhdr() failed: %s", elf_errmsg(-1));
7393 goto next_member;
7394 }
7395 if (strcmp(arhdr->ar_name, "/") == 0 ||
7396 strcmp(arhdr->ar_name, "//") == 0 ||
7397 strcmp(arhdr->ar_name, "__.SYMDEF") == 0)
7398 goto next_member;
7399 printf("\nFile: %s(%s)\n", re->filename, arhdr->ar_name);
7400 dump_elf(re);
7401
7402 next_member:
7403 cmd = elf_next(re->elf);
7404 elf_end(re->elf);
7405 }
7406 re->elf = re->ar;
7407 return (true);
7408 }
7409
7410 static bool
dump_object(struct readelf * re,int fd)7411 dump_object(struct readelf *re, int fd)
7412 {
7413 bool rv = false;
7414
7415 if ((re->flags & DISPLAY_FILENAME) != 0)
7416 printf("\nFile: %s\n", re->filename);
7417
7418 if ((re->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
7419 warnx("elf_begin() failed: %s", elf_errmsg(-1));
7420 goto done;
7421 }
7422
7423 switch (elf_kind(re->elf)) {
7424 case ELF_K_NONE:
7425 warnx("Not an ELF file.");
7426 goto done;
7427 case ELF_K_ELF:
7428 rv = dump_elf(re);
7429 break;
7430 case ELF_K_AR:
7431 rv = dump_ar(re, fd);
7432 break;
7433 default:
7434 warnx("Internal: libelf returned unknown elf kind.");
7435 }
7436
7437 done:
7438 elf_end(re->elf);
7439 return (rv);
7440 }
7441
7442 static void
add_dumpop(struct readelf * re,size_t si,const char * sn,int op,int t)7443 add_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t)
7444 {
7445 struct dumpop *d;
7446
7447 if ((d = find_dumpop(re, si, sn, -1, t)) == NULL) {
7448 if ((d = calloc(1, sizeof(*d))) == NULL)
7449 err(EXIT_FAILURE, "calloc failed");
7450 if (t == DUMP_BY_INDEX)
7451 d->u.si = si;
7452 else
7453 d->u.sn = sn;
7454 d->type = t;
7455 d->op = op;
7456 STAILQ_INSERT_TAIL(&re->v_dumpop, d, dumpop_list);
7457 } else
7458 d->op |= op;
7459 }
7460
7461 static struct dumpop *
find_dumpop(struct readelf * re,size_t si,const char * sn,int op,int t)7462 find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t)
7463 {
7464 struct dumpop *d;
7465
7466 STAILQ_FOREACH(d, &re->v_dumpop, dumpop_list) {
7467 if ((op == -1 || op & d->op) &&
7468 (t == -1 || (unsigned) t == d->type)) {
7469 if ((d->type == DUMP_BY_INDEX && d->u.si == si) ||
7470 (d->type == DUMP_BY_NAME && !strcmp(d->u.sn, sn)))
7471 return (d);
7472 }
7473 }
7474
7475 return (NULL);
7476 }
7477
7478 static struct {
7479 const char *ln;
7480 char sn;
7481 int value;
7482 } dwarf_op[] = {
7483 {"rawline", 'l', DW_L},
7484 {"decodedline", 'L', DW_LL},
7485 {"info", 'i', DW_I},
7486 {"abbrev", 'a', DW_A},
7487 {"pubnames", 'p', DW_P},
7488 {"aranges", 'r', DW_R},
7489 {"ranges", 'r', DW_R},
7490 {"Ranges", 'R', DW_RR},
7491 {"macro", 'm', DW_M},
7492 {"frames", 'f', DW_F},
7493 {"frames-interp", 'F', DW_FF},
7494 {"str", 's', DW_S},
7495 {"loc", 'o', DW_O},
7496 {NULL, 0, 0}
7497 };
7498
7499 static void
parse_dwarf_op_short(struct readelf * re,const char * op)7500 parse_dwarf_op_short(struct readelf *re, const char *op)
7501 {
7502 int i;
7503
7504 if (op == NULL) {
7505 re->dop |= DW_DEFAULT_OPTIONS;
7506 return;
7507 }
7508
7509 for (; *op != '\0'; op++) {
7510 for (i = 0; dwarf_op[i].ln != NULL; i++) {
7511 if (dwarf_op[i].sn == *op) {
7512 re->dop |= dwarf_op[i].value;
7513 break;
7514 }
7515 }
7516 }
7517 }
7518
7519 static void
parse_dwarf_op_long(struct readelf * re,const char * op)7520 parse_dwarf_op_long(struct readelf *re, const char *op)
7521 {
7522 char *p, *token, *bp;
7523 int i;
7524
7525 if (op == NULL) {
7526 re->dop |= DW_DEFAULT_OPTIONS;
7527 return;
7528 }
7529
7530 if ((p = strdup(op)) == NULL)
7531 err(EXIT_FAILURE, "strdup failed");
7532 bp = p;
7533
7534 while ((token = strsep(&p, ",")) != NULL) {
7535 for (i = 0; dwarf_op[i].ln != NULL; i++) {
7536 if (!strcmp(token, dwarf_op[i].ln)) {
7537 re->dop |= dwarf_op[i].value;
7538 break;
7539 }
7540 }
7541 }
7542
7543 free(bp);
7544 }
7545
7546 static uint64_t
_read_lsb(Elf_Data * d,uint64_t * offsetp,int bytes_to_read)7547 _read_lsb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read)
7548 {
7549 uint64_t ret;
7550 uint8_t *src;
7551
7552 src = (uint8_t *) d->d_buf + *offsetp;
7553
7554 ret = 0;
7555 switch (bytes_to_read) {
7556 case 8:
7557 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
7558 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
7559 /* FALLTHROUGH */
7560 case 4:
7561 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
7562 /* FALLTHROUGH */
7563 case 2:
7564 ret |= ((uint64_t) src[1]) << 8;
7565 /* FALLTHROUGH */
7566 case 1:
7567 ret |= src[0];
7568 break;
7569 default:
7570 return (0);
7571 }
7572
7573 *offsetp += bytes_to_read;
7574
7575 return (ret);
7576 }
7577
7578 static uint64_t
_read_msb(Elf_Data * d,uint64_t * offsetp,int bytes_to_read)7579 _read_msb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read)
7580 {
7581 uint64_t ret;
7582 uint8_t *src;
7583
7584 src = (uint8_t *) d->d_buf + *offsetp;
7585
7586 switch (bytes_to_read) {
7587 case 1:
7588 ret = src[0];
7589 break;
7590 case 2:
7591 ret = src[1] | ((uint64_t) src[0]) << 8;
7592 break;
7593 case 4:
7594 ret = src[3] | ((uint64_t) src[2]) << 8;
7595 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
7596 break;
7597 case 8:
7598 ret = src[7] | ((uint64_t) src[6]) << 8;
7599 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
7600 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
7601 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
7602 break;
7603 default:
7604 return (0);
7605 }
7606
7607 *offsetp += bytes_to_read;
7608
7609 return (ret);
7610 }
7611
7612 static uint64_t
_decode_lsb(uint8_t ** data,int bytes_to_read)7613 _decode_lsb(uint8_t **data, int bytes_to_read)
7614 {
7615 uint64_t ret;
7616 uint8_t *src;
7617
7618 src = *data;
7619
7620 ret = 0;
7621 switch (bytes_to_read) {
7622 case 8:
7623 ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
7624 ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
7625 /* FALLTHROUGH */
7626 case 4:
7627 ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
7628 /* FALLTHROUGH */
7629 case 2:
7630 ret |= ((uint64_t) src[1]) << 8;
7631 /* FALLTHROUGH */
7632 case 1:
7633 ret |= src[0];
7634 break;
7635 default:
7636 return (0);
7637 }
7638
7639 *data += bytes_to_read;
7640
7641 return (ret);
7642 }
7643
7644 static uint64_t
_decode_msb(uint8_t ** data,int bytes_to_read)7645 _decode_msb(uint8_t **data, int bytes_to_read)
7646 {
7647 uint64_t ret;
7648 uint8_t *src;
7649
7650 src = *data;
7651
7652 ret = 0;
7653 switch (bytes_to_read) {
7654 case 1:
7655 ret = src[0];
7656 break;
7657 case 2:
7658 ret = src[1] | ((uint64_t) src[0]) << 8;
7659 break;
7660 case 4:
7661 ret = src[3] | ((uint64_t) src[2]) << 8;
7662 ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24;
7663 break;
7664 case 8:
7665 ret = src[7] | ((uint64_t) src[6]) << 8;
7666 ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24;
7667 ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40;
7668 ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56;
7669 break;
7670 default:
7671 return (0);
7672 break;
7673 }
7674
7675 *data += bytes_to_read;
7676
7677 return (ret);
7678 }
7679
7680 static int64_t
_decode_sleb128(uint8_t ** dp,uint8_t * dpe)7681 _decode_sleb128(uint8_t **dp, uint8_t *dpe)
7682 {
7683 int64_t ret = 0;
7684 uint8_t b = 0;
7685 int shift = 0;
7686
7687 uint8_t *src = *dp;
7688
7689 do {
7690 if (src >= dpe)
7691 break;
7692 b = *src++;
7693 ret |= ((b & 0x7f) << shift);
7694 shift += 7;
7695 } while ((b & 0x80) != 0);
7696
7697 if (shift < 32 && (b & 0x40) != 0)
7698 ret |= (-1 << shift);
7699
7700 *dp = src;
7701
7702 return (ret);
7703 }
7704
7705 static uint64_t
_decode_uleb128(uint8_t ** dp,uint8_t * dpe)7706 _decode_uleb128(uint8_t **dp, uint8_t *dpe)
7707 {
7708 uint64_t ret = 0;
7709 uint8_t b;
7710 int shift = 0;
7711
7712 uint8_t *src = *dp;
7713
7714 do {
7715 if (src >= dpe)
7716 break;
7717 b = *src++;
7718 ret |= ((b & 0x7f) << shift);
7719 shift += 7;
7720 } while ((b & 0x80) != 0);
7721
7722 *dp = src;
7723
7724 return (ret);
7725 }
7726
7727 static void
readelf_version(void)7728 readelf_version(void)
7729 {
7730 (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(),
7731 elftc_version());
7732 exit(EXIT_SUCCESS);
7733 }
7734
7735 #define USAGE_MESSAGE "\
7736 Usage: %s [options] file...\n\
7737 Display information about ELF objects and ar(1) archives.\n\n\
7738 Options:\n\
7739 -a | --all Equivalent to specifying options '-dhIlrsASV'.\n\
7740 -c | --archive-index Print the archive symbol table for archives.\n\
7741 -d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\
7742 -e | --headers Print all headers in the object.\n\
7743 -g | --section-groups Print the contents of the section groups.\n\
7744 -h | --file-header Print the file header for the object.\n\
7745 -l | --program-headers Print the PHDR table for the object.\n\
7746 -n | --notes Print the contents of SHT_NOTE sections.\n\
7747 -p INDEX | --string-dump=INDEX\n\
7748 Print the contents of section at index INDEX.\n\
7749 -r | --relocs Print relocation information.\n\
7750 -s | --syms | --symbols Print symbol tables.\n\
7751 -t | --section-details Print additional information about sections.\n\
7752 -v | --version Print a version identifier and exit.\n\
7753 -w[afilmoprsFLR] | --debug-dump={abbrev,aranges,decodedline,frames,\n\
7754 frames-interp,info,loc,macro,pubnames,\n\
7755 ranges,Ranges,rawline,str}\n\
7756 Display DWARF information.\n\
7757 -x INDEX | --hex-dump=INDEX\n\
7758 Display contents of a section as hexadecimal.\n\
7759 -z | --decompress Decompress the contents of a section before displaying it.\n\
7760 -A | --arch-specific (accepted, but ignored)\n\
7761 -D | --use-dynamic Print the symbol table specified by the DT_SYMTAB\n\
7762 entry in the \".dynamic\" section.\n\
7763 -H | --help Print a help message.\n\
7764 -I | --histogram Print information on bucket list lengths for \n\
7765 hash sections.\n\
7766 -N | --full-section-name (accepted, but ignored)\n\
7767 -S | --sections | --section-headers\n\
7768 Print information about section headers.\n\
7769 -V | --version-info Print symbol versoning information.\n\
7770 -W | --wide Print information without wrapping long lines.\n"
7771
7772
7773 static void
readelf_usage(int status)7774 readelf_usage(int status)
7775 {
7776 fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
7777 exit(status);
7778 }
7779
7780 int
main(int argc,char ** argv)7781 main(int argc, char **argv)
7782 {
7783 struct readelf *re, re_storage;
7784 unsigned long si;
7785 int fd, opt, i, exit_code;
7786 char *ep;
7787
7788 re = &re_storage;
7789 memset(re, 0, sizeof(*re));
7790 STAILQ_INIT(&re->v_dumpop);
7791
7792 while ((opt = getopt_long(argc, argv, "AacDdegHhIi:lNnp:rSstuVvWw::x:z",
7793 longopts, NULL)) != -1) {
7794 switch(opt) {
7795 case '?':
7796 readelf_usage(EXIT_SUCCESS);
7797 break;
7798 case 'A':
7799 re->options |= RE_AA;
7800 break;
7801 case 'a':
7802 re->options |= RE_AA | RE_D | RE_G | RE_H | RE_II |
7803 RE_L | RE_N | RE_R | RE_SS | RE_S | RE_U | RE_VV;
7804 break;
7805 case 'c':
7806 re->options |= RE_C;
7807 break;
7808 case 'D':
7809 re->options |= RE_DD;
7810 break;
7811 case 'd':
7812 re->options |= RE_D;
7813 break;
7814 case 'e':
7815 re->options |= RE_H | RE_L | RE_SS;
7816 break;
7817 case 'g':
7818 re->options |= RE_G;
7819 break;
7820 case 'H':
7821 readelf_usage(EXIT_SUCCESS);
7822 break;
7823 case 'h':
7824 re->options |= RE_H;
7825 break;
7826 case 'I':
7827 re->options |= RE_II;
7828 break;
7829 case 'i':
7830 /* Not implemented yet. */
7831 break;
7832 case 'l':
7833 re->options |= RE_L;
7834 break;
7835 case 'N':
7836 re->options |= RE_NN;
7837 break;
7838 case 'n':
7839 re->options |= RE_N;
7840 break;
7841 case 'p':
7842 re->options |= RE_P;
7843 si = strtoul(optarg, &ep, 10);
7844 if (*ep == '\0')
7845 add_dumpop(re, (size_t) si, NULL, STR_DUMP,
7846 DUMP_BY_INDEX);
7847 else
7848 add_dumpop(re, 0, optarg, STR_DUMP,
7849 DUMP_BY_NAME);
7850 break;
7851 case 'r':
7852 re->options |= RE_R;
7853 break;
7854 case 'S':
7855 re->options |= RE_SS;
7856 break;
7857 case 's':
7858 re->options |= RE_S;
7859 break;
7860 case 't':
7861 re->options |= RE_SS | RE_T;
7862 break;
7863 case 'u':
7864 re->options |= RE_U;
7865 break;
7866 case 'V':
7867 re->options |= RE_VV;
7868 break;
7869 case 'v':
7870 readelf_version();
7871 break;
7872 case 'W':
7873 re->options |= RE_WW;
7874 break;
7875 case 'w':
7876 re->options |= RE_W;
7877 parse_dwarf_op_short(re, optarg);
7878 break;
7879 case 'x':
7880 re->options |= RE_X;
7881 si = strtoul(optarg, &ep, 10);
7882 if (*ep == '\0')
7883 add_dumpop(re, (size_t) si, NULL, HEX_DUMP,
7884 DUMP_BY_INDEX);
7885 else
7886 add_dumpop(re, 0, optarg, HEX_DUMP,
7887 DUMP_BY_NAME);
7888 break;
7889 case 'z':
7890 re->options |= RE_Z;
7891 break;
7892 case OPTION_DEBUG_DUMP:
7893 re->options |= RE_W;
7894 parse_dwarf_op_long(re, optarg);
7895 }
7896 }
7897
7898 argv += optind;
7899 argc -= optind;
7900
7901 if (argc == 0 || re->options == 0)
7902 readelf_usage(EXIT_FAILURE);
7903
7904 if (argc > 1)
7905 re->flags |= DISPLAY_FILENAME;
7906
7907 if (elf_version(EV_CURRENT) == EV_NONE)
7908 errx(EXIT_FAILURE, "ELF library initialization failed: %s",
7909 elf_errmsg(-1));
7910
7911 exit_code = EXIT_SUCCESS;
7912 for (i = 0; i < argc; i++) {
7913 re->filename = argv[i];
7914 fd = open(re->filename, O_RDONLY);
7915 if (fd < 0) {
7916 warn("open %s failed", re->filename);
7917 exit_code = EXIT_FAILURE;
7918 } else {
7919 if (!dump_object(re, fd))
7920 exit_code = EXIT_FAILURE;
7921 close(fd);
7922 }
7923 }
7924
7925 exit(exit_code);
7926 }
7927