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