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