1*3fe401a5SEd Maste /*- 2*3fe401a5SEd Maste * Copyright (c) 2007-2012 Kai Wang 3*3fe401a5SEd Maste * Copyright (c) 2003 David O'Brien. All rights reserved. 4*3fe401a5SEd Maste * Copyright (c) 2001 Jake Burkholder 5*3fe401a5SEd Maste * All rights reserved. 6*3fe401a5SEd Maste * 7*3fe401a5SEd Maste * Redistribution and use in source and binary forms, with or without 8*3fe401a5SEd Maste * modification, are permitted provided that the following conditions 9*3fe401a5SEd Maste * are met: 10*3fe401a5SEd Maste * 1. Redistributions of source code must retain the above copyright 11*3fe401a5SEd Maste * notice, this list of conditions and the following disclaimer. 12*3fe401a5SEd Maste * 2. Redistributions in binary form must reproduce the above copyright 13*3fe401a5SEd Maste * notice, this list of conditions and the following disclaimer in the 14*3fe401a5SEd Maste * documentation and/or other materials provided with the distribution. 15*3fe401a5SEd Maste * 16*3fe401a5SEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*3fe401a5SEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*3fe401a5SEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*3fe401a5SEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*3fe401a5SEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*3fe401a5SEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*3fe401a5SEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*3fe401a5SEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*3fe401a5SEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*3fe401a5SEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*3fe401a5SEd Maste * SUCH DAMAGE. 27*3fe401a5SEd Maste */ 28*3fe401a5SEd Maste 29*3fe401a5SEd Maste #include <sys/param.h> 30*3fe401a5SEd Maste #include <sys/queue.h> 31*3fe401a5SEd Maste #include <sys/stat.h> 32*3fe401a5SEd Maste 33*3fe401a5SEd Maste #include <ar.h> 34*3fe401a5SEd Maste #include <assert.h> 35*3fe401a5SEd Maste #include <err.h> 36*3fe401a5SEd Maste #include <fcntl.h> 37*3fe401a5SEd Maste #include <gelf.h> 38*3fe401a5SEd Maste #include <getopt.h> 39*3fe401a5SEd Maste #include <libelftc.h> 40*3fe401a5SEd Maste #include <inttypes.h> 41*3fe401a5SEd Maste #include <stdio.h> 42*3fe401a5SEd Maste #include <stdlib.h> 43*3fe401a5SEd Maste #include <string.h> 44*3fe401a5SEd Maste #include <unistd.h> 45*3fe401a5SEd Maste 46*3fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 47*3fe401a5SEd Maste #include <archive.h> 48*3fe401a5SEd Maste #include <archive_entry.h> 49*3fe401a5SEd Maste #endif 50*3fe401a5SEd Maste 51*3fe401a5SEd Maste #include "_elftc.h" 52*3fe401a5SEd Maste 53*3fe401a5SEd Maste ELFTC_VCSID("$Id: elfdump.c 3198 2015-05-14 18:36:19Z emaste $"); 54*3fe401a5SEd Maste 55*3fe401a5SEd Maste #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION) 56*3fe401a5SEd Maste #include "native-elf-format.h" 57*3fe401a5SEd Maste #if ELFTC_CLASS == ELFCLASS32 58*3fe401a5SEd Maste typedef Elf32_Nhdr Elf_Note; 59*3fe401a5SEd Maste #else 60*3fe401a5SEd Maste typedef Elf64_Nhdr Elf_Note; 61*3fe401a5SEd Maste #endif 62*3fe401a5SEd Maste #endif 63*3fe401a5SEd Maste 64*3fe401a5SEd Maste /* elfdump(1) options. */ 65*3fe401a5SEd Maste #define ED_DYN (1<<0) 66*3fe401a5SEd Maste #define ED_EHDR (1<<1) 67*3fe401a5SEd Maste #define ED_GOT (1<<2) 68*3fe401a5SEd Maste #define ED_HASH (1<<3) 69*3fe401a5SEd Maste #define ED_INTERP (1<<4) 70*3fe401a5SEd Maste #define ED_NOTE (1<<5) 71*3fe401a5SEd Maste #define ED_PHDR (1<<6) 72*3fe401a5SEd Maste #define ED_REL (1<<7) 73*3fe401a5SEd Maste #define ED_SHDR (1<<8) 74*3fe401a5SEd Maste #define ED_SYMTAB (1<<9) 75*3fe401a5SEd Maste #define ED_SYMVER (1<<10) 76*3fe401a5SEd Maste #define ED_CHECKSUM (1<<11) 77*3fe401a5SEd Maste #define ED_ALL ((1<<12)-1) 78*3fe401a5SEd Maste 79*3fe401a5SEd Maste /* elfdump(1) run control flags. */ 80*3fe401a5SEd Maste #define SOLARIS_FMT (1<<0) 81*3fe401a5SEd Maste #define PRINT_FILENAME (1<<1) 82*3fe401a5SEd Maste #define PRINT_ARSYM (1<<2) 83*3fe401a5SEd Maste #define ONLY_ARSYM (1<<3) 84*3fe401a5SEd Maste 85*3fe401a5SEd Maste /* Convenient print macro. */ 86*3fe401a5SEd Maste #define PRT(...) fprintf(ed->out, __VA_ARGS__) 87*3fe401a5SEd Maste 88*3fe401a5SEd Maste /* Internal data structure for sections. */ 89*3fe401a5SEd Maste struct section { 90*3fe401a5SEd Maste const char *name; /* section name */ 91*3fe401a5SEd Maste Elf_Scn *scn; /* section scn */ 92*3fe401a5SEd Maste uint64_t off; /* section offset */ 93*3fe401a5SEd Maste uint64_t sz; /* section size */ 94*3fe401a5SEd Maste uint64_t entsize; /* section entsize */ 95*3fe401a5SEd Maste uint64_t align; /* section alignment */ 96*3fe401a5SEd Maste uint64_t type; /* section type */ 97*3fe401a5SEd Maste uint64_t flags; /* section flags */ 98*3fe401a5SEd Maste uint64_t addr; /* section virtual addr */ 99*3fe401a5SEd Maste uint32_t link; /* section link ndx */ 100*3fe401a5SEd Maste uint32_t info; /* section info ndx */ 101*3fe401a5SEd Maste }; 102*3fe401a5SEd Maste 103*3fe401a5SEd Maste struct spec_name { 104*3fe401a5SEd Maste const char *name; 105*3fe401a5SEd Maste STAILQ_ENTRY(spec_name) sn_list; 106*3fe401a5SEd Maste }; 107*3fe401a5SEd Maste 108*3fe401a5SEd Maste /* Structure encapsulates the global data for readelf(1). */ 109*3fe401a5SEd Maste struct elfdump { 110*3fe401a5SEd Maste FILE *out; /* output redirection. */ 111*3fe401a5SEd Maste const char *filename; /* current processing file. */ 112*3fe401a5SEd Maste const char *archive; /* archive name */ 113*3fe401a5SEd Maste int options; /* command line options. */ 114*3fe401a5SEd Maste int flags; /* run control flags. */ 115*3fe401a5SEd Maste Elf *elf; /* underlying ELF descriptor. */ 116*3fe401a5SEd Maste #ifndef USE_LIBARCHIVE_AR 117*3fe401a5SEd Maste Elf *ar; /* ar(1) archive descriptor. */ 118*3fe401a5SEd Maste #endif 119*3fe401a5SEd Maste GElf_Ehdr ehdr; /* ELF header. */ 120*3fe401a5SEd Maste int ec; /* ELF class. */ 121*3fe401a5SEd Maste size_t shnum; /* #sections. */ 122*3fe401a5SEd Maste struct section *sl; /* list of sections. */ 123*3fe401a5SEd Maste STAILQ_HEAD(, spec_name) snl; /* list of names specified by -N. */ 124*3fe401a5SEd Maste }; 125*3fe401a5SEd Maste 126*3fe401a5SEd Maste /* Relocation entry. */ 127*3fe401a5SEd Maste struct rel_entry { 128*3fe401a5SEd Maste union { 129*3fe401a5SEd Maste GElf_Rel rel; 130*3fe401a5SEd Maste GElf_Rela rela; 131*3fe401a5SEd Maste } u_r; 132*3fe401a5SEd Maste const char *symn; 133*3fe401a5SEd Maste uint32_t type; 134*3fe401a5SEd Maste }; 135*3fe401a5SEd Maste 136*3fe401a5SEd Maste #if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS) 137*3fe401a5SEd Maste static __inline uint32_t 138*3fe401a5SEd Maste be32dec(const void *pp) 139*3fe401a5SEd Maste { 140*3fe401a5SEd Maste unsigned char const *p = (unsigned char const *)pp; 141*3fe401a5SEd Maste 142*3fe401a5SEd Maste return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); 143*3fe401a5SEd Maste } 144*3fe401a5SEd Maste 145*3fe401a5SEd Maste static __inline uint32_t 146*3fe401a5SEd Maste le32dec(const void *pp) 147*3fe401a5SEd Maste { 148*3fe401a5SEd Maste unsigned char const *p = (unsigned char const *)pp; 149*3fe401a5SEd Maste 150*3fe401a5SEd Maste return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); 151*3fe401a5SEd Maste } 152*3fe401a5SEd Maste #endif 153*3fe401a5SEd Maste 154*3fe401a5SEd Maste /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 155*3fe401a5SEd Maste static const char * 156*3fe401a5SEd Maste d_tags(uint64_t tag) 157*3fe401a5SEd Maste { 158*3fe401a5SEd Maste switch (tag) { 159*3fe401a5SEd Maste case 0: return "DT_NULL"; 160*3fe401a5SEd Maste case 1: return "DT_NEEDED"; 161*3fe401a5SEd Maste case 2: return "DT_PLTRELSZ"; 162*3fe401a5SEd Maste case 3: return "DT_PLTGOT"; 163*3fe401a5SEd Maste case 4: return "DT_HASH"; 164*3fe401a5SEd Maste case 5: return "DT_STRTAB"; 165*3fe401a5SEd Maste case 6: return "DT_SYMTAB"; 166*3fe401a5SEd Maste case 7: return "DT_RELA"; 167*3fe401a5SEd Maste case 8: return "DT_RELASZ"; 168*3fe401a5SEd Maste case 9: return "DT_RELAENT"; 169*3fe401a5SEd Maste case 10: return "DT_STRSZ"; 170*3fe401a5SEd Maste case 11: return "DT_SYMENT"; 171*3fe401a5SEd Maste case 12: return "DT_INIT"; 172*3fe401a5SEd Maste case 13: return "DT_FINI"; 173*3fe401a5SEd Maste case 14: return "DT_SONAME"; 174*3fe401a5SEd Maste case 15: return "DT_RPATH"; 175*3fe401a5SEd Maste case 16: return "DT_SYMBOLIC"; 176*3fe401a5SEd Maste case 17: return "DT_REL"; 177*3fe401a5SEd Maste case 18: return "DT_RELSZ"; 178*3fe401a5SEd Maste case 19: return "DT_RELENT"; 179*3fe401a5SEd Maste case 20: return "DT_PLTREL"; 180*3fe401a5SEd Maste case 21: return "DT_DEBUG"; 181*3fe401a5SEd Maste case 22: return "DT_TEXTREL"; 182*3fe401a5SEd Maste case 23: return "DT_JMPREL"; 183*3fe401a5SEd Maste case 24: return "DT_BIND_NOW"; 184*3fe401a5SEd Maste case 25: return "DT_INIT_ARRAY"; 185*3fe401a5SEd Maste case 26: return "DT_FINI_ARRAY"; 186*3fe401a5SEd Maste case 27: return "DT_INIT_ARRAYSZ"; 187*3fe401a5SEd Maste case 28: return "DT_FINI_ARRAYSZ"; 188*3fe401a5SEd Maste case 29: return "DT_RUNPATH"; 189*3fe401a5SEd Maste case 30: return "DT_FLAGS"; 190*3fe401a5SEd Maste case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ 191*3fe401a5SEd Maste case 33: return "DT_PREINIT_ARRAYSZ"; 192*3fe401a5SEd Maste /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 193*3fe401a5SEd Maste case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 194*3fe401a5SEd Maste case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 195*3fe401a5SEd Maste case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 196*3fe401a5SEd Maste case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 197*3fe401a5SEd Maste case 0x6ffffdf9: return "DT_PLTPADSZ"; 198*3fe401a5SEd Maste case 0x6ffffdfa: return "DT_MOVEENT"; 199*3fe401a5SEd Maste case 0x6ffffdfb: return "DT_MOVESZ"; 200*3fe401a5SEd Maste case 0x6ffffdfc: return "DT_FEATURE"; 201*3fe401a5SEd Maste case 0x6ffffdfd: return "DT_POSFLAG_1"; 202*3fe401a5SEd Maste case 0x6ffffdfe: return "DT_SYMINSZ"; 203*3fe401a5SEd Maste case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; 204*3fe401a5SEd Maste case 0x6ffffe00: return "DT_ADDRRNGLO"; 205*3fe401a5SEd Maste case 0x6ffffef5: return "DT_GNU_HASH"; 206*3fe401a5SEd Maste case 0x6ffffef8: return "DT_GNU_CONFLICT"; 207*3fe401a5SEd Maste case 0x6ffffef9: return "DT_GNU_LIBLIST"; 208*3fe401a5SEd Maste case 0x6ffffefa: return "DT_SUNW_CONFIG"; 209*3fe401a5SEd Maste case 0x6ffffefb: return "DT_SUNW_DEPAUDIT"; 210*3fe401a5SEd Maste case 0x6ffffefc: return "DT_SUNW_AUDIT"; 211*3fe401a5SEd Maste case 0x6ffffefd: return "DT_SUNW_PLTPAD"; 212*3fe401a5SEd Maste case 0x6ffffefe: return "DT_SUNW_MOVETAB"; 213*3fe401a5SEd Maste case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; 214*3fe401a5SEd Maste case 0x6ffffff9: return "DT_RELACOUNT"; 215*3fe401a5SEd Maste case 0x6ffffffa: return "DT_RELCOUNT"; 216*3fe401a5SEd Maste case 0x6ffffffb: return "DT_FLAGS_1"; 217*3fe401a5SEd Maste case 0x6ffffffc: return "DT_VERDEF"; 218*3fe401a5SEd Maste case 0x6ffffffd: return "DT_VERDEFNUM"; 219*3fe401a5SEd Maste case 0x6ffffffe: return "DT_VERNEED"; 220*3fe401a5SEd Maste case 0x6fffffff: return "DT_VERNEEDNUM"; 221*3fe401a5SEd Maste case 0x6ffffff0: return "DT_GNU_VERSYM"; 222*3fe401a5SEd Maste /* 0x70000000 - 0x7fffffff processor-specific semantics */ 223*3fe401a5SEd Maste case 0x70000000: return "DT_IA_64_PLT_RESERVE"; 224*3fe401a5SEd Maste case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; 225*3fe401a5SEd Maste case 0x7ffffffe: return "DT_SUNW_USED"; 226*3fe401a5SEd Maste case 0x7fffffff: return "DT_SUNW_FILTER"; 227*3fe401a5SEd Maste default: return "ERROR: TAG NOT DEFINED"; 228*3fe401a5SEd Maste } 229*3fe401a5SEd Maste } 230*3fe401a5SEd Maste 231*3fe401a5SEd Maste static const char * 232*3fe401a5SEd Maste e_machines(unsigned int mach) 233*3fe401a5SEd Maste { 234*3fe401a5SEd Maste static char machdesc[64]; 235*3fe401a5SEd Maste 236*3fe401a5SEd Maste switch (mach) { 237*3fe401a5SEd Maste case EM_NONE: return "EM_NONE"; 238*3fe401a5SEd Maste case EM_M32: return "EM_M32"; 239*3fe401a5SEd Maste case EM_SPARC: return "EM_SPARC"; 240*3fe401a5SEd Maste case EM_386: return "EM_386"; 241*3fe401a5SEd Maste case EM_68K: return "EM_68K"; 242*3fe401a5SEd Maste case EM_88K: return "EM_88K"; 243*3fe401a5SEd Maste case EM_IAMCU: return "EM_IAMCU"; 244*3fe401a5SEd Maste case EM_860: return "EM_860"; 245*3fe401a5SEd Maste case EM_MIPS: return "EM_MIPS"; 246*3fe401a5SEd Maste case EM_PPC: return "EM_PPC"; 247*3fe401a5SEd Maste case EM_ARM: return "EM_ARM"; 248*3fe401a5SEd Maste case EM_ALPHA: return "EM_ALPHA (legacy)"; 249*3fe401a5SEd Maste case EM_SPARCV9:return "EM_SPARCV9"; 250*3fe401a5SEd Maste case EM_IA_64: return "EM_IA_64"; 251*3fe401a5SEd Maste case EM_X86_64: return "EM_X86_64"; 252*3fe401a5SEd Maste } 253*3fe401a5SEd Maste snprintf(machdesc, sizeof(machdesc), 254*3fe401a5SEd Maste "(unknown machine) -- type 0x%x", mach); 255*3fe401a5SEd Maste return (machdesc); 256*3fe401a5SEd Maste } 257*3fe401a5SEd Maste 258*3fe401a5SEd Maste static const char *e_types[] = { 259*3fe401a5SEd Maste "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 260*3fe401a5SEd Maste }; 261*3fe401a5SEd Maste 262*3fe401a5SEd Maste static const char *ei_versions[] = { 263*3fe401a5SEd Maste "EV_NONE", "EV_CURRENT" 264*3fe401a5SEd Maste }; 265*3fe401a5SEd Maste 266*3fe401a5SEd Maste static const char *ei_classes[] = { 267*3fe401a5SEd Maste "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 268*3fe401a5SEd Maste }; 269*3fe401a5SEd Maste 270*3fe401a5SEd Maste static const char *ei_data[] = { 271*3fe401a5SEd Maste "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 272*3fe401a5SEd Maste }; 273*3fe401a5SEd Maste 274*3fe401a5SEd Maste static const char *ei_abis[] = { 275*3fe401a5SEd Maste "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 276*3fe401a5SEd Maste "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", 277*3fe401a5SEd Maste "ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", 278*3fe401a5SEd Maste "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD" 279*3fe401a5SEd Maste }; 280*3fe401a5SEd Maste 281*3fe401a5SEd Maste static const char *p_types[] = { 282*3fe401a5SEd Maste "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 283*3fe401a5SEd Maste "PT_SHLIB", "PT_PHDR", "PT_TLS" 284*3fe401a5SEd Maste }; 285*3fe401a5SEd Maste 286*3fe401a5SEd Maste static const char *p_flags[] = { 287*3fe401a5SEd Maste "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 288*3fe401a5SEd Maste "PF_X|PF_W|PF_R" 289*3fe401a5SEd Maste }; 290*3fe401a5SEd Maste 291*3fe401a5SEd Maste static const char * 292*3fe401a5SEd Maste sh_name(struct elfdump *ed, int ndx) 293*3fe401a5SEd Maste { 294*3fe401a5SEd Maste static char num[10]; 295*3fe401a5SEd Maste 296*3fe401a5SEd Maste switch (ndx) { 297*3fe401a5SEd Maste case SHN_UNDEF: return "UNDEF"; 298*3fe401a5SEd Maste case SHN_ABS: return "ABS"; 299*3fe401a5SEd Maste case SHN_COMMON: return "COMMON"; 300*3fe401a5SEd Maste default: 301*3fe401a5SEd Maste if ((uint64_t)ndx < ed->shnum) 302*3fe401a5SEd Maste return (ed->sl[ndx].name); 303*3fe401a5SEd Maste else { 304*3fe401a5SEd Maste snprintf(num, sizeof(num), "%d", ndx); 305*3fe401a5SEd Maste return (num); 306*3fe401a5SEd Maste } 307*3fe401a5SEd Maste } 308*3fe401a5SEd Maste } 309*3fe401a5SEd Maste 310*3fe401a5SEd Maste /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 311*3fe401a5SEd Maste static const char * 312*3fe401a5SEd Maste sh_types(u_int64_t sht) { 313*3fe401a5SEd Maste switch (sht) { 314*3fe401a5SEd Maste case 0: return "SHT_NULL"; 315*3fe401a5SEd Maste case 1: return "SHT_PROGBITS"; 316*3fe401a5SEd Maste case 2: return "SHT_SYMTAB"; 317*3fe401a5SEd Maste case 3: return "SHT_STRTAB"; 318*3fe401a5SEd Maste case 4: return "SHT_RELA"; 319*3fe401a5SEd Maste case 5: return "SHT_HASH"; 320*3fe401a5SEd Maste case 6: return "SHT_DYNAMIC"; 321*3fe401a5SEd Maste case 7: return "SHT_NOTE"; 322*3fe401a5SEd Maste case 8: return "SHT_NOBITS"; 323*3fe401a5SEd Maste case 9: return "SHT_REL"; 324*3fe401a5SEd Maste case 10: return "SHT_SHLIB"; 325*3fe401a5SEd Maste case 11: return "SHT_DYNSYM"; 326*3fe401a5SEd Maste case 14: return "SHT_INIT_ARRAY"; 327*3fe401a5SEd Maste case 15: return "SHT_FINI_ARRAY"; 328*3fe401a5SEd Maste case 16: return "SHT_PREINIT_ARRAY"; 329*3fe401a5SEd Maste case 17: return "SHT_GROUP"; 330*3fe401a5SEd Maste case 18: return "SHT_SYMTAB_SHNDX"; 331*3fe401a5SEd Maste /* 0x60000000 - 0x6fffffff operating system-specific semantics */ 332*3fe401a5SEd Maste case 0x6ffffff0: return "XXX:VERSYM"; 333*3fe401a5SEd Maste case 0x6ffffff6: return "SHT_GNU_HASH"; 334*3fe401a5SEd Maste case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 335*3fe401a5SEd Maste case 0x6ffffffc: return "XXX:VERDEF"; 336*3fe401a5SEd Maste case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; 337*3fe401a5SEd Maste case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; 338*3fe401a5SEd Maste case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; 339*3fe401a5SEd Maste /* 0x70000000 - 0x7fffffff processor-specific semantics */ 340*3fe401a5SEd Maste case 0x70000000: return "SHT_IA_64_EXT"; 341*3fe401a5SEd Maste case 0x70000001: return "SHT_IA_64_UNWIND"; 342*3fe401a5SEd Maste case 0x7ffffffd: return "XXX:AUXILIARY"; 343*3fe401a5SEd Maste case 0x7fffffff: return "XXX:FILTER"; 344*3fe401a5SEd Maste /* 0x80000000 - 0xffffffff application programs */ 345*3fe401a5SEd Maste default: return "ERROR: SHT NOT DEFINED"; 346*3fe401a5SEd Maste } 347*3fe401a5SEd Maste } 348*3fe401a5SEd Maste 349*3fe401a5SEd Maste /* 350*3fe401a5SEd Maste * Define known section flags. These flags are defined in the order 351*3fe401a5SEd Maste * they are to be printed out. 352*3fe401a5SEd Maste */ 353*3fe401a5SEd Maste #define DEFINE_SHFLAGS() \ 354*3fe401a5SEd Maste DEFINE_SHF(WRITE) \ 355*3fe401a5SEd Maste DEFINE_SHF(ALLOC) \ 356*3fe401a5SEd Maste DEFINE_SHF(EXECINSTR) \ 357*3fe401a5SEd Maste DEFINE_SHF(MERGE) \ 358*3fe401a5SEd Maste DEFINE_SHF(STRINGS) \ 359*3fe401a5SEd Maste DEFINE_SHF(INFO_LINK) \ 360*3fe401a5SEd Maste DEFINE_SHF(LINK_ORDER) \ 361*3fe401a5SEd Maste DEFINE_SHF(OS_NONCONFORMING) \ 362*3fe401a5SEd Maste DEFINE_SHF(GROUP) \ 363*3fe401a5SEd Maste DEFINE_SHF(TLS) 364*3fe401a5SEd Maste 365*3fe401a5SEd Maste #undef DEFINE_SHF 366*3fe401a5SEd Maste #define DEFINE_SHF(F) "SHF_" #F "|" 367*3fe401a5SEd Maste #define ALLSHFLAGS DEFINE_SHFLAGS() 368*3fe401a5SEd Maste 369*3fe401a5SEd Maste static const char * 370*3fe401a5SEd Maste sh_flags(uint64_t shf) 371*3fe401a5SEd Maste { 372*3fe401a5SEd Maste static char flg[sizeof(ALLSHFLAGS)+1]; 373*3fe401a5SEd Maste 374*3fe401a5SEd Maste flg[0] = '\0'; 375*3fe401a5SEd Maste 376*3fe401a5SEd Maste #undef DEFINE_SHF 377*3fe401a5SEd Maste #define DEFINE_SHF(N) \ 378*3fe401a5SEd Maste if (shf & SHF_##N) \ 379*3fe401a5SEd Maste strcat(flg, "SHF_" #N "|"); \ 380*3fe401a5SEd Maste 381*3fe401a5SEd Maste DEFINE_SHFLAGS() 382*3fe401a5SEd Maste 383*3fe401a5SEd Maste flg[strlen(flg) - 1] = '\0'; /* Remove the trailing "|". */ 384*3fe401a5SEd Maste 385*3fe401a5SEd Maste return (flg); 386*3fe401a5SEd Maste } 387*3fe401a5SEd Maste 388*3fe401a5SEd Maste static const char *st_types[] = { 389*3fe401a5SEd Maste "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE", 390*3fe401a5SEd Maste "STT_COMMON", "STT_TLS" 391*3fe401a5SEd Maste }; 392*3fe401a5SEd Maste 393*3fe401a5SEd Maste static const char *st_types_S[] = { 394*3fe401a5SEd Maste "NOTY", "OBJT", "FUNC", "SECT", "FILE" 395*3fe401a5SEd Maste }; 396*3fe401a5SEd Maste 397*3fe401a5SEd Maste static const char *st_bindings[] = { 398*3fe401a5SEd Maste "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 399*3fe401a5SEd Maste }; 400*3fe401a5SEd Maste 401*3fe401a5SEd Maste static const char *st_bindings_S[] = { 402*3fe401a5SEd Maste "LOCL", "GLOB", "WEAK" 403*3fe401a5SEd Maste }; 404*3fe401a5SEd Maste 405*3fe401a5SEd Maste static unsigned char st_others[] = { 406*3fe401a5SEd Maste 'D', 'I', 'H', 'P' 407*3fe401a5SEd Maste }; 408*3fe401a5SEd Maste 409*3fe401a5SEd Maste static const char * 410*3fe401a5SEd Maste r_type(unsigned int mach, unsigned int type) 411*3fe401a5SEd Maste { 412*3fe401a5SEd Maste switch(mach) { 413*3fe401a5SEd Maste case EM_NONE: return ""; 414*3fe401a5SEd Maste case EM_386: 415*3fe401a5SEd Maste case EM_IAMCU: 416*3fe401a5SEd Maste switch(type) { 417*3fe401a5SEd Maste case 0: return "R_386_NONE"; 418*3fe401a5SEd Maste case 1: return "R_386_32"; 419*3fe401a5SEd Maste case 2: return "R_386_PC32"; 420*3fe401a5SEd Maste case 3: return "R_386_GOT32"; 421*3fe401a5SEd Maste case 4: return "R_386_PLT32"; 422*3fe401a5SEd Maste case 5: return "R_386_COPY"; 423*3fe401a5SEd Maste case 6: return "R_386_GLOB_DAT"; 424*3fe401a5SEd Maste case 7: return "R_386_JMP_SLOT"; 425*3fe401a5SEd Maste case 8: return "R_386_RELATIVE"; 426*3fe401a5SEd Maste case 9: return "R_386_GOTOFF"; 427*3fe401a5SEd Maste case 10: return "R_386_GOTPC"; 428*3fe401a5SEd Maste case 14: return "R_386_TLS_TPOFF"; 429*3fe401a5SEd Maste case 15: return "R_386_TLS_IE"; 430*3fe401a5SEd Maste case 16: return "R_386_TLS_GOTIE"; 431*3fe401a5SEd Maste case 17: return "R_386_TLS_LE"; 432*3fe401a5SEd Maste case 18: return "R_386_TLS_GD"; 433*3fe401a5SEd Maste case 19: return "R_386_TLS_LDM"; 434*3fe401a5SEd Maste case 24: return "R_386_TLS_GD_32"; 435*3fe401a5SEd Maste case 25: return "R_386_TLS_GD_PUSH"; 436*3fe401a5SEd Maste case 26: return "R_386_TLS_GD_CALL"; 437*3fe401a5SEd Maste case 27: return "R_386_TLS_GD_POP"; 438*3fe401a5SEd Maste case 28: return "R_386_TLS_LDM_32"; 439*3fe401a5SEd Maste case 29: return "R_386_TLS_LDM_PUSH"; 440*3fe401a5SEd Maste case 30: return "R_386_TLS_LDM_CALL"; 441*3fe401a5SEd Maste case 31: return "R_386_TLS_LDM_POP"; 442*3fe401a5SEd Maste case 32: return "R_386_TLS_LDO_32"; 443*3fe401a5SEd Maste case 33: return "R_386_TLS_IE_32"; 444*3fe401a5SEd Maste case 34: return "R_386_TLS_LE_32"; 445*3fe401a5SEd Maste case 35: return "R_386_TLS_DTPMOD32"; 446*3fe401a5SEd Maste case 36: return "R_386_TLS_DTPOFF32"; 447*3fe401a5SEd Maste case 37: return "R_386_TLS_TPOFF32"; 448*3fe401a5SEd Maste default: return ""; 449*3fe401a5SEd Maste } 450*3fe401a5SEd Maste case EM_ARM: 451*3fe401a5SEd Maste switch(type) { 452*3fe401a5SEd Maste case 0: return "R_ARM_NONE"; 453*3fe401a5SEd Maste case 1: return "R_ARM_PC24"; 454*3fe401a5SEd Maste case 2: return "R_ARM_ABS32"; 455*3fe401a5SEd Maste case 3: return "R_ARM_REL32"; 456*3fe401a5SEd Maste case 4: return "R_ARM_PC13"; 457*3fe401a5SEd Maste case 5: return "R_ARM_ABS16"; 458*3fe401a5SEd Maste case 6: return "R_ARM_ABS12"; 459*3fe401a5SEd Maste case 7: return "R_ARM_THM_ABS5"; 460*3fe401a5SEd Maste case 8: return "R_ARM_ABS8"; 461*3fe401a5SEd Maste case 9: return "R_ARM_SBREL32"; 462*3fe401a5SEd Maste case 10: return "R_ARM_THM_PC22"; 463*3fe401a5SEd Maste case 11: return "R_ARM_THM_PC8"; 464*3fe401a5SEd Maste case 12: return "R_ARM_AMP_VCALL9"; 465*3fe401a5SEd Maste case 13: return "R_ARM_SWI24"; 466*3fe401a5SEd Maste case 14: return "R_ARM_THM_SWI8"; 467*3fe401a5SEd Maste case 15: return "R_ARM_XPC25"; 468*3fe401a5SEd Maste case 16: return "R_ARM_THM_XPC22"; 469*3fe401a5SEd Maste case 20: return "R_ARM_COPY"; 470*3fe401a5SEd Maste case 21: return "R_ARM_GLOB_DAT"; 471*3fe401a5SEd Maste case 22: return "R_ARM_JUMP_SLOT"; 472*3fe401a5SEd Maste case 23: return "R_ARM_RELATIVE"; 473*3fe401a5SEd Maste case 24: return "R_ARM_GOTOFF"; 474*3fe401a5SEd Maste case 25: return "R_ARM_GOTPC"; 475*3fe401a5SEd Maste case 26: return "R_ARM_GOT32"; 476*3fe401a5SEd Maste case 27: return "R_ARM_PLT32"; 477*3fe401a5SEd Maste case 100: return "R_ARM_GNU_VTENTRY"; 478*3fe401a5SEd Maste case 101: return "R_ARM_GNU_VTINHERIT"; 479*3fe401a5SEd Maste case 250: return "R_ARM_RSBREL32"; 480*3fe401a5SEd Maste case 251: return "R_ARM_THM_RPC22"; 481*3fe401a5SEd Maste case 252: return "R_ARM_RREL32"; 482*3fe401a5SEd Maste case 253: return "R_ARM_RABS32"; 483*3fe401a5SEd Maste case 254: return "R_ARM_RPC24"; 484*3fe401a5SEd Maste case 255: return "R_ARM_RBASE"; 485*3fe401a5SEd Maste default: return ""; 486*3fe401a5SEd Maste } 487*3fe401a5SEd Maste case EM_IA_64: 488*3fe401a5SEd Maste switch(type) { 489*3fe401a5SEd Maste case 0: return "R_IA_64_NONE"; 490*3fe401a5SEd Maste case 33: return "R_IA_64_IMM14"; 491*3fe401a5SEd Maste case 34: return "R_IA_64_IMM22"; 492*3fe401a5SEd Maste case 35: return "R_IA_64_IMM64"; 493*3fe401a5SEd Maste case 36: return "R_IA_64_DIR32MSB"; 494*3fe401a5SEd Maste case 37: return "R_IA_64_DIR32LSB"; 495*3fe401a5SEd Maste case 38: return "R_IA_64_DIR64MSB"; 496*3fe401a5SEd Maste case 39: return "R_IA_64_DIR64LSB"; 497*3fe401a5SEd Maste case 42: return "R_IA_64_GPREL22"; 498*3fe401a5SEd Maste case 43: return "R_IA_64_GPREL64I"; 499*3fe401a5SEd Maste case 44: return "R_IA_64_GPREL32MSB"; 500*3fe401a5SEd Maste case 45: return "R_IA_64_GPREL32LSB"; 501*3fe401a5SEd Maste case 46: return "R_IA_64_GPREL64MSB"; 502*3fe401a5SEd Maste case 47: return "R_IA_64_GPREL64LSB"; 503*3fe401a5SEd Maste case 50: return "R_IA_64_LTOFF22"; 504*3fe401a5SEd Maste case 51: return "R_IA_64_LTOFF64I"; 505*3fe401a5SEd Maste case 58: return "R_IA_64_PLTOFF22"; 506*3fe401a5SEd Maste case 59: return "R_IA_64_PLTOFF64I"; 507*3fe401a5SEd Maste case 62: return "R_IA_64_PLTOFF64MSB"; 508*3fe401a5SEd Maste case 63: return "R_IA_64_PLTOFF64LSB"; 509*3fe401a5SEd Maste case 67: return "R_IA_64_FPTR64I"; 510*3fe401a5SEd Maste case 68: return "R_IA_64_FPTR32MSB"; 511*3fe401a5SEd Maste case 69: return "R_IA_64_FPTR32LSB"; 512*3fe401a5SEd Maste case 70: return "R_IA_64_FPTR64MSB"; 513*3fe401a5SEd Maste case 71: return "R_IA_64_FPTR64LSB"; 514*3fe401a5SEd Maste case 72: return "R_IA_64_PCREL60B"; 515*3fe401a5SEd Maste case 73: return "R_IA_64_PCREL21B"; 516*3fe401a5SEd Maste case 74: return "R_IA_64_PCREL21M"; 517*3fe401a5SEd Maste case 75: return "R_IA_64_PCREL21F"; 518*3fe401a5SEd Maste case 76: return "R_IA_64_PCREL32MSB"; 519*3fe401a5SEd Maste case 77: return "R_IA_64_PCREL32LSB"; 520*3fe401a5SEd Maste case 78: return "R_IA_64_PCREL64MSB"; 521*3fe401a5SEd Maste case 79: return "R_IA_64_PCREL64LSB"; 522*3fe401a5SEd Maste case 82: return "R_IA_64_LTOFF_FPTR22"; 523*3fe401a5SEd Maste case 83: return "R_IA_64_LTOFF_FPTR64I"; 524*3fe401a5SEd Maste case 84: return "R_IA_64_LTOFF_FPTR32MSB"; 525*3fe401a5SEd Maste case 85: return "R_IA_64_LTOFF_FPTR32LSB"; 526*3fe401a5SEd Maste case 86: return "R_IA_64_LTOFF_FPTR64MSB"; 527*3fe401a5SEd Maste case 87: return "R_IA_64_LTOFF_FPTR64LSB"; 528*3fe401a5SEd Maste case 92: return "R_IA_64_SEGREL32MSB"; 529*3fe401a5SEd Maste case 93: return "R_IA_64_SEGREL32LSB"; 530*3fe401a5SEd Maste case 94: return "R_IA_64_SEGREL64MSB"; 531*3fe401a5SEd Maste case 95: return "R_IA_64_SEGREL64LSB"; 532*3fe401a5SEd Maste case 100: return "R_IA_64_SECREL32MSB"; 533*3fe401a5SEd Maste case 101: return "R_IA_64_SECREL32LSB"; 534*3fe401a5SEd Maste case 102: return "R_IA_64_SECREL64MSB"; 535*3fe401a5SEd Maste case 103: return "R_IA_64_SECREL64LSB"; 536*3fe401a5SEd Maste case 108: return "R_IA_64_REL32MSB"; 537*3fe401a5SEd Maste case 109: return "R_IA_64_REL32LSB"; 538*3fe401a5SEd Maste case 110: return "R_IA_64_REL64MSB"; 539*3fe401a5SEd Maste case 111: return "R_IA_64_REL64LSB"; 540*3fe401a5SEd Maste case 116: return "R_IA_64_LTV32MSB"; 541*3fe401a5SEd Maste case 117: return "R_IA_64_LTV32LSB"; 542*3fe401a5SEd Maste case 118: return "R_IA_64_LTV64MSB"; 543*3fe401a5SEd Maste case 119: return "R_IA_64_LTV64LSB"; 544*3fe401a5SEd Maste case 121: return "R_IA_64_PCREL21BI"; 545*3fe401a5SEd Maste case 122: return "R_IA_64_PCREL22"; 546*3fe401a5SEd Maste case 123: return "R_IA_64_PCREL64I"; 547*3fe401a5SEd Maste case 128: return "R_IA_64_IPLTMSB"; 548*3fe401a5SEd Maste case 129: return "R_IA_64_IPLTLSB"; 549*3fe401a5SEd Maste case 133: return "R_IA_64_SUB"; 550*3fe401a5SEd Maste case 134: return "R_IA_64_LTOFF22X"; 551*3fe401a5SEd Maste case 135: return "R_IA_64_LDXMOV"; 552*3fe401a5SEd Maste case 145: return "R_IA_64_TPREL14"; 553*3fe401a5SEd Maste case 146: return "R_IA_64_TPREL22"; 554*3fe401a5SEd Maste case 147: return "R_IA_64_TPREL64I"; 555*3fe401a5SEd Maste case 150: return "R_IA_64_TPREL64MSB"; 556*3fe401a5SEd Maste case 151: return "R_IA_64_TPREL64LSB"; 557*3fe401a5SEd Maste case 154: return "R_IA_64_LTOFF_TPREL22"; 558*3fe401a5SEd Maste case 166: return "R_IA_64_DTPMOD64MSB"; 559*3fe401a5SEd Maste case 167: return "R_IA_64_DTPMOD64LSB"; 560*3fe401a5SEd Maste case 170: return "R_IA_64_LTOFF_DTPMOD22"; 561*3fe401a5SEd Maste case 177: return "R_IA_64_DTPREL14"; 562*3fe401a5SEd Maste case 178: return "R_IA_64_DTPREL22"; 563*3fe401a5SEd Maste case 179: return "R_IA_64_DTPREL64I"; 564*3fe401a5SEd Maste case 180: return "R_IA_64_DTPREL32MSB"; 565*3fe401a5SEd Maste case 181: return "R_IA_64_DTPREL32LSB"; 566*3fe401a5SEd Maste case 182: return "R_IA_64_DTPREL64MSB"; 567*3fe401a5SEd Maste case 183: return "R_IA_64_DTPREL64LSB"; 568*3fe401a5SEd Maste case 186: return "R_IA_64_LTOFF_DTPREL22"; 569*3fe401a5SEd Maste default: return ""; 570*3fe401a5SEd Maste } 571*3fe401a5SEd Maste case EM_MIPS: 572*3fe401a5SEd Maste switch(type) { 573*3fe401a5SEd Maste case 0: return "R_MIPS_NONE"; 574*3fe401a5SEd Maste case 1: return "R_MIPS_16"; 575*3fe401a5SEd Maste case 2: return "R_MIPS_32"; 576*3fe401a5SEd Maste case 3: return "R_MIPS_REL32"; 577*3fe401a5SEd Maste case 4: return "R_MIPS_26"; 578*3fe401a5SEd Maste case 5: return "R_MIPS_HI16"; 579*3fe401a5SEd Maste case 6: return "R_MIPS_LO16"; 580*3fe401a5SEd Maste case 7: return "R_MIPS_GPREL16"; 581*3fe401a5SEd Maste case 8: return "R_MIPS_LITERAL"; 582*3fe401a5SEd Maste case 9: return "R_MIPS_GOT16"; 583*3fe401a5SEd Maste case 10: return "R_MIPS_PC16"; 584*3fe401a5SEd Maste case 11: return "R_MIPS_CALL16"; 585*3fe401a5SEd Maste case 12: return "R_MIPS_GPREL32"; 586*3fe401a5SEd Maste case 21: return "R_MIPS_GOTHI16"; 587*3fe401a5SEd Maste case 22: return "R_MIPS_GOTLO16"; 588*3fe401a5SEd Maste case 30: return "R_MIPS_CALLHI16"; 589*3fe401a5SEd Maste case 31: return "R_MIPS_CALLLO16"; 590*3fe401a5SEd Maste default: return ""; 591*3fe401a5SEd Maste } 592*3fe401a5SEd Maste case EM_PPC: 593*3fe401a5SEd Maste switch(type) { 594*3fe401a5SEd Maste case 0: return "R_PPC_NONE"; 595*3fe401a5SEd Maste case 1: return "R_PPC_ADDR32"; 596*3fe401a5SEd Maste case 2: return "R_PPC_ADDR24"; 597*3fe401a5SEd Maste case 3: return "R_PPC_ADDR16"; 598*3fe401a5SEd Maste case 4: return "R_PPC_ADDR16_LO"; 599*3fe401a5SEd Maste case 5: return "R_PPC_ADDR16_HI"; 600*3fe401a5SEd Maste case 6: return "R_PPC_ADDR16_HA"; 601*3fe401a5SEd Maste case 7: return "R_PPC_ADDR14"; 602*3fe401a5SEd Maste case 8: return "R_PPC_ADDR14_BRTAKEN"; 603*3fe401a5SEd Maste case 9: return "R_PPC_ADDR14_BRNTAKEN"; 604*3fe401a5SEd Maste case 10: return "R_PPC_REL24"; 605*3fe401a5SEd Maste case 11: return "R_PPC_REL14"; 606*3fe401a5SEd Maste case 12: return "R_PPC_REL14_BRTAKEN"; 607*3fe401a5SEd Maste case 13: return "R_PPC_REL14_BRNTAKEN"; 608*3fe401a5SEd Maste case 14: return "R_PPC_GOT16"; 609*3fe401a5SEd Maste case 15: return "R_PPC_GOT16_LO"; 610*3fe401a5SEd Maste case 16: return "R_PPC_GOT16_HI"; 611*3fe401a5SEd Maste case 17: return "R_PPC_GOT16_HA"; 612*3fe401a5SEd Maste case 18: return "R_PPC_PLTREL24"; 613*3fe401a5SEd Maste case 19: return "R_PPC_COPY"; 614*3fe401a5SEd Maste case 20: return "R_PPC_GLOB_DAT"; 615*3fe401a5SEd Maste case 21: return "R_PPC_JMP_SLOT"; 616*3fe401a5SEd Maste case 22: return "R_PPC_RELATIVE"; 617*3fe401a5SEd Maste case 23: return "R_PPC_LOCAL24PC"; 618*3fe401a5SEd Maste case 24: return "R_PPC_UADDR32"; 619*3fe401a5SEd Maste case 25: return "R_PPC_UADDR16"; 620*3fe401a5SEd Maste case 26: return "R_PPC_REL32"; 621*3fe401a5SEd Maste case 27: return "R_PPC_PLT32"; 622*3fe401a5SEd Maste case 28: return "R_PPC_PLTREL32"; 623*3fe401a5SEd Maste case 29: return "R_PPC_PLT16_LO"; 624*3fe401a5SEd Maste case 30: return "R_PPC_PLT16_HI"; 625*3fe401a5SEd Maste case 31: return "R_PPC_PLT16_HA"; 626*3fe401a5SEd Maste case 32: return "R_PPC_SDAREL16"; 627*3fe401a5SEd Maste case 33: return "R_PPC_SECTOFF"; 628*3fe401a5SEd Maste case 34: return "R_PPC_SECTOFF_LO"; 629*3fe401a5SEd Maste case 35: return "R_PPC_SECTOFF_HI"; 630*3fe401a5SEd Maste case 36: return "R_PPC_SECTOFF_HA"; 631*3fe401a5SEd Maste case 67: return "R_PPC_TLS"; 632*3fe401a5SEd Maste case 68: return "R_PPC_DTPMOD32"; 633*3fe401a5SEd Maste case 69: return "R_PPC_TPREL16"; 634*3fe401a5SEd Maste case 70: return "R_PPC_TPREL16_LO"; 635*3fe401a5SEd Maste case 71: return "R_PPC_TPREL16_HI"; 636*3fe401a5SEd Maste case 72: return "R_PPC_TPREL16_HA"; 637*3fe401a5SEd Maste case 73: return "R_PPC_TPREL32"; 638*3fe401a5SEd Maste case 74: return "R_PPC_DTPREL16"; 639*3fe401a5SEd Maste case 75: return "R_PPC_DTPREL16_LO"; 640*3fe401a5SEd Maste case 76: return "R_PPC_DTPREL16_HI"; 641*3fe401a5SEd Maste case 77: return "R_PPC_DTPREL16_HA"; 642*3fe401a5SEd Maste case 78: return "R_PPC_DTPREL32"; 643*3fe401a5SEd Maste case 79: return "R_PPC_GOT_TLSGD16"; 644*3fe401a5SEd Maste case 80: return "R_PPC_GOT_TLSGD16_LO"; 645*3fe401a5SEd Maste case 81: return "R_PPC_GOT_TLSGD16_HI"; 646*3fe401a5SEd Maste case 82: return "R_PPC_GOT_TLSGD16_HA"; 647*3fe401a5SEd Maste case 83: return "R_PPC_GOT_TLSLD16"; 648*3fe401a5SEd Maste case 84: return "R_PPC_GOT_TLSLD16_LO"; 649*3fe401a5SEd Maste case 85: return "R_PPC_GOT_TLSLD16_HI"; 650*3fe401a5SEd Maste case 86: return "R_PPC_GOT_TLSLD16_HA"; 651*3fe401a5SEd Maste case 87: return "R_PPC_GOT_TPREL16"; 652*3fe401a5SEd Maste case 88: return "R_PPC_GOT_TPREL16_LO"; 653*3fe401a5SEd Maste case 89: return "R_PPC_GOT_TPREL16_HI"; 654*3fe401a5SEd Maste case 90: return "R_PPC_GOT_TPREL16_HA"; 655*3fe401a5SEd Maste case 101: return "R_PPC_EMB_NADDR32"; 656*3fe401a5SEd Maste case 102: return "R_PPC_EMB_NADDR16"; 657*3fe401a5SEd Maste case 103: return "R_PPC_EMB_NADDR16_LO"; 658*3fe401a5SEd Maste case 104: return "R_PPC_EMB_NADDR16_HI"; 659*3fe401a5SEd Maste case 105: return "R_PPC_EMB_NADDR16_HA"; 660*3fe401a5SEd Maste case 106: return "R_PPC_EMB_SDAI16"; 661*3fe401a5SEd Maste case 107: return "R_PPC_EMB_SDA2I16"; 662*3fe401a5SEd Maste case 108: return "R_PPC_EMB_SDA2REL"; 663*3fe401a5SEd Maste case 109: return "R_PPC_EMB_SDA21"; 664*3fe401a5SEd Maste case 110: return "R_PPC_EMB_MRKREF"; 665*3fe401a5SEd Maste case 111: return "R_PPC_EMB_RELSEC16"; 666*3fe401a5SEd Maste case 112: return "R_PPC_EMB_RELST_LO"; 667*3fe401a5SEd Maste case 113: return "R_PPC_EMB_RELST_HI"; 668*3fe401a5SEd Maste case 114: return "R_PPC_EMB_RELST_HA"; 669*3fe401a5SEd Maste case 115: return "R_PPC_EMB_BIT_FLD"; 670*3fe401a5SEd Maste case 116: return "R_PPC_EMB_RELSDA"; 671*3fe401a5SEd Maste default: return ""; 672*3fe401a5SEd Maste } 673*3fe401a5SEd Maste case EM_SPARC: 674*3fe401a5SEd Maste case EM_SPARCV9: 675*3fe401a5SEd Maste switch(type) { 676*3fe401a5SEd Maste case 0: return "R_SPARC_NONE"; 677*3fe401a5SEd Maste case 1: return "R_SPARC_8"; 678*3fe401a5SEd Maste case 2: return "R_SPARC_16"; 679*3fe401a5SEd Maste case 3: return "R_SPARC_32"; 680*3fe401a5SEd Maste case 4: return "R_SPARC_DISP8"; 681*3fe401a5SEd Maste case 5: return "R_SPARC_DISP16"; 682*3fe401a5SEd Maste case 6: return "R_SPARC_DISP32"; 683*3fe401a5SEd Maste case 7: return "R_SPARC_WDISP30"; 684*3fe401a5SEd Maste case 8: return "R_SPARC_WDISP22"; 685*3fe401a5SEd Maste case 9: return "R_SPARC_HI22"; 686*3fe401a5SEd Maste case 10: return "R_SPARC_22"; 687*3fe401a5SEd Maste case 11: return "R_SPARC_13"; 688*3fe401a5SEd Maste case 12: return "R_SPARC_LO10"; 689*3fe401a5SEd Maste case 13: return "R_SPARC_GOT10"; 690*3fe401a5SEd Maste case 14: return "R_SPARC_GOT13"; 691*3fe401a5SEd Maste case 15: return "R_SPARC_GOT22"; 692*3fe401a5SEd Maste case 16: return "R_SPARC_PC10"; 693*3fe401a5SEd Maste case 17: return "R_SPARC_PC22"; 694*3fe401a5SEd Maste case 18: return "R_SPARC_WPLT30"; 695*3fe401a5SEd Maste case 19: return "R_SPARC_COPY"; 696*3fe401a5SEd Maste case 20: return "R_SPARC_GLOB_DAT"; 697*3fe401a5SEd Maste case 21: return "R_SPARC_JMP_SLOT"; 698*3fe401a5SEd Maste case 22: return "R_SPARC_RELATIVE"; 699*3fe401a5SEd Maste case 23: return "R_SPARC_UA32"; 700*3fe401a5SEd Maste case 24: return "R_SPARC_PLT32"; 701*3fe401a5SEd Maste case 25: return "R_SPARC_HIPLT22"; 702*3fe401a5SEd Maste case 26: return "R_SPARC_LOPLT10"; 703*3fe401a5SEd Maste case 27: return "R_SPARC_PCPLT32"; 704*3fe401a5SEd Maste case 28: return "R_SPARC_PCPLT22"; 705*3fe401a5SEd Maste case 29: return "R_SPARC_PCPLT10"; 706*3fe401a5SEd Maste case 30: return "R_SPARC_10"; 707*3fe401a5SEd Maste case 31: return "R_SPARC_11"; 708*3fe401a5SEd Maste case 32: return "R_SPARC_64"; 709*3fe401a5SEd Maste case 33: return "R_SPARC_OLO10"; 710*3fe401a5SEd Maste case 34: return "R_SPARC_HH22"; 711*3fe401a5SEd Maste case 35: return "R_SPARC_HM10"; 712*3fe401a5SEd Maste case 36: return "R_SPARC_LM22"; 713*3fe401a5SEd Maste case 37: return "R_SPARC_PC_HH22"; 714*3fe401a5SEd Maste case 38: return "R_SPARC_PC_HM10"; 715*3fe401a5SEd Maste case 39: return "R_SPARC_PC_LM22"; 716*3fe401a5SEd Maste case 40: return "R_SPARC_WDISP16"; 717*3fe401a5SEd Maste case 41: return "R_SPARC_WDISP19"; 718*3fe401a5SEd Maste case 42: return "R_SPARC_GLOB_JMP"; 719*3fe401a5SEd Maste case 43: return "R_SPARC_7"; 720*3fe401a5SEd Maste case 44: return "R_SPARC_5"; 721*3fe401a5SEd Maste case 45: return "R_SPARC_6"; 722*3fe401a5SEd Maste case 46: return "R_SPARC_DISP64"; 723*3fe401a5SEd Maste case 47: return "R_SPARC_PLT64"; 724*3fe401a5SEd Maste case 48: return "R_SPARC_HIX22"; 725*3fe401a5SEd Maste case 49: return "R_SPARC_LOX10"; 726*3fe401a5SEd Maste case 50: return "R_SPARC_H44"; 727*3fe401a5SEd Maste case 51: return "R_SPARC_M44"; 728*3fe401a5SEd Maste case 52: return "R_SPARC_L44"; 729*3fe401a5SEd Maste case 53: return "R_SPARC_REGISTER"; 730*3fe401a5SEd Maste case 54: return "R_SPARC_UA64"; 731*3fe401a5SEd Maste case 55: return "R_SPARC_UA16"; 732*3fe401a5SEd Maste case 56: return "R_SPARC_TLS_GD_HI22"; 733*3fe401a5SEd Maste case 57: return "R_SPARC_TLS_GD_LO10"; 734*3fe401a5SEd Maste case 58: return "R_SPARC_TLS_GD_ADD"; 735*3fe401a5SEd Maste case 59: return "R_SPARC_TLS_GD_CALL"; 736*3fe401a5SEd Maste case 60: return "R_SPARC_TLS_LDM_HI22"; 737*3fe401a5SEd Maste case 61: return "R_SPARC_TLS_LDM_LO10"; 738*3fe401a5SEd Maste case 62: return "R_SPARC_TLS_LDM_ADD"; 739*3fe401a5SEd Maste case 63: return "R_SPARC_TLS_LDM_CALL"; 740*3fe401a5SEd Maste case 64: return "R_SPARC_TLS_LDO_HIX22"; 741*3fe401a5SEd Maste case 65: return "R_SPARC_TLS_LDO_LOX10"; 742*3fe401a5SEd Maste case 66: return "R_SPARC_TLS_LDO_ADD"; 743*3fe401a5SEd Maste case 67: return "R_SPARC_TLS_IE_HI22"; 744*3fe401a5SEd Maste case 68: return "R_SPARC_TLS_IE_LO10"; 745*3fe401a5SEd Maste case 69: return "R_SPARC_TLS_IE_LD"; 746*3fe401a5SEd Maste case 70: return "R_SPARC_TLS_IE_LDX"; 747*3fe401a5SEd Maste case 71: return "R_SPARC_TLS_IE_ADD"; 748*3fe401a5SEd Maste case 72: return "R_SPARC_TLS_LE_HIX22"; 749*3fe401a5SEd Maste case 73: return "R_SPARC_TLS_LE_LOX10"; 750*3fe401a5SEd Maste case 74: return "R_SPARC_TLS_DTPMOD32"; 751*3fe401a5SEd Maste case 75: return "R_SPARC_TLS_DTPMOD64"; 752*3fe401a5SEd Maste case 76: return "R_SPARC_TLS_DTPOFF32"; 753*3fe401a5SEd Maste case 77: return "R_SPARC_TLS_DTPOFF64"; 754*3fe401a5SEd Maste case 78: return "R_SPARC_TLS_TPOFF32"; 755*3fe401a5SEd Maste case 79: return "R_SPARC_TLS_TPOFF64"; 756*3fe401a5SEd Maste default: return ""; 757*3fe401a5SEd Maste } 758*3fe401a5SEd Maste case EM_X86_64: 759*3fe401a5SEd Maste switch(type) { 760*3fe401a5SEd Maste case 0: return "R_X86_64_NONE"; 761*3fe401a5SEd Maste case 1: return "R_X86_64_64"; 762*3fe401a5SEd Maste case 2: return "R_X86_64_PC32"; 763*3fe401a5SEd Maste case 3: return "R_X86_64_GOT32"; 764*3fe401a5SEd Maste case 4: return "R_X86_64_PLT32"; 765*3fe401a5SEd Maste case 5: return "R_X86_64_COPY"; 766*3fe401a5SEd Maste case 6: return "R_X86_64_GLOB_DAT"; 767*3fe401a5SEd Maste case 7: return "R_X86_64_JMP_SLOT"; 768*3fe401a5SEd Maste case 8: return "R_X86_64_RELATIVE"; 769*3fe401a5SEd Maste case 9: return "R_X86_64_GOTPCREL"; 770*3fe401a5SEd Maste case 10: return "R_X86_64_32"; 771*3fe401a5SEd Maste case 11: return "R_X86_64_32S"; 772*3fe401a5SEd Maste case 12: return "R_X86_64_16"; 773*3fe401a5SEd Maste case 13: return "R_X86_64_PC16"; 774*3fe401a5SEd Maste case 14: return "R_X86_64_8"; 775*3fe401a5SEd Maste case 15: return "R_X86_64_PC8"; 776*3fe401a5SEd Maste case 16: return "R_X86_64_DTPMOD64"; 777*3fe401a5SEd Maste case 17: return "R_X86_64_DTPOFF64"; 778*3fe401a5SEd Maste case 18: return "R_X86_64_TPOFF64"; 779*3fe401a5SEd Maste case 19: return "R_X86_64_TLSGD"; 780*3fe401a5SEd Maste case 20: return "R_X86_64_TLSLD"; 781*3fe401a5SEd Maste case 21: return "R_X86_64_DTPOFF32"; 782*3fe401a5SEd Maste case 22: return "R_X86_64_GOTTPOFF"; 783*3fe401a5SEd Maste case 23: return "R_X86_64_TPOFF32"; 784*3fe401a5SEd Maste default: return ""; 785*3fe401a5SEd Maste } 786*3fe401a5SEd Maste default: return ""; 787*3fe401a5SEd Maste } 788*3fe401a5SEd Maste } 789*3fe401a5SEd Maste 790*3fe401a5SEd Maste static void add_name(struct elfdump *ed, const char *name); 791*3fe401a5SEd Maste static void elf_print_object(struct elfdump *ed); 792*3fe401a5SEd Maste static void elf_print_elf(struct elfdump *ed); 793*3fe401a5SEd Maste static void elf_print_ehdr(struct elfdump *ed); 794*3fe401a5SEd Maste static void elf_print_phdr(struct elfdump *ed); 795*3fe401a5SEd Maste static void elf_print_shdr(struct elfdump *ed); 796*3fe401a5SEd Maste static void elf_print_symtab(struct elfdump *ed, int i); 797*3fe401a5SEd Maste static void elf_print_symtabs(struct elfdump *ed); 798*3fe401a5SEd Maste static void elf_print_symver(struct elfdump *ed); 799*3fe401a5SEd Maste static void elf_print_verdef(struct elfdump *ed, struct section *s); 800*3fe401a5SEd Maste static void elf_print_verneed(struct elfdump *ed, struct section *s); 801*3fe401a5SEd Maste static void elf_print_interp(struct elfdump *ed); 802*3fe401a5SEd Maste static void elf_print_dynamic(struct elfdump *ed); 803*3fe401a5SEd Maste static void elf_print_rel_entry(struct elfdump *ed, struct section *s, 804*3fe401a5SEd Maste int j, struct rel_entry *r); 805*3fe401a5SEd Maste static void elf_print_rela(struct elfdump *ed, struct section *s, 806*3fe401a5SEd Maste Elf_Data *data); 807*3fe401a5SEd Maste static void elf_print_rel(struct elfdump *ed, struct section *s, 808*3fe401a5SEd Maste Elf_Data *data); 809*3fe401a5SEd Maste static void elf_print_reloc(struct elfdump *ed); 810*3fe401a5SEd Maste static void elf_print_got(struct elfdump *ed); 811*3fe401a5SEd Maste static void elf_print_got_section(struct elfdump *ed, struct section *s); 812*3fe401a5SEd Maste static void elf_print_note(struct elfdump *ed); 813*3fe401a5SEd Maste static void elf_print_svr4_hash(struct elfdump *ed, struct section *s); 814*3fe401a5SEd Maste static void elf_print_svr4_hash64(struct elfdump *ed, struct section *s); 815*3fe401a5SEd Maste static void elf_print_gnu_hash(struct elfdump *ed, struct section *s); 816*3fe401a5SEd Maste static void elf_print_hash(struct elfdump *ed); 817*3fe401a5SEd Maste static void elf_print_checksum(struct elfdump *ed); 818*3fe401a5SEd Maste static void find_gotrel(struct elfdump *ed, struct section *gs, 819*3fe401a5SEd Maste struct rel_entry *got); 820*3fe401a5SEd Maste static struct spec_name *find_name(struct elfdump *ed, const char *name); 821*3fe401a5SEd Maste static const char *get_symbol_name(struct elfdump *ed, int symtab, int i); 822*3fe401a5SEd Maste static const char *get_string(struct elfdump *ed, int strtab, size_t off); 823*3fe401a5SEd Maste static void get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs); 824*3fe401a5SEd Maste static void load_sections(struct elfdump *ed); 825*3fe401a5SEd Maste static void unload_sections(struct elfdump *ed); 826*3fe401a5SEd Maste static void usage(void); 827*3fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 828*3fe401a5SEd Maste static int ac_detect_ar(int fd); 829*3fe401a5SEd Maste static void ac_print_ar(struct elfdump *ed, int fd); 830*3fe401a5SEd Maste #else 831*3fe401a5SEd Maste static void elf_print_ar(struct elfdump *ed, int fd); 832*3fe401a5SEd Maste #endif /* USE_LIBARCHIVE_AR */ 833*3fe401a5SEd Maste 834*3fe401a5SEd Maste static struct option elfdump_longopts[] = 835*3fe401a5SEd Maste { 836*3fe401a5SEd Maste { "help", no_argument, NULL, 'H' }, 837*3fe401a5SEd Maste { "version", no_argument, NULL, 'V' }, 838*3fe401a5SEd Maste { NULL, 0, NULL, 0 } 839*3fe401a5SEd Maste }; 840*3fe401a5SEd Maste 841*3fe401a5SEd Maste int 842*3fe401a5SEd Maste main(int ac, char **av) 843*3fe401a5SEd Maste { 844*3fe401a5SEd Maste struct elfdump *ed, ed_storage; 845*3fe401a5SEd Maste struct spec_name *sn; 846*3fe401a5SEd Maste int ch, i; 847*3fe401a5SEd Maste 848*3fe401a5SEd Maste ed = &ed_storage; 849*3fe401a5SEd Maste memset(ed, 0, sizeof(*ed)); 850*3fe401a5SEd Maste STAILQ_INIT(&ed->snl); 851*3fe401a5SEd Maste ed->out = stdout; 852*3fe401a5SEd Maste while ((ch = getopt_long(ac, av, "acdeiGHhknN:prsSvVw:", 853*3fe401a5SEd Maste elfdump_longopts, NULL)) != -1) 854*3fe401a5SEd Maste switch (ch) { 855*3fe401a5SEd Maste case 'a': 856*3fe401a5SEd Maste ed->options = ED_ALL; 857*3fe401a5SEd Maste break; 858*3fe401a5SEd Maste case 'c': 859*3fe401a5SEd Maste ed->options |= ED_SHDR; 860*3fe401a5SEd Maste break; 861*3fe401a5SEd Maste case 'd': 862*3fe401a5SEd Maste ed->options |= ED_DYN; 863*3fe401a5SEd Maste break; 864*3fe401a5SEd Maste case 'e': 865*3fe401a5SEd Maste ed->options |= ED_EHDR; 866*3fe401a5SEd Maste break; 867*3fe401a5SEd Maste case 'i': 868*3fe401a5SEd Maste ed->options |= ED_INTERP; 869*3fe401a5SEd Maste break; 870*3fe401a5SEd Maste case 'G': 871*3fe401a5SEd Maste ed->options |= ED_GOT; 872*3fe401a5SEd Maste break; 873*3fe401a5SEd Maste case 'h': 874*3fe401a5SEd Maste ed->options |= ED_HASH; 875*3fe401a5SEd Maste break; 876*3fe401a5SEd Maste case 'k': 877*3fe401a5SEd Maste ed->options |= ED_CHECKSUM; 878*3fe401a5SEd Maste break; 879*3fe401a5SEd Maste case 'n': 880*3fe401a5SEd Maste ed->options |= ED_NOTE; 881*3fe401a5SEd Maste break; 882*3fe401a5SEd Maste case 'N': 883*3fe401a5SEd Maste add_name(ed, optarg); 884*3fe401a5SEd Maste break; 885*3fe401a5SEd Maste case 'p': 886*3fe401a5SEd Maste ed->options |= ED_PHDR; 887*3fe401a5SEd Maste break; 888*3fe401a5SEd Maste case 'r': 889*3fe401a5SEd Maste ed->options |= ED_REL; 890*3fe401a5SEd Maste break; 891*3fe401a5SEd Maste case 's': 892*3fe401a5SEd Maste ed->options |= ED_SYMTAB; 893*3fe401a5SEd Maste break; 894*3fe401a5SEd Maste case 'S': 895*3fe401a5SEd Maste ed->flags |= SOLARIS_FMT; 896*3fe401a5SEd Maste break; 897*3fe401a5SEd Maste case 'v': 898*3fe401a5SEd Maste ed->options |= ED_SYMVER; 899*3fe401a5SEd Maste break; 900*3fe401a5SEd Maste case 'V': 901*3fe401a5SEd Maste (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), 902*3fe401a5SEd Maste elftc_version()); 903*3fe401a5SEd Maste exit(EXIT_SUCCESS); 904*3fe401a5SEd Maste break; 905*3fe401a5SEd Maste case 'w': 906*3fe401a5SEd Maste if ((ed->out = fopen(optarg, "w")) == NULL) 907*3fe401a5SEd Maste err(EXIT_FAILURE, "%s", optarg); 908*3fe401a5SEd Maste break; 909*3fe401a5SEd Maste case '?': 910*3fe401a5SEd Maste case 'H': 911*3fe401a5SEd Maste default: 912*3fe401a5SEd Maste usage(); 913*3fe401a5SEd Maste } 914*3fe401a5SEd Maste 915*3fe401a5SEd Maste ac -= optind; 916*3fe401a5SEd Maste av += optind; 917*3fe401a5SEd Maste 918*3fe401a5SEd Maste if (ed->options == 0) 919*3fe401a5SEd Maste ed->options = ED_ALL; 920*3fe401a5SEd Maste sn = NULL; 921*3fe401a5SEd Maste if (ed->options & ED_SYMTAB && 922*3fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || (sn = find_name(ed, "ARSYM")) != NULL)) { 923*3fe401a5SEd Maste ed->flags |= PRINT_ARSYM; 924*3fe401a5SEd Maste if (sn != NULL) { 925*3fe401a5SEd Maste STAILQ_REMOVE(&ed->snl, sn, spec_name, sn_list); 926*3fe401a5SEd Maste if (STAILQ_EMPTY(&ed->snl)) 927*3fe401a5SEd Maste ed->flags |= ONLY_ARSYM; 928*3fe401a5SEd Maste } 929*3fe401a5SEd Maste } 930*3fe401a5SEd Maste if (ac == 0) 931*3fe401a5SEd Maste usage(); 932*3fe401a5SEd Maste if (ac > 1) 933*3fe401a5SEd Maste ed->flags |= PRINT_FILENAME; 934*3fe401a5SEd Maste if (elf_version(EV_CURRENT) == EV_NONE) 935*3fe401a5SEd Maste errx(EXIT_FAILURE, "ELF library initialization failed: %s", 936*3fe401a5SEd Maste elf_errmsg(-1)); 937*3fe401a5SEd Maste 938*3fe401a5SEd Maste for (i = 0; i < ac; i++) { 939*3fe401a5SEd Maste ed->filename = av[i]; 940*3fe401a5SEd Maste ed->archive = NULL; 941*3fe401a5SEd Maste elf_print_object(ed); 942*3fe401a5SEd Maste } 943*3fe401a5SEd Maste 944*3fe401a5SEd Maste exit(EXIT_SUCCESS); 945*3fe401a5SEd Maste } 946*3fe401a5SEd Maste 947*3fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 948*3fe401a5SEd Maste 949*3fe401a5SEd Maste /* Archive symbol table entry. */ 950*3fe401a5SEd Maste struct arsym_entry { 951*3fe401a5SEd Maste char *sym_name; 952*3fe401a5SEd Maste size_t off; 953*3fe401a5SEd Maste }; 954*3fe401a5SEd Maste 955*3fe401a5SEd Maste /* 956*3fe401a5SEd Maste * Convenient wrapper for general libarchive error handling. 957*3fe401a5SEd Maste */ 958*3fe401a5SEd Maste #define AC(CALL) do { \ 959*3fe401a5SEd Maste if ((CALL)) { \ 960*3fe401a5SEd Maste warnx("%s", archive_error_string(a)); \ 961*3fe401a5SEd Maste return; \ 962*3fe401a5SEd Maste } \ 963*3fe401a5SEd Maste } while (0) 964*3fe401a5SEd Maste 965*3fe401a5SEd Maste /* 966*3fe401a5SEd Maste * Detect an ar(1) archive using libarchive(3). 967*3fe401a5SEd Maste */ 968*3fe401a5SEd Maste static int 969*3fe401a5SEd Maste ac_detect_ar(int fd) 970*3fe401a5SEd Maste { 971*3fe401a5SEd Maste struct archive *a; 972*3fe401a5SEd Maste struct archive_entry *entry; 973*3fe401a5SEd Maste int r; 974*3fe401a5SEd Maste 975*3fe401a5SEd Maste r = -1; 976*3fe401a5SEd Maste if ((a = archive_read_new()) == NULL) 977*3fe401a5SEd Maste return (0); 978*3fe401a5SEd Maste archive_read_support_format_ar(a); 979*3fe401a5SEd Maste if (archive_read_open_fd(a, fd, 10240) == ARCHIVE_OK) 980*3fe401a5SEd Maste r = archive_read_next_header(a, &entry); 981*3fe401a5SEd Maste archive_read_close(a); 982*3fe401a5SEd Maste archive_read_free(a); 983*3fe401a5SEd Maste 984*3fe401a5SEd Maste return (r == ARCHIVE_OK); 985*3fe401a5SEd Maste } 986*3fe401a5SEd Maste 987*3fe401a5SEd Maste /* 988*3fe401a5SEd Maste * Dump an ar(1) archive using libarchive(3). 989*3fe401a5SEd Maste */ 990*3fe401a5SEd Maste static void 991*3fe401a5SEd Maste ac_print_ar(struct elfdump *ed, int fd) 992*3fe401a5SEd Maste { 993*3fe401a5SEd Maste struct archive *a; 994*3fe401a5SEd Maste struct archive_entry *entry; 995*3fe401a5SEd Maste struct arsym_entry *arsym; 996*3fe401a5SEd Maste const char *name; 997*3fe401a5SEd Maste char idx[10], *b; 998*3fe401a5SEd Maste void *buff; 999*3fe401a5SEd Maste size_t size; 1000*3fe401a5SEd Maste uint32_t cnt; 1001*3fe401a5SEd Maste int i, r; 1002*3fe401a5SEd Maste 1003*3fe401a5SEd Maste if (lseek(fd, 0, SEEK_SET) == -1) 1004*3fe401a5SEd Maste err(EXIT_FAILURE, "lseek failed"); 1005*3fe401a5SEd Maste if ((a = archive_read_new()) == NULL) 1006*3fe401a5SEd Maste errx(EXIT_FAILURE, "%s", archive_error_string(a)); 1007*3fe401a5SEd Maste archive_read_support_format_ar(a); 1008*3fe401a5SEd Maste AC(archive_read_open_fd(a, fd, 10240)); 1009*3fe401a5SEd Maste for(;;) { 1010*3fe401a5SEd Maste r = archive_read_next_header(a, &entry); 1011*3fe401a5SEd Maste if (r == ARCHIVE_FATAL) 1012*3fe401a5SEd Maste errx(EXIT_FAILURE, "%s", archive_error_string(a)); 1013*3fe401a5SEd Maste if (r == ARCHIVE_EOF) 1014*3fe401a5SEd Maste break; 1015*3fe401a5SEd Maste if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY) 1016*3fe401a5SEd Maste warnx("%s", archive_error_string(a)); 1017*3fe401a5SEd Maste if (r == ARCHIVE_RETRY) 1018*3fe401a5SEd Maste continue; 1019*3fe401a5SEd Maste name = archive_entry_pathname(entry); 1020*3fe401a5SEd Maste size = archive_entry_size(entry); 1021*3fe401a5SEd Maste if (size == 0) 1022*3fe401a5SEd Maste continue; 1023*3fe401a5SEd Maste if ((buff = malloc(size)) == NULL) { 1024*3fe401a5SEd Maste warn("malloc failed"); 1025*3fe401a5SEd Maste continue; 1026*3fe401a5SEd Maste } 1027*3fe401a5SEd Maste if (archive_read_data(a, buff, size) != (ssize_t)size) { 1028*3fe401a5SEd Maste warnx("%s", archive_error_string(a)); 1029*3fe401a5SEd Maste free(buff); 1030*3fe401a5SEd Maste continue; 1031*3fe401a5SEd Maste } 1032*3fe401a5SEd Maste 1033*3fe401a5SEd Maste /* 1034*3fe401a5SEd Maste * Note that when processing arsym via libarchive, there is 1035*3fe401a5SEd Maste * no way to tell which member a certain symbol belongs to, 1036*3fe401a5SEd Maste * since we can not just "lseek" to a member offset and read 1037*3fe401a5SEd Maste * the member header. 1038*3fe401a5SEd Maste */ 1039*3fe401a5SEd Maste if (!strcmp(name, "/") && ed->flags & PRINT_ARSYM) { 1040*3fe401a5SEd Maste b = buff; 1041*3fe401a5SEd Maste cnt = be32dec(b); 1042*3fe401a5SEd Maste if (cnt == 0) { 1043*3fe401a5SEd Maste free(buff); 1044*3fe401a5SEd Maste continue; 1045*3fe401a5SEd Maste } 1046*3fe401a5SEd Maste arsym = calloc(cnt, sizeof(*arsym)); 1047*3fe401a5SEd Maste if (arsym == NULL) 1048*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 1049*3fe401a5SEd Maste b += sizeof(uint32_t); 1050*3fe401a5SEd Maste for (i = 0; (size_t)i < cnt; i++) { 1051*3fe401a5SEd Maste arsym[i].off = be32dec(b); 1052*3fe401a5SEd Maste b += sizeof(uint32_t); 1053*3fe401a5SEd Maste } 1054*3fe401a5SEd Maste for (i = 0; (size_t)i < cnt; i++) { 1055*3fe401a5SEd Maste arsym[i].sym_name = b; 1056*3fe401a5SEd Maste b += strlen(b) + 1; 1057*3fe401a5SEd Maste } 1058*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1059*3fe401a5SEd Maste PRT("\nSymbol Table: (archive)\n"); 1060*3fe401a5SEd Maste PRT(" index offset symbol\n"); 1061*3fe401a5SEd Maste } else 1062*3fe401a5SEd Maste PRT("\nsymbol table (archive):\n"); 1063*3fe401a5SEd Maste for (i = 0; (size_t)i < cnt; i++) { 1064*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1065*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", i); 1066*3fe401a5SEd Maste PRT("%10s ", idx); 1067*3fe401a5SEd Maste PRT("0x%8.8jx ", 1068*3fe401a5SEd Maste (uintmax_t)arsym[i].off); 1069*3fe401a5SEd Maste PRT("%s\n", arsym[i].sym_name); 1070*3fe401a5SEd Maste } else { 1071*3fe401a5SEd Maste PRT("\nentry: %d\n", i); 1072*3fe401a5SEd Maste PRT("\toffset: %#jx\n", 1073*3fe401a5SEd Maste (uintmax_t)arsym[i].off); 1074*3fe401a5SEd Maste PRT("\tsymbol: %s\n", 1075*3fe401a5SEd Maste arsym[i].sym_name); 1076*3fe401a5SEd Maste } 1077*3fe401a5SEd Maste } 1078*3fe401a5SEd Maste free(arsym); 1079*3fe401a5SEd Maste free(buff); 1080*3fe401a5SEd Maste /* No need to continue if we only dump ARSYM. */ 1081*3fe401a5SEd Maste if (ed->flags & ONLY_ARSYM) { 1082*3fe401a5SEd Maste AC(archive_read_close(a)); 1083*3fe401a5SEd Maste AC(archive_read_free(a)); 1084*3fe401a5SEd Maste return; 1085*3fe401a5SEd Maste } 1086*3fe401a5SEd Maste continue; 1087*3fe401a5SEd Maste } 1088*3fe401a5SEd Maste if ((ed->elf = elf_memory(buff, size)) == NULL) { 1089*3fe401a5SEd Maste warnx("elf_memroy() failed: %s", 1090*3fe401a5SEd Maste elf_errmsg(-1)); 1091*3fe401a5SEd Maste free(buff); 1092*3fe401a5SEd Maste continue; 1093*3fe401a5SEd Maste } 1094*3fe401a5SEd Maste /* Skip non-ELF member. */ 1095*3fe401a5SEd Maste if (elf_kind(ed->elf) == ELF_K_ELF) { 1096*3fe401a5SEd Maste printf("\n%s(%s):\n", ed->archive, name); 1097*3fe401a5SEd Maste elf_print_elf(ed); 1098*3fe401a5SEd Maste } 1099*3fe401a5SEd Maste elf_end(ed->elf); 1100*3fe401a5SEd Maste free(buff); 1101*3fe401a5SEd Maste } 1102*3fe401a5SEd Maste AC(archive_read_close(a)); 1103*3fe401a5SEd Maste AC(archive_read_free(a)); 1104*3fe401a5SEd Maste } 1105*3fe401a5SEd Maste 1106*3fe401a5SEd Maste #else /* USE_LIBARCHIVE_AR */ 1107*3fe401a5SEd Maste 1108*3fe401a5SEd Maste /* 1109*3fe401a5SEd Maste * Dump an ar(1) archive. 1110*3fe401a5SEd Maste */ 1111*3fe401a5SEd Maste static void 1112*3fe401a5SEd Maste elf_print_ar(struct elfdump *ed, int fd) 1113*3fe401a5SEd Maste { 1114*3fe401a5SEd Maste Elf *e; 1115*3fe401a5SEd Maste Elf_Arhdr *arh; 1116*3fe401a5SEd Maste Elf_Arsym *arsym; 1117*3fe401a5SEd Maste Elf_Cmd cmd; 1118*3fe401a5SEd Maste char idx[10]; 1119*3fe401a5SEd Maste size_t cnt; 1120*3fe401a5SEd Maste int i; 1121*3fe401a5SEd Maste 1122*3fe401a5SEd Maste ed->ar = ed->elf; 1123*3fe401a5SEd Maste 1124*3fe401a5SEd Maste if (ed->flags & PRINT_ARSYM) { 1125*3fe401a5SEd Maste cnt = 0; 1126*3fe401a5SEd Maste if ((arsym = elf_getarsym(ed->ar, &cnt)) == NULL) { 1127*3fe401a5SEd Maste warnx("elf_getarsym failed: %s", elf_errmsg(-1)); 1128*3fe401a5SEd Maste goto print_members; 1129*3fe401a5SEd Maste } 1130*3fe401a5SEd Maste if (cnt == 0) 1131*3fe401a5SEd Maste goto print_members; 1132*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1133*3fe401a5SEd Maste PRT("\nSymbol Table: (archive)\n"); 1134*3fe401a5SEd Maste PRT(" index offset member name and symbol\n"); 1135*3fe401a5SEd Maste } else 1136*3fe401a5SEd Maste PRT("\nsymbol table (archive):\n"); 1137*3fe401a5SEd Maste for (i = 0; (size_t)i < cnt - 1; i++) { 1138*3fe401a5SEd Maste if (elf_rand(ed->ar, arsym[i].as_off) != 1139*3fe401a5SEd Maste arsym[i].as_off) { 1140*3fe401a5SEd Maste warnx("elf_rand failed: %s", elf_errmsg(-1)); 1141*3fe401a5SEd Maste break; 1142*3fe401a5SEd Maste } 1143*3fe401a5SEd Maste if ((e = elf_begin(fd, ELF_C_READ, ed->ar)) == NULL) { 1144*3fe401a5SEd Maste warnx("elf_begin failed: %s", elf_errmsg(-1)); 1145*3fe401a5SEd Maste break; 1146*3fe401a5SEd Maste } 1147*3fe401a5SEd Maste if ((arh = elf_getarhdr(e)) == NULL) { 1148*3fe401a5SEd Maste warnx("elf_getarhdr failed: %s", 1149*3fe401a5SEd Maste elf_errmsg(-1)); 1150*3fe401a5SEd Maste break; 1151*3fe401a5SEd Maste } 1152*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1153*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", i); 1154*3fe401a5SEd Maste PRT("%10s ", idx); 1155*3fe401a5SEd Maste PRT("0x%8.8jx ", 1156*3fe401a5SEd Maste (uintmax_t)arsym[i].as_off); 1157*3fe401a5SEd Maste PRT("(%s):%s\n", arh->ar_name, 1158*3fe401a5SEd Maste arsym[i].as_name); 1159*3fe401a5SEd Maste } else { 1160*3fe401a5SEd Maste PRT("\nentry: %d\n", i); 1161*3fe401a5SEd Maste PRT("\toffset: %#jx\n", 1162*3fe401a5SEd Maste (uintmax_t)arsym[i].as_off); 1163*3fe401a5SEd Maste PRT("\tmember: %s\n", arh->ar_name); 1164*3fe401a5SEd Maste PRT("\tsymbol: %s\n", arsym[i].as_name); 1165*3fe401a5SEd Maste } 1166*3fe401a5SEd Maste elf_end(e); 1167*3fe401a5SEd Maste } 1168*3fe401a5SEd Maste 1169*3fe401a5SEd Maste /* No need to continue if we only dump ARSYM. */ 1170*3fe401a5SEd Maste if (ed->flags & ONLY_ARSYM) 1171*3fe401a5SEd Maste return; 1172*3fe401a5SEd Maste } 1173*3fe401a5SEd Maste 1174*3fe401a5SEd Maste print_members: 1175*3fe401a5SEd Maste 1176*3fe401a5SEd Maste /* Rewind the archive. */ 1177*3fe401a5SEd Maste if (elf_rand(ed->ar, SARMAG) != SARMAG) { 1178*3fe401a5SEd Maste warnx("elf_rand failed: %s", elf_errmsg(-1)); 1179*3fe401a5SEd Maste return; 1180*3fe401a5SEd Maste } 1181*3fe401a5SEd Maste 1182*3fe401a5SEd Maste /* Dump each member of the archive. */ 1183*3fe401a5SEd Maste cmd = ELF_C_READ; 1184*3fe401a5SEd Maste while ((ed->elf = elf_begin(fd, cmd, ed->ar)) != NULL) { 1185*3fe401a5SEd Maste /* Skip non-ELF member. */ 1186*3fe401a5SEd Maste if (elf_kind(ed->elf) == ELF_K_ELF) { 1187*3fe401a5SEd Maste if ((arh = elf_getarhdr(ed->elf)) == NULL) { 1188*3fe401a5SEd Maste warnx("elf_getarhdr failed: %s", 1189*3fe401a5SEd Maste elf_errmsg(-1)); 1190*3fe401a5SEd Maste break; 1191*3fe401a5SEd Maste } 1192*3fe401a5SEd Maste printf("\n%s(%s):\n", ed->archive, arh->ar_name); 1193*3fe401a5SEd Maste elf_print_elf(ed); 1194*3fe401a5SEd Maste } 1195*3fe401a5SEd Maste cmd = elf_next(ed->elf); 1196*3fe401a5SEd Maste elf_end(ed->elf); 1197*3fe401a5SEd Maste } 1198*3fe401a5SEd Maste } 1199*3fe401a5SEd Maste 1200*3fe401a5SEd Maste #endif /* USE_LIBARCHIVE_AR */ 1201*3fe401a5SEd Maste 1202*3fe401a5SEd Maste /* 1203*3fe401a5SEd Maste * Dump an object. (ELF object or ar(1) archive) 1204*3fe401a5SEd Maste */ 1205*3fe401a5SEd Maste static void 1206*3fe401a5SEd Maste elf_print_object(struct elfdump *ed) 1207*3fe401a5SEd Maste { 1208*3fe401a5SEd Maste int fd; 1209*3fe401a5SEd Maste 1210*3fe401a5SEd Maste if ((fd = open(ed->filename, O_RDONLY)) == -1) { 1211*3fe401a5SEd Maste warn("open %s failed", ed->filename); 1212*3fe401a5SEd Maste return; 1213*3fe401a5SEd Maste } 1214*3fe401a5SEd Maste 1215*3fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 1216*3fe401a5SEd Maste if (ac_detect_ar(fd)) { 1217*3fe401a5SEd Maste ed->archive = ed->filename; 1218*3fe401a5SEd Maste ac_print_ar(ed, fd); 1219*3fe401a5SEd Maste return; 1220*3fe401a5SEd Maste } 1221*3fe401a5SEd Maste #endif /* USE_LIBARCHIVE_AR */ 1222*3fe401a5SEd Maste 1223*3fe401a5SEd Maste if ((ed->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 1224*3fe401a5SEd Maste warnx("elf_begin() failed: %s", elf_errmsg(-1)); 1225*3fe401a5SEd Maste return; 1226*3fe401a5SEd Maste } 1227*3fe401a5SEd Maste 1228*3fe401a5SEd Maste switch (elf_kind(ed->elf)) { 1229*3fe401a5SEd Maste case ELF_K_NONE: 1230*3fe401a5SEd Maste warnx("Not an ELF file."); 1231*3fe401a5SEd Maste return; 1232*3fe401a5SEd Maste case ELF_K_ELF: 1233*3fe401a5SEd Maste if (ed->flags & PRINT_FILENAME) 1234*3fe401a5SEd Maste printf("\n%s:\n", ed->filename); 1235*3fe401a5SEd Maste elf_print_elf(ed); 1236*3fe401a5SEd Maste break; 1237*3fe401a5SEd Maste case ELF_K_AR: 1238*3fe401a5SEd Maste #ifndef USE_LIBARCHIVE_AR 1239*3fe401a5SEd Maste ed->archive = ed->filename; 1240*3fe401a5SEd Maste elf_print_ar(ed, fd); 1241*3fe401a5SEd Maste #endif 1242*3fe401a5SEd Maste break; 1243*3fe401a5SEd Maste default: 1244*3fe401a5SEd Maste warnx("Internal: libelf returned unknown elf kind."); 1245*3fe401a5SEd Maste return; 1246*3fe401a5SEd Maste } 1247*3fe401a5SEd Maste 1248*3fe401a5SEd Maste elf_end(ed->elf); 1249*3fe401a5SEd Maste } 1250*3fe401a5SEd Maste 1251*3fe401a5SEd Maste /* 1252*3fe401a5SEd Maste * Dump an ELF object. 1253*3fe401a5SEd Maste */ 1254*3fe401a5SEd Maste static void 1255*3fe401a5SEd Maste elf_print_elf(struct elfdump *ed) 1256*3fe401a5SEd Maste { 1257*3fe401a5SEd Maste 1258*3fe401a5SEd Maste if (gelf_getehdr(ed->elf, &ed->ehdr) == NULL) { 1259*3fe401a5SEd Maste warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 1260*3fe401a5SEd Maste return; 1261*3fe401a5SEd Maste } 1262*3fe401a5SEd Maste if ((ed->ec = gelf_getclass(ed->elf)) == ELFCLASSNONE) { 1263*3fe401a5SEd Maste warnx("gelf_getclass failed: %s", elf_errmsg(-1)); 1264*3fe401a5SEd Maste return; 1265*3fe401a5SEd Maste } 1266*3fe401a5SEd Maste 1267*3fe401a5SEd Maste if (ed->options & (ED_SHDR | ED_DYN | ED_REL | ED_GOT | ED_SYMTAB | 1268*3fe401a5SEd Maste ED_SYMVER | ED_NOTE | ED_HASH)) 1269*3fe401a5SEd Maste load_sections(ed); 1270*3fe401a5SEd Maste 1271*3fe401a5SEd Maste if (ed->options & ED_EHDR) 1272*3fe401a5SEd Maste elf_print_ehdr(ed); 1273*3fe401a5SEd Maste if (ed->options & ED_PHDR) 1274*3fe401a5SEd Maste elf_print_phdr(ed); 1275*3fe401a5SEd Maste if (ed->options & ED_INTERP) 1276*3fe401a5SEd Maste elf_print_interp(ed); 1277*3fe401a5SEd Maste if (ed->options & ED_SHDR) 1278*3fe401a5SEd Maste elf_print_shdr(ed); 1279*3fe401a5SEd Maste if (ed->options & ED_DYN) 1280*3fe401a5SEd Maste elf_print_dynamic(ed); 1281*3fe401a5SEd Maste if (ed->options & ED_REL) 1282*3fe401a5SEd Maste elf_print_reloc(ed); 1283*3fe401a5SEd Maste if (ed->options & ED_GOT) 1284*3fe401a5SEd Maste elf_print_got(ed); 1285*3fe401a5SEd Maste if (ed->options & ED_SYMTAB) 1286*3fe401a5SEd Maste elf_print_symtabs(ed); 1287*3fe401a5SEd Maste if (ed->options & ED_SYMVER) 1288*3fe401a5SEd Maste elf_print_symver(ed); 1289*3fe401a5SEd Maste if (ed->options & ED_NOTE) 1290*3fe401a5SEd Maste elf_print_note(ed); 1291*3fe401a5SEd Maste if (ed->options & ED_HASH) 1292*3fe401a5SEd Maste elf_print_hash(ed); 1293*3fe401a5SEd Maste if (ed->options & ED_CHECKSUM) 1294*3fe401a5SEd Maste elf_print_checksum(ed); 1295*3fe401a5SEd Maste 1296*3fe401a5SEd Maste unload_sections(ed); 1297*3fe401a5SEd Maste } 1298*3fe401a5SEd Maste 1299*3fe401a5SEd Maste /* 1300*3fe401a5SEd Maste * Read the section headers from ELF object and store them in the 1301*3fe401a5SEd Maste * internal cache. 1302*3fe401a5SEd Maste */ 1303*3fe401a5SEd Maste static void 1304*3fe401a5SEd Maste load_sections(struct elfdump *ed) 1305*3fe401a5SEd Maste { 1306*3fe401a5SEd Maste struct section *s; 1307*3fe401a5SEd Maste const char *name; 1308*3fe401a5SEd Maste Elf_Scn *scn; 1309*3fe401a5SEd Maste GElf_Shdr sh; 1310*3fe401a5SEd Maste size_t shstrndx, ndx; 1311*3fe401a5SEd Maste int elferr; 1312*3fe401a5SEd Maste 1313*3fe401a5SEd Maste assert(ed->sl == NULL); 1314*3fe401a5SEd Maste 1315*3fe401a5SEd Maste if (!elf_getshnum(ed->elf, &ed->shnum)) { 1316*3fe401a5SEd Maste warnx("elf_getshnum failed: %s", elf_errmsg(-1)); 1317*3fe401a5SEd Maste return; 1318*3fe401a5SEd Maste } 1319*3fe401a5SEd Maste if (ed->shnum == 0) 1320*3fe401a5SEd Maste return; 1321*3fe401a5SEd Maste if ((ed->sl = calloc(ed->shnum, sizeof(*ed->sl))) == NULL) 1322*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 1323*3fe401a5SEd Maste if (!elf_getshstrndx(ed->elf, &shstrndx)) { 1324*3fe401a5SEd Maste warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 1325*3fe401a5SEd Maste return; 1326*3fe401a5SEd Maste } 1327*3fe401a5SEd Maste if ((scn = elf_getscn(ed->elf, 0)) == NULL) { 1328*3fe401a5SEd Maste warnx("elf_getscn failed: %s", elf_errmsg(-1)); 1329*3fe401a5SEd Maste return; 1330*3fe401a5SEd Maste } 1331*3fe401a5SEd Maste (void) elf_errno(); 1332*3fe401a5SEd Maste do { 1333*3fe401a5SEd Maste if (gelf_getshdr(scn, &sh) == NULL) { 1334*3fe401a5SEd Maste warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 1335*3fe401a5SEd Maste (void) elf_errno(); 1336*3fe401a5SEd Maste continue; 1337*3fe401a5SEd Maste } 1338*3fe401a5SEd Maste if ((name = elf_strptr(ed->elf, shstrndx, sh.sh_name)) == NULL) { 1339*3fe401a5SEd Maste (void) elf_errno(); 1340*3fe401a5SEd Maste name = "ERROR"; 1341*3fe401a5SEd Maste } 1342*3fe401a5SEd Maste if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) 1343*3fe401a5SEd Maste if ((elferr = elf_errno()) != 0) { 1344*3fe401a5SEd Maste warnx("elf_ndxscn failed: %s", 1345*3fe401a5SEd Maste elf_errmsg(elferr)); 1346*3fe401a5SEd Maste continue; 1347*3fe401a5SEd Maste } 1348*3fe401a5SEd Maste if (ndx >= ed->shnum) { 1349*3fe401a5SEd Maste warnx("section index of '%s' out of range", name); 1350*3fe401a5SEd Maste continue; 1351*3fe401a5SEd Maste } 1352*3fe401a5SEd Maste s = &ed->sl[ndx]; 1353*3fe401a5SEd Maste s->name = name; 1354*3fe401a5SEd Maste s->scn = scn; 1355*3fe401a5SEd Maste s->off = sh.sh_offset; 1356*3fe401a5SEd Maste s->sz = sh.sh_size; 1357*3fe401a5SEd Maste s->entsize = sh.sh_entsize; 1358*3fe401a5SEd Maste s->align = sh.sh_addralign; 1359*3fe401a5SEd Maste s->type = sh.sh_type; 1360*3fe401a5SEd Maste s->flags = sh.sh_flags; 1361*3fe401a5SEd Maste s->addr = sh.sh_addr; 1362*3fe401a5SEd Maste s->link = sh.sh_link; 1363*3fe401a5SEd Maste s->info = sh.sh_info; 1364*3fe401a5SEd Maste } while ((scn = elf_nextscn(ed->elf, scn)) != NULL); 1365*3fe401a5SEd Maste elferr = elf_errno(); 1366*3fe401a5SEd Maste if (elferr != 0) 1367*3fe401a5SEd Maste warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 1368*3fe401a5SEd Maste } 1369*3fe401a5SEd Maste 1370*3fe401a5SEd Maste /* 1371*3fe401a5SEd Maste * Release section related resources. 1372*3fe401a5SEd Maste */ 1373*3fe401a5SEd Maste static void 1374*3fe401a5SEd Maste unload_sections(struct elfdump *ed) 1375*3fe401a5SEd Maste { 1376*3fe401a5SEd Maste if (ed->sl != NULL) { 1377*3fe401a5SEd Maste free(ed->sl); 1378*3fe401a5SEd Maste ed->sl = NULL; 1379*3fe401a5SEd Maste } 1380*3fe401a5SEd Maste } 1381*3fe401a5SEd Maste 1382*3fe401a5SEd Maste /* 1383*3fe401a5SEd Maste * Add a name to the '-N' name list. 1384*3fe401a5SEd Maste */ 1385*3fe401a5SEd Maste static void 1386*3fe401a5SEd Maste add_name(struct elfdump *ed, const char *name) 1387*3fe401a5SEd Maste { 1388*3fe401a5SEd Maste struct spec_name *sn; 1389*3fe401a5SEd Maste 1390*3fe401a5SEd Maste if (find_name(ed, name)) 1391*3fe401a5SEd Maste return; 1392*3fe401a5SEd Maste if ((sn = malloc(sizeof(*sn))) == NULL) { 1393*3fe401a5SEd Maste warn("malloc failed"); 1394*3fe401a5SEd Maste return; 1395*3fe401a5SEd Maste } 1396*3fe401a5SEd Maste sn->name = name; 1397*3fe401a5SEd Maste STAILQ_INSERT_TAIL(&ed->snl, sn, sn_list); 1398*3fe401a5SEd Maste } 1399*3fe401a5SEd Maste 1400*3fe401a5SEd Maste /* 1401*3fe401a5SEd Maste * Lookup a name in the '-N' name list. 1402*3fe401a5SEd Maste */ 1403*3fe401a5SEd Maste static struct spec_name * 1404*3fe401a5SEd Maste find_name(struct elfdump *ed, const char *name) 1405*3fe401a5SEd Maste { 1406*3fe401a5SEd Maste struct spec_name *sn; 1407*3fe401a5SEd Maste 1408*3fe401a5SEd Maste STAILQ_FOREACH(sn, &ed->snl, sn_list) { 1409*3fe401a5SEd Maste if (!strcmp(sn->name, name)) 1410*3fe401a5SEd Maste return (sn); 1411*3fe401a5SEd Maste } 1412*3fe401a5SEd Maste 1413*3fe401a5SEd Maste return (NULL); 1414*3fe401a5SEd Maste } 1415*3fe401a5SEd Maste 1416*3fe401a5SEd Maste /* 1417*3fe401a5SEd Maste * Retrieve the name of a symbol using the section index of the symbol 1418*3fe401a5SEd Maste * table and the index of the symbol within that table. 1419*3fe401a5SEd Maste */ 1420*3fe401a5SEd Maste static const char * 1421*3fe401a5SEd Maste get_symbol_name(struct elfdump *ed, int symtab, int i) 1422*3fe401a5SEd Maste { 1423*3fe401a5SEd Maste static char sname[64]; 1424*3fe401a5SEd Maste struct section *s; 1425*3fe401a5SEd Maste const char *name; 1426*3fe401a5SEd Maste GElf_Sym sym; 1427*3fe401a5SEd Maste Elf_Data *data; 1428*3fe401a5SEd Maste int elferr; 1429*3fe401a5SEd Maste 1430*3fe401a5SEd Maste s = &ed->sl[symtab]; 1431*3fe401a5SEd Maste if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) 1432*3fe401a5SEd Maste return (""); 1433*3fe401a5SEd Maste (void) elf_errno(); 1434*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1435*3fe401a5SEd Maste elferr = elf_errno(); 1436*3fe401a5SEd Maste if (elferr != 0) 1437*3fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1438*3fe401a5SEd Maste return (""); 1439*3fe401a5SEd Maste } 1440*3fe401a5SEd Maste if (gelf_getsym(data, i, &sym) != &sym) 1441*3fe401a5SEd Maste return (""); 1442*3fe401a5SEd Maste if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) { 1443*3fe401a5SEd Maste if (sym.st_shndx < ed->shnum) { 1444*3fe401a5SEd Maste snprintf(sname, sizeof(sname), "%s (section)", 1445*3fe401a5SEd Maste ed->sl[sym.st_shndx].name); 1446*3fe401a5SEd Maste return (sname); 1447*3fe401a5SEd Maste } else 1448*3fe401a5SEd Maste return (""); 1449*3fe401a5SEd Maste } 1450*3fe401a5SEd Maste if ((name = elf_strptr(ed->elf, s->link, sym.st_name)) == NULL) 1451*3fe401a5SEd Maste return (""); 1452*3fe401a5SEd Maste 1453*3fe401a5SEd Maste return (name); 1454*3fe401a5SEd Maste } 1455*3fe401a5SEd Maste 1456*3fe401a5SEd Maste /* 1457*3fe401a5SEd Maste * Retrieve a string using string table section index and the string offset. 1458*3fe401a5SEd Maste */ 1459*3fe401a5SEd Maste static const char* 1460*3fe401a5SEd Maste get_string(struct elfdump *ed, int strtab, size_t off) 1461*3fe401a5SEd Maste { 1462*3fe401a5SEd Maste const char *name; 1463*3fe401a5SEd Maste 1464*3fe401a5SEd Maste if ((name = elf_strptr(ed->elf, strtab, off)) == NULL) 1465*3fe401a5SEd Maste return (""); 1466*3fe401a5SEd Maste 1467*3fe401a5SEd Maste return (name); 1468*3fe401a5SEd Maste } 1469*3fe401a5SEd Maste 1470*3fe401a5SEd Maste /* 1471*3fe401a5SEd Maste * Dump the ELF Executable Header. 1472*3fe401a5SEd Maste */ 1473*3fe401a5SEd Maste static void 1474*3fe401a5SEd Maste elf_print_ehdr(struct elfdump *ed) 1475*3fe401a5SEd Maste { 1476*3fe401a5SEd Maste 1477*3fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 1478*3fe401a5SEd Maste return; 1479*3fe401a5SEd Maste 1480*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1481*3fe401a5SEd Maste PRT("\nELF Header\n"); 1482*3fe401a5SEd Maste PRT(" ei_magic: { %#x, %c, %c, %c }\n", 1483*3fe401a5SEd Maste ed->ehdr.e_ident[0], ed->ehdr.e_ident[1], 1484*3fe401a5SEd Maste ed->ehdr.e_ident[2], ed->ehdr.e_ident[3]); 1485*3fe401a5SEd Maste PRT(" ei_class: %-18s", 1486*3fe401a5SEd Maste ei_classes[ed->ehdr.e_ident[EI_CLASS]]); 1487*3fe401a5SEd Maste PRT(" ei_data: %s\n", ei_data[ed->ehdr.e_ident[EI_DATA]]); 1488*3fe401a5SEd Maste PRT(" e_machine: %-18s", e_machines(ed->ehdr.e_machine)); 1489*3fe401a5SEd Maste PRT(" e_version: %s\n", ei_versions[ed->ehdr.e_version]); 1490*3fe401a5SEd Maste PRT(" e_type: %s\n", e_types[ed->ehdr.e_type]); 1491*3fe401a5SEd Maste PRT(" e_flags: %18d\n", ed->ehdr.e_flags); 1492*3fe401a5SEd Maste PRT(" e_entry: %#18jx", (uintmax_t)ed->ehdr.e_entry); 1493*3fe401a5SEd Maste PRT(" e_ehsize: %6d", ed->ehdr.e_ehsize); 1494*3fe401a5SEd Maste PRT(" e_shstrndx:%5d\n", ed->ehdr.e_shstrndx); 1495*3fe401a5SEd Maste PRT(" e_shoff: %#18jx", (uintmax_t)ed->ehdr.e_shoff); 1496*3fe401a5SEd Maste PRT(" e_shentsize: %3d", ed->ehdr.e_shentsize); 1497*3fe401a5SEd Maste PRT(" e_shnum: %5d\n", ed->ehdr.e_shnum); 1498*3fe401a5SEd Maste PRT(" e_phoff: %#18jx", (uintmax_t)ed->ehdr.e_phoff); 1499*3fe401a5SEd Maste PRT(" e_phentsize: %3d", ed->ehdr.e_phentsize); 1500*3fe401a5SEd Maste PRT(" e_phnum: %5d\n", ed->ehdr.e_phnum); 1501*3fe401a5SEd Maste } else { 1502*3fe401a5SEd Maste PRT("\nelf header:\n"); 1503*3fe401a5SEd Maste PRT("\n"); 1504*3fe401a5SEd Maste PRT("\te_ident: %s %s %s\n", 1505*3fe401a5SEd Maste ei_classes[ed->ehdr.e_ident[EI_CLASS]], 1506*3fe401a5SEd Maste ei_data[ed->ehdr.e_ident[EI_DATA]], 1507*3fe401a5SEd Maste ei_abis[ed->ehdr.e_ident[EI_OSABI]]); 1508*3fe401a5SEd Maste PRT("\te_type: %s\n", e_types[ed->ehdr.e_type]); 1509*3fe401a5SEd Maste PRT("\te_machine: %s\n", e_machines(ed->ehdr.e_machine)); 1510*3fe401a5SEd Maste PRT("\te_version: %s\n", ei_versions[ed->ehdr.e_version]); 1511*3fe401a5SEd Maste PRT("\te_entry: %#jx\n", (uintmax_t)ed->ehdr.e_entry); 1512*3fe401a5SEd Maste PRT("\te_phoff: %ju\n", (uintmax_t)ed->ehdr.e_phoff); 1513*3fe401a5SEd Maste PRT("\te_shoff: %ju\n", (uintmax_t) ed->ehdr.e_shoff); 1514*3fe401a5SEd Maste PRT("\te_flags: %u\n", ed->ehdr.e_flags); 1515*3fe401a5SEd Maste PRT("\te_ehsize: %u\n", ed->ehdr.e_ehsize); 1516*3fe401a5SEd Maste PRT("\te_phentsize: %u\n", ed->ehdr.e_phentsize); 1517*3fe401a5SEd Maste PRT("\te_phnum: %u\n", ed->ehdr.e_phnum); 1518*3fe401a5SEd Maste PRT("\te_shentsize: %u\n", ed->ehdr.e_shentsize); 1519*3fe401a5SEd Maste PRT("\te_shnum: %u\n", ed->ehdr.e_shnum); 1520*3fe401a5SEd Maste PRT("\te_shstrndx: %u\n", ed->ehdr.e_shstrndx); 1521*3fe401a5SEd Maste } 1522*3fe401a5SEd Maste } 1523*3fe401a5SEd Maste 1524*3fe401a5SEd Maste /* 1525*3fe401a5SEd Maste * Dump the ELF Program Header Table. 1526*3fe401a5SEd Maste */ 1527*3fe401a5SEd Maste static void 1528*3fe401a5SEd Maste elf_print_phdr(struct elfdump *ed) 1529*3fe401a5SEd Maste { 1530*3fe401a5SEd Maste GElf_Phdr ph; 1531*3fe401a5SEd Maste size_t phnum; 1532*3fe401a5SEd Maste int header, i; 1533*3fe401a5SEd Maste 1534*3fe401a5SEd Maste if (elf_getphnum(ed->elf, &phnum) == 0) { 1535*3fe401a5SEd Maste warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 1536*3fe401a5SEd Maste return; 1537*3fe401a5SEd Maste } 1538*3fe401a5SEd Maste header = 0; 1539*3fe401a5SEd Maste for (i = 0; (u_int64_t) i < phnum; i++) { 1540*3fe401a5SEd Maste if (gelf_getphdr(ed->elf, i, &ph) != &ph) { 1541*3fe401a5SEd Maste warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 1542*3fe401a5SEd Maste continue; 1543*3fe401a5SEd Maste } 1544*3fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl) && 1545*3fe401a5SEd Maste find_name(ed, p_types[ph.p_type & 0x7]) == NULL) 1546*3fe401a5SEd Maste continue; 1547*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1548*3fe401a5SEd Maste PRT("\nProgram Header[%d]:\n", i); 1549*3fe401a5SEd Maste PRT(" p_vaddr: %#-14jx", (uintmax_t)ph.p_vaddr); 1550*3fe401a5SEd Maste PRT(" p_flags: [ %s ]\n", p_flags[ph.p_flags]); 1551*3fe401a5SEd Maste PRT(" p_paddr: %#-14jx", (uintmax_t)ph.p_paddr); 1552*3fe401a5SEd Maste PRT(" p_type: [ %s ]\n", p_types[ph.p_type & 0x7]); 1553*3fe401a5SEd Maste PRT(" p_filesz: %#-14jx", 1554*3fe401a5SEd Maste (uintmax_t)ph.p_filesz); 1555*3fe401a5SEd Maste PRT(" p_memsz: %#jx\n", (uintmax_t)ph.p_memsz); 1556*3fe401a5SEd Maste PRT(" p_offset: %#-14jx", 1557*3fe401a5SEd Maste (uintmax_t)ph.p_offset); 1558*3fe401a5SEd Maste PRT(" p_align: %#jx\n", (uintmax_t)ph.p_align); 1559*3fe401a5SEd Maste } else { 1560*3fe401a5SEd Maste if (!header) { 1561*3fe401a5SEd Maste PRT("\nprogram header:\n"); 1562*3fe401a5SEd Maste header = 1; 1563*3fe401a5SEd Maste } 1564*3fe401a5SEd Maste PRT("\n"); 1565*3fe401a5SEd Maste PRT("entry: %d\n", i); 1566*3fe401a5SEd Maste PRT("\tp_type: %s\n", p_types[ph.p_type & 0x7]); 1567*3fe401a5SEd Maste PRT("\tp_offset: %ju\n", (uintmax_t)ph.p_offset); 1568*3fe401a5SEd Maste PRT("\tp_vaddr: %#jx\n", (uintmax_t)ph.p_vaddr); 1569*3fe401a5SEd Maste PRT("\tp_paddr: %#jx\n", (uintmax_t)ph.p_paddr); 1570*3fe401a5SEd Maste PRT("\tp_filesz: %ju\n", (uintmax_t)ph.p_filesz); 1571*3fe401a5SEd Maste PRT("\tp_memsz: %ju\n", (uintmax_t)ph.p_memsz); 1572*3fe401a5SEd Maste PRT("\tp_flags: %s\n", p_flags[ph.p_flags]); 1573*3fe401a5SEd Maste PRT("\tp_align: %ju\n", (uintmax_t)ph.p_align); 1574*3fe401a5SEd Maste } 1575*3fe401a5SEd Maste } 1576*3fe401a5SEd Maste } 1577*3fe401a5SEd Maste 1578*3fe401a5SEd Maste /* 1579*3fe401a5SEd Maste * Dump the ELF Section Header Table. 1580*3fe401a5SEd Maste */ 1581*3fe401a5SEd Maste static void 1582*3fe401a5SEd Maste elf_print_shdr(struct elfdump *ed) 1583*3fe401a5SEd Maste { 1584*3fe401a5SEd Maste struct section *s; 1585*3fe401a5SEd Maste int i; 1586*3fe401a5SEd Maste 1587*3fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 1588*3fe401a5SEd Maste return; 1589*3fe401a5SEd Maste 1590*3fe401a5SEd Maste if ((ed->flags & SOLARIS_FMT) == 0) 1591*3fe401a5SEd Maste PRT("\nsection header:\n"); 1592*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 1593*3fe401a5SEd Maste s = &ed->sl[i]; 1594*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1595*3fe401a5SEd Maste if (i == 0) 1596*3fe401a5SEd Maste continue; 1597*3fe401a5SEd Maste PRT("\nSection Header[%d]:", i); 1598*3fe401a5SEd Maste PRT(" sh_name: %s\n", s->name); 1599*3fe401a5SEd Maste PRT(" sh_addr: %#-14jx", (uintmax_t)s->addr); 1600*3fe401a5SEd Maste if (s->flags != 0) 1601*3fe401a5SEd Maste PRT(" sh_flags: [ %s ]\n", sh_flags(s->flags)); 1602*3fe401a5SEd Maste else 1603*3fe401a5SEd Maste PRT(" sh_flags: 0\n"); 1604*3fe401a5SEd Maste PRT(" sh_size: %#-14jx", (uintmax_t)s->sz); 1605*3fe401a5SEd Maste PRT(" sh_type: [ %s ]\n", sh_types(s->type)); 1606*3fe401a5SEd Maste PRT(" sh_offset: %#-14jx", (uintmax_t)s->off); 1607*3fe401a5SEd Maste PRT(" sh_entsize: %#jx\n", (uintmax_t)s->entsize); 1608*3fe401a5SEd Maste PRT(" sh_link: %-14u", s->link); 1609*3fe401a5SEd Maste PRT(" sh_info: %u\n", s->info); 1610*3fe401a5SEd Maste PRT(" sh_addralign: %#jx\n", (uintmax_t)s->align); 1611*3fe401a5SEd Maste } else { 1612*3fe401a5SEd Maste PRT("\n"); 1613*3fe401a5SEd Maste PRT("entry: %ju\n", (uintmax_t)i); 1614*3fe401a5SEd Maste PRT("\tsh_name: %s\n", s->name); 1615*3fe401a5SEd Maste PRT("\tsh_type: %s\n", sh_types(s->type)); 1616*3fe401a5SEd Maste PRT("\tsh_flags: %s\n", sh_flags(s->flags)); 1617*3fe401a5SEd Maste PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr); 1618*3fe401a5SEd Maste PRT("\tsh_offset: %ju\n", (uintmax_t)s->off); 1619*3fe401a5SEd Maste PRT("\tsh_size: %ju\n", (uintmax_t)s->sz); 1620*3fe401a5SEd Maste PRT("\tsh_link: %u\n", s->link); 1621*3fe401a5SEd Maste PRT("\tsh_info: %u\n", s->info); 1622*3fe401a5SEd Maste PRT("\tsh_addralign: %ju\n", (uintmax_t)s->align); 1623*3fe401a5SEd Maste PRT("\tsh_entsize: %ju\n", (uintmax_t)s->entsize); 1624*3fe401a5SEd Maste } 1625*3fe401a5SEd Maste } 1626*3fe401a5SEd Maste } 1627*3fe401a5SEd Maste 1628*3fe401a5SEd Maste /* 1629*3fe401a5SEd Maste * Retrieve the content of the corresponding SHT_SUNW_versym section for 1630*3fe401a5SEd Maste * a symbol table section. 1631*3fe401a5SEd Maste */ 1632*3fe401a5SEd Maste static void 1633*3fe401a5SEd Maste get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs) 1634*3fe401a5SEd Maste { 1635*3fe401a5SEd Maste struct section *s; 1636*3fe401a5SEd Maste Elf_Data *data; 1637*3fe401a5SEd Maste int j, elferr; 1638*3fe401a5SEd Maste 1639*3fe401a5SEd Maste s = NULL; 1640*3fe401a5SEd Maste for (j = 0; (size_t)j < ed->shnum; j++) { 1641*3fe401a5SEd Maste s = &ed->sl[j]; 1642*3fe401a5SEd Maste if (s->type == SHT_SUNW_versym && s->link == (uint32_t)i) 1643*3fe401a5SEd Maste break; 1644*3fe401a5SEd Maste } 1645*3fe401a5SEd Maste if ((size_t)j >= ed->shnum) { 1646*3fe401a5SEd Maste *vs = NULL; 1647*3fe401a5SEd Maste return; 1648*3fe401a5SEd Maste } 1649*3fe401a5SEd Maste (void) elf_errno(); 1650*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1651*3fe401a5SEd Maste elferr = elf_errno(); 1652*3fe401a5SEd Maste if (elferr != 0) 1653*3fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1654*3fe401a5SEd Maste *vs = NULL; 1655*3fe401a5SEd Maste return; 1656*3fe401a5SEd Maste } 1657*3fe401a5SEd Maste 1658*3fe401a5SEd Maste *vs = data->d_buf; 1659*3fe401a5SEd Maste *nvs = data->d_size / s->entsize; 1660*3fe401a5SEd Maste } 1661*3fe401a5SEd Maste 1662*3fe401a5SEd Maste /* 1663*3fe401a5SEd Maste * Dump the symbol table section. 1664*3fe401a5SEd Maste */ 1665*3fe401a5SEd Maste static void 1666*3fe401a5SEd Maste elf_print_symtab(struct elfdump *ed, int i) 1667*3fe401a5SEd Maste { 1668*3fe401a5SEd Maste struct section *s; 1669*3fe401a5SEd Maste const char *name; 1670*3fe401a5SEd Maste uint16_t *vs; 1671*3fe401a5SEd Maste char idx[10]; 1672*3fe401a5SEd Maste Elf_Data *data; 1673*3fe401a5SEd Maste GElf_Sym sym; 1674*3fe401a5SEd Maste int len, j, elferr, nvs; 1675*3fe401a5SEd Maste 1676*3fe401a5SEd Maste s = &ed->sl[i]; 1677*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 1678*3fe401a5SEd Maste PRT("\nSymbol Table Section: %s\n", s->name); 1679*3fe401a5SEd Maste else 1680*3fe401a5SEd Maste PRT("\nsymbol table (%s):\n", s->name); 1681*3fe401a5SEd Maste (void) elf_errno(); 1682*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1683*3fe401a5SEd Maste elferr = elf_errno(); 1684*3fe401a5SEd Maste if (elferr != 0) 1685*3fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1686*3fe401a5SEd Maste return; 1687*3fe401a5SEd Maste } 1688*3fe401a5SEd Maste vs = NULL; 1689*3fe401a5SEd Maste nvs = 0; 1690*3fe401a5SEd Maste len = data->d_size / s->entsize; 1691*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1692*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) 1693*3fe401a5SEd Maste PRT(" index value "); 1694*3fe401a5SEd Maste else 1695*3fe401a5SEd Maste PRT(" index value "); 1696*3fe401a5SEd Maste PRT("size type bind oth ver shndx name\n"); 1697*3fe401a5SEd Maste get_versym(ed, i, &vs, &nvs); 1698*3fe401a5SEd Maste if (vs != NULL && nvs != len) { 1699*3fe401a5SEd Maste warnx("#symbol not equal to #versym"); 1700*3fe401a5SEd Maste vs = NULL; 1701*3fe401a5SEd Maste } 1702*3fe401a5SEd Maste } 1703*3fe401a5SEd Maste for (j = 0; j < len; j++) { 1704*3fe401a5SEd Maste if (gelf_getsym(data, j, &sym) != &sym) { 1705*3fe401a5SEd Maste warnx("gelf_getsym failed: %s", elf_errmsg(-1)); 1706*3fe401a5SEd Maste continue; 1707*3fe401a5SEd Maste } 1708*3fe401a5SEd Maste name = get_string(ed, s->link, sym.st_name); 1709*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1710*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j); 1711*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) 1712*3fe401a5SEd Maste PRT("%10s ", idx); 1713*3fe401a5SEd Maste else 1714*3fe401a5SEd Maste PRT("%10s ", idx); 1715*3fe401a5SEd Maste PRT("0x%8.8jx ", (uintmax_t)sym.st_value); 1716*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) 1717*3fe401a5SEd Maste PRT("0x%8.8jx ", (uintmax_t)sym.st_size); 1718*3fe401a5SEd Maste else 1719*3fe401a5SEd Maste PRT("0x%12.12jx ", (uintmax_t)sym.st_size); 1720*3fe401a5SEd Maste PRT("%s ", st_types_S[GELF_ST_TYPE(sym.st_info)]); 1721*3fe401a5SEd Maste PRT("%s ", st_bindings_S[GELF_ST_BIND(sym.st_info)]); 1722*3fe401a5SEd Maste PRT("%c ", st_others[sym.st_other]); 1723*3fe401a5SEd Maste PRT("%3u ", (vs == NULL ? 0 : vs[j])); 1724*3fe401a5SEd Maste PRT("%-11.11s ", sh_name(ed, sym.st_shndx)); 1725*3fe401a5SEd Maste PRT("%s\n", name); 1726*3fe401a5SEd Maste } else { 1727*3fe401a5SEd Maste PRT("\nentry: %d\n", j); 1728*3fe401a5SEd Maste PRT("\tst_name: %s\n", name); 1729*3fe401a5SEd Maste PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value); 1730*3fe401a5SEd Maste PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size); 1731*3fe401a5SEd Maste PRT("\tst_info: %s %s\n", 1732*3fe401a5SEd Maste st_types[GELF_ST_TYPE(sym.st_info)], 1733*3fe401a5SEd Maste st_bindings[GELF_ST_BIND(sym.st_info)]); 1734*3fe401a5SEd Maste PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx); 1735*3fe401a5SEd Maste } 1736*3fe401a5SEd Maste } 1737*3fe401a5SEd Maste } 1738*3fe401a5SEd Maste 1739*3fe401a5SEd Maste /* 1740*3fe401a5SEd Maste * Dump the symbol tables. (.dynsym and .symtab) 1741*3fe401a5SEd Maste */ 1742*3fe401a5SEd Maste static void 1743*3fe401a5SEd Maste elf_print_symtabs(struct elfdump *ed) 1744*3fe401a5SEd Maste { 1745*3fe401a5SEd Maste int i; 1746*3fe401a5SEd Maste 1747*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) 1748*3fe401a5SEd Maste if ((ed->sl[i].type == SHT_SYMTAB || 1749*3fe401a5SEd Maste ed->sl[i].type == SHT_DYNSYM) && 1750*3fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, ed->sl[i].name))) 1751*3fe401a5SEd Maste elf_print_symtab(ed, i); 1752*3fe401a5SEd Maste } 1753*3fe401a5SEd Maste 1754*3fe401a5SEd Maste /* 1755*3fe401a5SEd Maste * Dump the content of .dynamic section. 1756*3fe401a5SEd Maste */ 1757*3fe401a5SEd Maste static void 1758*3fe401a5SEd Maste elf_print_dynamic(struct elfdump *ed) 1759*3fe401a5SEd Maste { 1760*3fe401a5SEd Maste struct section *s; 1761*3fe401a5SEd Maste const char *name; 1762*3fe401a5SEd Maste char idx[10]; 1763*3fe401a5SEd Maste Elf_Data *data; 1764*3fe401a5SEd Maste GElf_Dyn dyn; 1765*3fe401a5SEd Maste int elferr, i, len; 1766*3fe401a5SEd Maste 1767*3fe401a5SEd Maste s = NULL; 1768*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 1769*3fe401a5SEd Maste s = &ed->sl[i]; 1770*3fe401a5SEd Maste if (s->type == SHT_DYNAMIC && 1771*3fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 1772*3fe401a5SEd Maste break; 1773*3fe401a5SEd Maste } 1774*3fe401a5SEd Maste if ((size_t)i >= ed->shnum) 1775*3fe401a5SEd Maste return; 1776*3fe401a5SEd Maste 1777*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1778*3fe401a5SEd Maste PRT("Dynamic Section: %s\n", s->name); 1779*3fe401a5SEd Maste PRT(" index tag value\n"); 1780*3fe401a5SEd Maste } else 1781*3fe401a5SEd Maste PRT("\ndynamic:\n"); 1782*3fe401a5SEd Maste (void) elf_errno(); 1783*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1784*3fe401a5SEd Maste elferr = elf_errno(); 1785*3fe401a5SEd Maste if (elferr != 0) 1786*3fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1787*3fe401a5SEd Maste return; 1788*3fe401a5SEd Maste } 1789*3fe401a5SEd Maste len = data->d_size / s->entsize; 1790*3fe401a5SEd Maste for (i = 0; i < len; i++) { 1791*3fe401a5SEd Maste if (gelf_getdyn(data, i, &dyn) != &dyn) { 1792*3fe401a5SEd Maste warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); 1793*3fe401a5SEd Maste continue; 1794*3fe401a5SEd Maste } 1795*3fe401a5SEd Maste 1796*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1797*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", i); 1798*3fe401a5SEd Maste PRT("%10s %-16s ", idx, d_tags(dyn.d_tag)); 1799*3fe401a5SEd Maste } else { 1800*3fe401a5SEd Maste PRT("\n"); 1801*3fe401a5SEd Maste PRT("entry: %d\n", i); 1802*3fe401a5SEd Maste PRT("\td_tag: %s\n", d_tags(dyn.d_tag)); 1803*3fe401a5SEd Maste } 1804*3fe401a5SEd Maste switch(dyn.d_tag) { 1805*3fe401a5SEd Maste case DT_NEEDED: 1806*3fe401a5SEd Maste case DT_SONAME: 1807*3fe401a5SEd Maste case DT_RPATH: 1808*3fe401a5SEd Maste if ((name = elf_strptr(ed->elf, s->link, 1809*3fe401a5SEd Maste dyn.d_un.d_val)) == NULL) 1810*3fe401a5SEd Maste name = ""; 1811*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 1812*3fe401a5SEd Maste PRT("%#-16jx %s\n", (uintmax_t)dyn.d_un.d_val, 1813*3fe401a5SEd Maste name); 1814*3fe401a5SEd Maste else 1815*3fe401a5SEd Maste PRT("\td_val: %s\n", name); 1816*3fe401a5SEd Maste break; 1817*3fe401a5SEd Maste case DT_PLTRELSZ: 1818*3fe401a5SEd Maste case DT_RELA: 1819*3fe401a5SEd Maste case DT_RELASZ: 1820*3fe401a5SEd Maste case DT_RELAENT: 1821*3fe401a5SEd Maste case DT_RELACOUNT: 1822*3fe401a5SEd Maste case DT_STRSZ: 1823*3fe401a5SEd Maste case DT_SYMENT: 1824*3fe401a5SEd Maste case DT_RELSZ: 1825*3fe401a5SEd Maste case DT_RELENT: 1826*3fe401a5SEd Maste case DT_PLTREL: 1827*3fe401a5SEd Maste case DT_VERDEF: 1828*3fe401a5SEd Maste case DT_VERDEFNUM: 1829*3fe401a5SEd Maste case DT_VERNEED: 1830*3fe401a5SEd Maste case DT_VERNEEDNUM: 1831*3fe401a5SEd Maste case DT_VERSYM: 1832*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 1833*3fe401a5SEd Maste PRT("%#jx\n", (uintmax_t)dyn.d_un.d_val); 1834*3fe401a5SEd Maste else 1835*3fe401a5SEd Maste PRT("\td_val: %ju\n", 1836*3fe401a5SEd Maste (uintmax_t)dyn.d_un.d_val); 1837*3fe401a5SEd Maste break; 1838*3fe401a5SEd Maste case DT_PLTGOT: 1839*3fe401a5SEd Maste case DT_HASH: 1840*3fe401a5SEd Maste case DT_GNU_HASH: 1841*3fe401a5SEd Maste case DT_STRTAB: 1842*3fe401a5SEd Maste case DT_SYMTAB: 1843*3fe401a5SEd Maste case DT_INIT: 1844*3fe401a5SEd Maste case DT_FINI: 1845*3fe401a5SEd Maste case DT_REL: 1846*3fe401a5SEd Maste case DT_JMPREL: 1847*3fe401a5SEd Maste case DT_DEBUG: 1848*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 1849*3fe401a5SEd Maste PRT("%#jx\n", (uintmax_t)dyn.d_un.d_ptr); 1850*3fe401a5SEd Maste else 1851*3fe401a5SEd Maste PRT("\td_ptr: %#jx\n", 1852*3fe401a5SEd Maste (uintmax_t)dyn.d_un.d_ptr); 1853*3fe401a5SEd Maste break; 1854*3fe401a5SEd Maste case DT_NULL: 1855*3fe401a5SEd Maste case DT_SYMBOLIC: 1856*3fe401a5SEd Maste case DT_TEXTREL: 1857*3fe401a5SEd Maste default: 1858*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 1859*3fe401a5SEd Maste PRT("\n"); 1860*3fe401a5SEd Maste break; 1861*3fe401a5SEd Maste } 1862*3fe401a5SEd Maste } 1863*3fe401a5SEd Maste } 1864*3fe401a5SEd Maste 1865*3fe401a5SEd Maste /* 1866*3fe401a5SEd Maste * Dump a .rel/.rela section entry. 1867*3fe401a5SEd Maste */ 1868*3fe401a5SEd Maste static void 1869*3fe401a5SEd Maste elf_print_rel_entry(struct elfdump *ed, struct section *s, int j, 1870*3fe401a5SEd Maste struct rel_entry *r) 1871*3fe401a5SEd Maste { 1872*3fe401a5SEd Maste 1873*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1874*3fe401a5SEd Maste PRT(" %-23s ", r_type(ed->ehdr.e_machine, 1875*3fe401a5SEd Maste GELF_R_TYPE(r->u_r.rel.r_info))); 1876*3fe401a5SEd Maste PRT("%#12jx ", (uintmax_t)r->u_r.rel.r_offset); 1877*3fe401a5SEd Maste if (r->type == SHT_RELA) 1878*3fe401a5SEd Maste PRT("%10jd ", (intmax_t)r->u_r.rela.r_addend); 1879*3fe401a5SEd Maste else 1880*3fe401a5SEd Maste PRT(" "); 1881*3fe401a5SEd Maste PRT("%-14s ", s->name); 1882*3fe401a5SEd Maste PRT("%s\n", r->symn); 1883*3fe401a5SEd Maste } else { 1884*3fe401a5SEd Maste PRT("\n"); 1885*3fe401a5SEd Maste PRT("entry: %d\n", j); 1886*3fe401a5SEd Maste PRT("\tr_offset: %#jx\n", (uintmax_t)r->u_r.rel.r_offset); 1887*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) 1888*3fe401a5SEd Maste PRT("\tr_info: %#jx\n", (uintmax_t) 1889*3fe401a5SEd Maste ELF32_R_INFO(ELF64_R_SYM(r->u_r.rel.r_info), 1890*3fe401a5SEd Maste ELF64_R_TYPE(r->u_r.rel.r_info))); 1891*3fe401a5SEd Maste else 1892*3fe401a5SEd Maste PRT("\tr_info: %#jx\n", (uintmax_t)r->u_r.rel.r_info); 1893*3fe401a5SEd Maste if (r->type == SHT_RELA) 1894*3fe401a5SEd Maste PRT("\tr_addend: %jd\n", 1895*3fe401a5SEd Maste (intmax_t)r->u_r.rela.r_addend); 1896*3fe401a5SEd Maste } 1897*3fe401a5SEd Maste } 1898*3fe401a5SEd Maste 1899*3fe401a5SEd Maste /* 1900*3fe401a5SEd Maste * Dump a relocation section of type SHT_RELA. 1901*3fe401a5SEd Maste */ 1902*3fe401a5SEd Maste static void 1903*3fe401a5SEd Maste elf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data) 1904*3fe401a5SEd Maste { 1905*3fe401a5SEd Maste struct rel_entry r; 1906*3fe401a5SEd Maste int j, len; 1907*3fe401a5SEd Maste 1908*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1909*3fe401a5SEd Maste PRT("\nRelocation Section: %s\n", s->name); 1910*3fe401a5SEd Maste PRT(" type offset " 1911*3fe401a5SEd Maste "addend section with respect to\n"); 1912*3fe401a5SEd Maste } else 1913*3fe401a5SEd Maste PRT("\nrelocation with addend (%s):\n", s->name); 1914*3fe401a5SEd Maste r.type = SHT_RELA; 1915*3fe401a5SEd Maste len = data->d_size / s->entsize; 1916*3fe401a5SEd Maste for (j = 0; j < len; j++) { 1917*3fe401a5SEd Maste if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) { 1918*3fe401a5SEd Maste warnx("gelf_getrela failed: %s", 1919*3fe401a5SEd Maste elf_errmsg(-1)); 1920*3fe401a5SEd Maste continue; 1921*3fe401a5SEd Maste } 1922*3fe401a5SEd Maste r.symn = get_symbol_name(ed, s->link, 1923*3fe401a5SEd Maste GELF_R_SYM(r.u_r.rela.r_info)); 1924*3fe401a5SEd Maste elf_print_rel_entry(ed, s, j, &r); 1925*3fe401a5SEd Maste } 1926*3fe401a5SEd Maste } 1927*3fe401a5SEd Maste 1928*3fe401a5SEd Maste /* 1929*3fe401a5SEd Maste * Dump a relocation section of type SHT_REL. 1930*3fe401a5SEd Maste */ 1931*3fe401a5SEd Maste static void 1932*3fe401a5SEd Maste elf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data) 1933*3fe401a5SEd Maste { 1934*3fe401a5SEd Maste struct rel_entry r; 1935*3fe401a5SEd Maste int j, len; 1936*3fe401a5SEd Maste 1937*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 1938*3fe401a5SEd Maste PRT("\nRelocation Section: %s\n", s->name); 1939*3fe401a5SEd Maste PRT(" type offset " 1940*3fe401a5SEd Maste "section with respect to\n"); 1941*3fe401a5SEd Maste } else 1942*3fe401a5SEd Maste PRT("\nrelocation (%s):\n", s->name); 1943*3fe401a5SEd Maste r.type = SHT_REL; 1944*3fe401a5SEd Maste len = data->d_size / s->entsize; 1945*3fe401a5SEd Maste for (j = 0; j < len; j++) { 1946*3fe401a5SEd Maste if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) { 1947*3fe401a5SEd Maste warnx("gelf_getrel failed: %s", elf_errmsg(-1)); 1948*3fe401a5SEd Maste continue; 1949*3fe401a5SEd Maste } 1950*3fe401a5SEd Maste r.symn = get_symbol_name(ed, s->link, 1951*3fe401a5SEd Maste GELF_R_SYM(r.u_r.rel.r_info)); 1952*3fe401a5SEd Maste elf_print_rel_entry(ed, s, j, &r); 1953*3fe401a5SEd Maste } 1954*3fe401a5SEd Maste } 1955*3fe401a5SEd Maste 1956*3fe401a5SEd Maste /* 1957*3fe401a5SEd Maste * Dump relocation sections. 1958*3fe401a5SEd Maste */ 1959*3fe401a5SEd Maste static void 1960*3fe401a5SEd Maste elf_print_reloc(struct elfdump *ed) 1961*3fe401a5SEd Maste { 1962*3fe401a5SEd Maste struct section *s; 1963*3fe401a5SEd Maste Elf_Data *data; 1964*3fe401a5SEd Maste int i, elferr; 1965*3fe401a5SEd Maste 1966*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 1967*3fe401a5SEd Maste s = &ed->sl[i]; 1968*3fe401a5SEd Maste if ((s->type == SHT_REL || s->type == SHT_RELA) && 1969*3fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 1970*3fe401a5SEd Maste (void) elf_errno(); 1971*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1972*3fe401a5SEd Maste elferr = elf_errno(); 1973*3fe401a5SEd Maste if (elferr != 0) 1974*3fe401a5SEd Maste warnx("elf_getdata failed: %s", 1975*3fe401a5SEd Maste elf_errmsg(elferr)); 1976*3fe401a5SEd Maste continue; 1977*3fe401a5SEd Maste } 1978*3fe401a5SEd Maste if (s->type == SHT_REL) 1979*3fe401a5SEd Maste elf_print_rel(ed, s, data); 1980*3fe401a5SEd Maste else 1981*3fe401a5SEd Maste elf_print_rela(ed, s, data); 1982*3fe401a5SEd Maste } 1983*3fe401a5SEd Maste } 1984*3fe401a5SEd Maste } 1985*3fe401a5SEd Maste 1986*3fe401a5SEd Maste /* 1987*3fe401a5SEd Maste * Dump the content of PT_INTERP segment. 1988*3fe401a5SEd Maste */ 1989*3fe401a5SEd Maste static void 1990*3fe401a5SEd Maste elf_print_interp(struct elfdump *ed) 1991*3fe401a5SEd Maste { 1992*3fe401a5SEd Maste const char *s; 1993*3fe401a5SEd Maste GElf_Phdr phdr; 1994*3fe401a5SEd Maste size_t phnum; 1995*3fe401a5SEd Maste int i; 1996*3fe401a5SEd Maste 1997*3fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl) && find_name(ed, "PT_INTERP") == NULL) 1998*3fe401a5SEd Maste return; 1999*3fe401a5SEd Maste 2000*3fe401a5SEd Maste if ((s = elf_rawfile(ed->elf, NULL)) == NULL) { 2001*3fe401a5SEd Maste warnx("elf_rawfile failed: %s", elf_errmsg(-1)); 2002*3fe401a5SEd Maste return; 2003*3fe401a5SEd Maste } 2004*3fe401a5SEd Maste if (!elf_getphnum(ed->elf, &phnum)) { 2005*3fe401a5SEd Maste warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 2006*3fe401a5SEd Maste return; 2007*3fe401a5SEd Maste } 2008*3fe401a5SEd Maste for (i = 0; (size_t)i < phnum; i++) { 2009*3fe401a5SEd Maste if (gelf_getphdr(ed->elf, i, &phdr) != &phdr) { 2010*3fe401a5SEd Maste warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 2011*3fe401a5SEd Maste continue; 2012*3fe401a5SEd Maste } 2013*3fe401a5SEd Maste if (phdr.p_type == PT_INTERP) { 2014*3fe401a5SEd Maste PRT("\ninterp:\n"); 2015*3fe401a5SEd Maste PRT("\t%s\n", s + phdr.p_offset); 2016*3fe401a5SEd Maste } 2017*3fe401a5SEd Maste } 2018*3fe401a5SEd Maste } 2019*3fe401a5SEd Maste 2020*3fe401a5SEd Maste /* 2021*3fe401a5SEd Maste * Search the relocation sections for entries refering to the .got section. 2022*3fe401a5SEd Maste */ 2023*3fe401a5SEd Maste static void 2024*3fe401a5SEd Maste find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got) 2025*3fe401a5SEd Maste { 2026*3fe401a5SEd Maste struct section *s; 2027*3fe401a5SEd Maste struct rel_entry r; 2028*3fe401a5SEd Maste Elf_Data *data; 2029*3fe401a5SEd Maste int elferr, i, j, k, len; 2030*3fe401a5SEd Maste 2031*3fe401a5SEd Maste for(i = 0; (size_t)i < ed->shnum; i++) { 2032*3fe401a5SEd Maste s = &ed->sl[i]; 2033*3fe401a5SEd Maste if (s->type != SHT_REL && s->type != SHT_RELA) 2034*3fe401a5SEd Maste continue; 2035*3fe401a5SEd Maste (void) elf_errno(); 2036*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2037*3fe401a5SEd Maste elferr = elf_errno(); 2038*3fe401a5SEd Maste if (elferr != 0) 2039*3fe401a5SEd Maste warnx("elf_getdata failed: %s", 2040*3fe401a5SEd Maste elf_errmsg(elferr)); 2041*3fe401a5SEd Maste return; 2042*3fe401a5SEd Maste } 2043*3fe401a5SEd Maste memset(&r, 0, sizeof(struct rel_entry)); 2044*3fe401a5SEd Maste r.type = s->type; 2045*3fe401a5SEd Maste len = data->d_size / s->entsize; 2046*3fe401a5SEd Maste for (j = 0; j < len; j++) { 2047*3fe401a5SEd Maste if (s->type == SHT_REL) { 2048*3fe401a5SEd Maste if (gelf_getrel(data, j, &r.u_r.rel) != 2049*3fe401a5SEd Maste &r.u_r.rel) { 2050*3fe401a5SEd Maste warnx("gelf_getrel failed: %s", 2051*3fe401a5SEd Maste elf_errmsg(-1)); 2052*3fe401a5SEd Maste continue; 2053*3fe401a5SEd Maste } 2054*3fe401a5SEd Maste } else { 2055*3fe401a5SEd Maste if (gelf_getrela(data, j, &r.u_r.rela) != 2056*3fe401a5SEd Maste &r.u_r.rela) { 2057*3fe401a5SEd Maste warnx("gelf_getrel failed: %s", 2058*3fe401a5SEd Maste elf_errmsg(-1)); 2059*3fe401a5SEd Maste continue; 2060*3fe401a5SEd Maste } 2061*3fe401a5SEd Maste } 2062*3fe401a5SEd Maste if (r.u_r.rel.r_offset >= gs->addr && 2063*3fe401a5SEd Maste r.u_r.rel.r_offset < gs->addr + gs->sz) { 2064*3fe401a5SEd Maste r.symn = get_symbol_name(ed, s->link, 2065*3fe401a5SEd Maste GELF_R_SYM(r.u_r.rel.r_info)); 2066*3fe401a5SEd Maste k = (r.u_r.rel.r_offset - gs->addr) / 2067*3fe401a5SEd Maste gs->entsize; 2068*3fe401a5SEd Maste memcpy(&got[k], &r, sizeof(struct rel_entry)); 2069*3fe401a5SEd Maste } 2070*3fe401a5SEd Maste } 2071*3fe401a5SEd Maste } 2072*3fe401a5SEd Maste } 2073*3fe401a5SEd Maste 2074*3fe401a5SEd Maste static void 2075*3fe401a5SEd Maste elf_print_got_section(struct elfdump *ed, struct section *s) 2076*3fe401a5SEd Maste { 2077*3fe401a5SEd Maste struct rel_entry *got; 2078*3fe401a5SEd Maste Elf_Data *data, dst; 2079*3fe401a5SEd Maste int elferr, i, len; 2080*3fe401a5SEd Maste 2081*3fe401a5SEd Maste if (s->entsize == 0) { 2082*3fe401a5SEd Maste /* XXX IA64 GOT section generated by gcc has entry size 0. */ 2083*3fe401a5SEd Maste if (s->align != 0) 2084*3fe401a5SEd Maste s->entsize = s->align; 2085*3fe401a5SEd Maste else 2086*3fe401a5SEd Maste return; 2087*3fe401a5SEd Maste } 2088*3fe401a5SEd Maste 2089*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2090*3fe401a5SEd Maste PRT("\nGlobal Offset Table Section: %s (%jd entries)\n", 2091*3fe401a5SEd Maste s->name, s->sz / s->entsize); 2092*3fe401a5SEd Maste else 2093*3fe401a5SEd Maste PRT("\nglobal offset table: %s\n", s->name); 2094*3fe401a5SEd Maste (void) elf_errno(); 2095*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2096*3fe401a5SEd Maste elferr = elf_errno(); 2097*3fe401a5SEd Maste if (elferr != 0) 2098*3fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 2099*3fe401a5SEd Maste return; 2100*3fe401a5SEd Maste } 2101*3fe401a5SEd Maste 2102*3fe401a5SEd Maste /* 2103*3fe401a5SEd Maste * GOT section has section type SHT_PROGBITS, thus libelf treats it as 2104*3fe401a5SEd Maste * byte stream and will not perfrom any translation on it. As a result, 2105*3fe401a5SEd Maste * an exlicit call to gelf_xlatetom is needed here. Depends on arch, 2106*3fe401a5SEd Maste * GOT section should be translated to either WORD or XWORD. 2107*3fe401a5SEd Maste */ 2108*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) 2109*3fe401a5SEd Maste data->d_type = ELF_T_WORD; 2110*3fe401a5SEd Maste else 2111*3fe401a5SEd Maste data->d_type = ELF_T_XWORD; 2112*3fe401a5SEd Maste memcpy(&dst, data, sizeof(Elf_Data)); 2113*3fe401a5SEd Maste if (gelf_xlatetom(ed->elf, &dst, data, ed->ehdr.e_ident[EI_DATA]) != 2114*3fe401a5SEd Maste &dst) { 2115*3fe401a5SEd Maste warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 2116*3fe401a5SEd Maste return; 2117*3fe401a5SEd Maste } 2118*3fe401a5SEd Maste len = dst.d_size / s->entsize; 2119*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2120*3fe401a5SEd Maste /* 2121*3fe401a5SEd Maste * In verbose/Solaris mode, we search the relocation sections 2122*3fe401a5SEd Maste * and try to find the corresponding reloc entry for each GOT 2123*3fe401a5SEd Maste * section entry. 2124*3fe401a5SEd Maste */ 2125*3fe401a5SEd Maste if ((got = calloc(len, sizeof(struct rel_entry))) == NULL) 2126*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 2127*3fe401a5SEd Maste find_gotrel(ed, s, got); 2128*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) { 2129*3fe401a5SEd Maste PRT(" ndx addr value reloc "); 2130*3fe401a5SEd Maste PRT("addend symbol\n"); 2131*3fe401a5SEd Maste } else { 2132*3fe401a5SEd Maste PRT(" ndx addr value "); 2133*3fe401a5SEd Maste PRT("reloc addend symbol\n"); 2134*3fe401a5SEd Maste } 2135*3fe401a5SEd Maste for(i = 0; i < len; i++) { 2136*3fe401a5SEd Maste PRT("[%5.5d] ", i); 2137*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) { 2138*3fe401a5SEd Maste PRT("%-8.8jx ", s->addr + i * s->entsize); 2139*3fe401a5SEd Maste PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i)); 2140*3fe401a5SEd Maste } else { 2141*3fe401a5SEd Maste PRT("%-16.16jx ", s->addr + i * s->entsize); 2142*3fe401a5SEd Maste PRT("%-16.16jx ", *((uint64_t *)dst.d_buf + i)); 2143*3fe401a5SEd Maste } 2144*3fe401a5SEd Maste PRT("%-18s ", r_type(ed->ehdr.e_machine, 2145*3fe401a5SEd Maste GELF_R_TYPE(got[i].u_r.rel.r_info))); 2146*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) 2147*3fe401a5SEd Maste PRT("%-8.8jd ", 2148*3fe401a5SEd Maste (intmax_t)got[i].u_r.rela.r_addend); 2149*3fe401a5SEd Maste else 2150*3fe401a5SEd Maste PRT("%-12.12jd ", 2151*3fe401a5SEd Maste (intmax_t)got[i].u_r.rela.r_addend); 2152*3fe401a5SEd Maste if (got[i].symn == NULL) 2153*3fe401a5SEd Maste got[i].symn = ""; 2154*3fe401a5SEd Maste PRT("%s\n", got[i].symn); 2155*3fe401a5SEd Maste } 2156*3fe401a5SEd Maste free(got); 2157*3fe401a5SEd Maste } else { 2158*3fe401a5SEd Maste for(i = 0; i < len; i++) { 2159*3fe401a5SEd Maste PRT("\nentry: %d\n", i); 2160*3fe401a5SEd Maste if (ed->ec == ELFCLASS32) 2161*3fe401a5SEd Maste PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i)); 2162*3fe401a5SEd Maste else 2163*3fe401a5SEd Maste PRT("\t%#jx\n", *((uint64_t *)dst.d_buf + i)); 2164*3fe401a5SEd Maste } 2165*3fe401a5SEd Maste } 2166*3fe401a5SEd Maste } 2167*3fe401a5SEd Maste 2168*3fe401a5SEd Maste /* 2169*3fe401a5SEd Maste * Dump the content of Global Offset Table section. 2170*3fe401a5SEd Maste */ 2171*3fe401a5SEd Maste static void 2172*3fe401a5SEd Maste elf_print_got(struct elfdump *ed) 2173*3fe401a5SEd Maste { 2174*3fe401a5SEd Maste struct section *s; 2175*3fe401a5SEd Maste int i; 2176*3fe401a5SEd Maste 2177*3fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 2178*3fe401a5SEd Maste return; 2179*3fe401a5SEd Maste 2180*3fe401a5SEd Maste s = NULL; 2181*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 2182*3fe401a5SEd Maste s = &ed->sl[i]; 2183*3fe401a5SEd Maste if (s->name && !strncmp(s->name, ".got", 4) && 2184*3fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 2185*3fe401a5SEd Maste elf_print_got_section(ed, s); 2186*3fe401a5SEd Maste } 2187*3fe401a5SEd Maste } 2188*3fe401a5SEd Maste 2189*3fe401a5SEd Maste /* 2190*3fe401a5SEd Maste * Dump the content of .note.ABI-tag section. 2191*3fe401a5SEd Maste */ 2192*3fe401a5SEd Maste static void 2193*3fe401a5SEd Maste elf_print_note(struct elfdump *ed) 2194*3fe401a5SEd Maste { 2195*3fe401a5SEd Maste struct section *s; 2196*3fe401a5SEd Maste Elf_Data *data; 2197*3fe401a5SEd Maste Elf_Note *en; 2198*3fe401a5SEd Maste uint32_t namesz; 2199*3fe401a5SEd Maste uint32_t descsz; 2200*3fe401a5SEd Maste uint32_t desc; 2201*3fe401a5SEd Maste size_t count; 2202*3fe401a5SEd Maste int elferr, i; 2203*3fe401a5SEd Maste char *src, idx[10]; 2204*3fe401a5SEd Maste 2205*3fe401a5SEd Maste s = NULL; 2206*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 2207*3fe401a5SEd Maste s = &ed->sl[i]; 2208*3fe401a5SEd Maste if (s->type == SHT_NOTE && s->name && 2209*3fe401a5SEd Maste !strcmp(s->name, ".note.ABI-tag") && 2210*3fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 2211*3fe401a5SEd Maste break; 2212*3fe401a5SEd Maste } 2213*3fe401a5SEd Maste if ((size_t)i >= ed->shnum) 2214*3fe401a5SEd Maste return; 2215*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2216*3fe401a5SEd Maste PRT("\nNote Section: %s\n", s->name); 2217*3fe401a5SEd Maste else 2218*3fe401a5SEd Maste PRT("\nnote (%s):\n", s->name); 2219*3fe401a5SEd Maste (void) elf_errno(); 2220*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2221*3fe401a5SEd Maste elferr = elf_errno(); 2222*3fe401a5SEd Maste if (elferr != 0) 2223*3fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 2224*3fe401a5SEd Maste return; 2225*3fe401a5SEd Maste } 2226*3fe401a5SEd Maste src = data->d_buf; 2227*3fe401a5SEd Maste count = data->d_size; 2228*3fe401a5SEd Maste while (count > sizeof(Elf_Note)) { 2229*3fe401a5SEd Maste en = (Elf_Note *) (uintptr_t) src; 2230*3fe401a5SEd Maste namesz = en->n_namesz; 2231*3fe401a5SEd Maste descsz = en->n_descsz; 2232*3fe401a5SEd Maste src += sizeof(Elf_Note); 2233*3fe401a5SEd Maste count -= sizeof(Elf_Note); 2234*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2235*3fe401a5SEd Maste PRT("\n type %#x\n", en->n_type); 2236*3fe401a5SEd Maste PRT(" namesz %#x:\n", en->n_namesz); 2237*3fe401a5SEd Maste PRT("%s\n", src); 2238*3fe401a5SEd Maste } else 2239*3fe401a5SEd Maste PRT("\t%s ", src); 2240*3fe401a5SEd Maste src += roundup2(namesz, 4); 2241*3fe401a5SEd Maste count -= roundup2(namesz, 4); 2242*3fe401a5SEd Maste 2243*3fe401a5SEd Maste /* 2244*3fe401a5SEd Maste * Note that we dump the whole desc part if we're in 2245*3fe401a5SEd Maste * "Solaris mode", while in the normal mode, we only look 2246*3fe401a5SEd Maste * at the first 4 bytes (a 32bit word) of the desc, i.e, 2247*3fe401a5SEd Maste * we assume that it's always a FreeBSD version number. 2248*3fe401a5SEd Maste */ 2249*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2250*3fe401a5SEd Maste PRT(" descsz %#x:", en->n_descsz); 2251*3fe401a5SEd Maste for (i = 0; (uint32_t)i < descsz; i++) { 2252*3fe401a5SEd Maste if ((i & 0xF) == 0) { 2253*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "desc[%d]", 2254*3fe401a5SEd Maste i); 2255*3fe401a5SEd Maste PRT("\n %-9s", idx); 2256*3fe401a5SEd Maste } else if ((i & 0x3) == 0) 2257*3fe401a5SEd Maste PRT(" "); 2258*3fe401a5SEd Maste PRT(" %2.2x", src[i]); 2259*3fe401a5SEd Maste } 2260*3fe401a5SEd Maste PRT("\n"); 2261*3fe401a5SEd Maste } else { 2262*3fe401a5SEd Maste if (ed->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) 2263*3fe401a5SEd Maste desc = be32dec(src); 2264*3fe401a5SEd Maste else 2265*3fe401a5SEd Maste desc = le32dec(src); 2266*3fe401a5SEd Maste PRT("%d\n", desc); 2267*3fe401a5SEd Maste } 2268*3fe401a5SEd Maste src += roundup2(descsz, 4); 2269*3fe401a5SEd Maste count -= roundup2(descsz, 4); 2270*3fe401a5SEd Maste } 2271*3fe401a5SEd Maste } 2272*3fe401a5SEd Maste 2273*3fe401a5SEd Maste /* 2274*3fe401a5SEd Maste * Dump a hash table. 2275*3fe401a5SEd Maste */ 2276*3fe401a5SEd Maste static void 2277*3fe401a5SEd Maste elf_print_svr4_hash(struct elfdump *ed, struct section *s) 2278*3fe401a5SEd Maste { 2279*3fe401a5SEd Maste Elf_Data *data; 2280*3fe401a5SEd Maste uint32_t *buf; 2281*3fe401a5SEd Maste uint32_t *bucket, *chain; 2282*3fe401a5SEd Maste uint32_t nbucket, nchain; 2283*3fe401a5SEd Maste uint32_t *bl, *c, maxl, total; 2284*3fe401a5SEd Maste int i, j, first, elferr; 2285*3fe401a5SEd Maste char idx[10]; 2286*3fe401a5SEd Maste 2287*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2288*3fe401a5SEd Maste PRT("\nHash Section: %s\n", s->name); 2289*3fe401a5SEd Maste else 2290*3fe401a5SEd Maste PRT("\nhash table (%s):\n", s->name); 2291*3fe401a5SEd Maste (void) elf_errno(); 2292*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2293*3fe401a5SEd Maste elferr = elf_errno(); 2294*3fe401a5SEd Maste if (elferr != 0) 2295*3fe401a5SEd Maste warnx("elf_getdata failed: %s", 2296*3fe401a5SEd Maste elf_errmsg(elferr)); 2297*3fe401a5SEd Maste return; 2298*3fe401a5SEd Maste } 2299*3fe401a5SEd Maste if (data->d_size < 2 * sizeof(uint32_t)) { 2300*3fe401a5SEd Maste warnx(".hash section too small"); 2301*3fe401a5SEd Maste return; 2302*3fe401a5SEd Maste } 2303*3fe401a5SEd Maste buf = data->d_buf; 2304*3fe401a5SEd Maste nbucket = buf[0]; 2305*3fe401a5SEd Maste nchain = buf[1]; 2306*3fe401a5SEd Maste if (nbucket <= 0 || nchain <= 0) { 2307*3fe401a5SEd Maste warnx("Malformed .hash section"); 2308*3fe401a5SEd Maste return; 2309*3fe401a5SEd Maste } 2310*3fe401a5SEd Maste if (data->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) { 2311*3fe401a5SEd Maste warnx("Malformed .hash section"); 2312*3fe401a5SEd Maste return; 2313*3fe401a5SEd Maste } 2314*3fe401a5SEd Maste bucket = &buf[2]; 2315*3fe401a5SEd Maste chain = &buf[2 + nbucket]; 2316*3fe401a5SEd Maste 2317*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2318*3fe401a5SEd Maste maxl = 0; 2319*3fe401a5SEd Maste if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 2320*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 2321*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 2322*3fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; 2323*3fe401a5SEd Maste j = chain[j]) 2324*3fe401a5SEd Maste if (++bl[i] > maxl) 2325*3fe401a5SEd Maste maxl = bl[i]; 2326*3fe401a5SEd Maste if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 2327*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 2328*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 2329*3fe401a5SEd Maste c[bl[i]]++; 2330*3fe401a5SEd Maste PRT(" bucket symndx name\n"); 2331*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) { 2332*3fe401a5SEd Maste first = 1; 2333*3fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; 2334*3fe401a5SEd Maste j = chain[j]) { 2335*3fe401a5SEd Maste if (first) { 2336*3fe401a5SEd Maste PRT("%10d ", i); 2337*3fe401a5SEd Maste first = 0; 2338*3fe401a5SEd Maste } else 2339*3fe401a5SEd Maste PRT(" "); 2340*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j); 2341*3fe401a5SEd Maste PRT("%-10s ", idx); 2342*3fe401a5SEd Maste PRT("%s\n", get_symbol_name(ed, s->link, j)); 2343*3fe401a5SEd Maste } 2344*3fe401a5SEd Maste } 2345*3fe401a5SEd Maste PRT("\n"); 2346*3fe401a5SEd Maste total = 0; 2347*3fe401a5SEd Maste for (i = 0; (uint32_t)i <= maxl; i++) { 2348*3fe401a5SEd Maste total += c[i] * i; 2349*3fe401a5SEd Maste PRT("%10u buckets contain %8d symbols\n", c[i], i); 2350*3fe401a5SEd Maste } 2351*3fe401a5SEd Maste PRT("%10u buckets %8u symbols (globals)\n", nbucket, 2352*3fe401a5SEd Maste total); 2353*3fe401a5SEd Maste } else { 2354*3fe401a5SEd Maste PRT("\nnbucket: %u\n", nbucket); 2355*3fe401a5SEd Maste PRT("nchain: %u\n\n", nchain); 2356*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 2357*3fe401a5SEd Maste PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 2358*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nchain; i++) 2359*3fe401a5SEd Maste PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 2360*3fe401a5SEd Maste } 2361*3fe401a5SEd Maste } 2362*3fe401a5SEd Maste 2363*3fe401a5SEd Maste /* 2364*3fe401a5SEd Maste * Dump a 64bit hash table. 2365*3fe401a5SEd Maste */ 2366*3fe401a5SEd Maste static void 2367*3fe401a5SEd Maste elf_print_svr4_hash64(struct elfdump *ed, struct section *s) 2368*3fe401a5SEd Maste { 2369*3fe401a5SEd Maste Elf_Data *data, dst; 2370*3fe401a5SEd Maste uint64_t *buf; 2371*3fe401a5SEd Maste uint64_t *bucket, *chain; 2372*3fe401a5SEd Maste uint64_t nbucket, nchain; 2373*3fe401a5SEd Maste uint64_t *bl, *c, maxl, total; 2374*3fe401a5SEd Maste int i, j, elferr, first; 2375*3fe401a5SEd Maste char idx[10]; 2376*3fe401a5SEd Maste 2377*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2378*3fe401a5SEd Maste PRT("\nHash Section: %s\n", s->name); 2379*3fe401a5SEd Maste else 2380*3fe401a5SEd Maste PRT("\nhash table (%s):\n", s->name); 2381*3fe401a5SEd Maste 2382*3fe401a5SEd Maste /* 2383*3fe401a5SEd Maste * ALPHA uses 64-bit hash entries. Since libelf assumes that 2384*3fe401a5SEd Maste * .hash section contains only 32-bit entry, an explicit 2385*3fe401a5SEd Maste * gelf_xlatetom is needed here. 2386*3fe401a5SEd Maste */ 2387*3fe401a5SEd Maste (void) elf_errno(); 2388*3fe401a5SEd Maste if ((data = elf_rawdata(s->scn, NULL)) == NULL) { 2389*3fe401a5SEd Maste elferr = elf_errno(); 2390*3fe401a5SEd Maste if (elferr != 0) 2391*3fe401a5SEd Maste warnx("elf_rawdata failed: %s", 2392*3fe401a5SEd Maste elf_errmsg(elferr)); 2393*3fe401a5SEd Maste return; 2394*3fe401a5SEd Maste } 2395*3fe401a5SEd Maste data->d_type = ELF_T_XWORD; 2396*3fe401a5SEd Maste memcpy(&dst, data, sizeof(Elf_Data)); 2397*3fe401a5SEd Maste if (gelf_xlatetom(ed->elf, &dst, data, 2398*3fe401a5SEd Maste ed->ehdr.e_ident[EI_DATA]) != &dst) { 2399*3fe401a5SEd Maste warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 2400*3fe401a5SEd Maste return; 2401*3fe401a5SEd Maste } 2402*3fe401a5SEd Maste if (dst.d_size < 2 * sizeof(uint64_t)) { 2403*3fe401a5SEd Maste warnx(".hash section too small"); 2404*3fe401a5SEd Maste return; 2405*3fe401a5SEd Maste } 2406*3fe401a5SEd Maste buf = dst.d_buf; 2407*3fe401a5SEd Maste nbucket = buf[0]; 2408*3fe401a5SEd Maste nchain = buf[1]; 2409*3fe401a5SEd Maste if (nbucket <= 0 || nchain <= 0) { 2410*3fe401a5SEd Maste warnx("Malformed .hash section"); 2411*3fe401a5SEd Maste return; 2412*3fe401a5SEd Maste } 2413*3fe401a5SEd Maste if (dst.d_size != (nbucket + nchain + 2) * sizeof(uint64_t)) { 2414*3fe401a5SEd Maste warnx("Malformed .hash section"); 2415*3fe401a5SEd Maste return; 2416*3fe401a5SEd Maste } 2417*3fe401a5SEd Maste bucket = &buf[2]; 2418*3fe401a5SEd Maste chain = &buf[2 + nbucket]; 2419*3fe401a5SEd Maste 2420*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2421*3fe401a5SEd Maste maxl = 0; 2422*3fe401a5SEd Maste if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 2423*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 2424*3fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) 2425*3fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint64_t)j < nchain; 2426*3fe401a5SEd Maste j = chain[j]) 2427*3fe401a5SEd Maste if (++bl[i] > maxl) 2428*3fe401a5SEd Maste maxl = bl[i]; 2429*3fe401a5SEd Maste if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 2430*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 2431*3fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) 2432*3fe401a5SEd Maste c[bl[i]]++; 2433*3fe401a5SEd Maste PRT(" bucket symndx name\n"); 2434*3fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) { 2435*3fe401a5SEd Maste first = 1; 2436*3fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint64_t)j < nchain; 2437*3fe401a5SEd Maste j = chain[j]) { 2438*3fe401a5SEd Maste if (first) { 2439*3fe401a5SEd Maste PRT("%10d ", i); 2440*3fe401a5SEd Maste first = 0; 2441*3fe401a5SEd Maste } else 2442*3fe401a5SEd Maste PRT(" "); 2443*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j); 2444*3fe401a5SEd Maste PRT("%-10s ", idx); 2445*3fe401a5SEd Maste PRT("%s\n", get_symbol_name(ed, s->link, j)); 2446*3fe401a5SEd Maste } 2447*3fe401a5SEd Maste } 2448*3fe401a5SEd Maste PRT("\n"); 2449*3fe401a5SEd Maste total = 0; 2450*3fe401a5SEd Maste for (i = 0; (uint64_t)i <= maxl; i++) { 2451*3fe401a5SEd Maste total += c[i] * i; 2452*3fe401a5SEd Maste PRT("%10ju buckets contain %8d symbols\n", 2453*3fe401a5SEd Maste (uintmax_t)c[i], i); 2454*3fe401a5SEd Maste } 2455*3fe401a5SEd Maste PRT("%10ju buckets %8ju symbols (globals)\n", 2456*3fe401a5SEd Maste (uintmax_t)nbucket, (uintmax_t)total); 2457*3fe401a5SEd Maste } else { 2458*3fe401a5SEd Maste PRT("\nnbucket: %ju\n", (uintmax_t)nbucket); 2459*3fe401a5SEd Maste PRT("nchain: %ju\n\n", (uintmax_t)nchain); 2460*3fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) 2461*3fe401a5SEd Maste PRT("bucket[%d]:\n\t%ju\n\n", i, (uintmax_t)bucket[i]); 2462*3fe401a5SEd Maste for (i = 0; (uint64_t)i < nchain; i++) 2463*3fe401a5SEd Maste PRT("chain[%d]:\n\t%ju\n\n", i, (uintmax_t)chain[i]); 2464*3fe401a5SEd Maste } 2465*3fe401a5SEd Maste 2466*3fe401a5SEd Maste } 2467*3fe401a5SEd Maste 2468*3fe401a5SEd Maste /* 2469*3fe401a5SEd Maste * Dump a GNU hash table. 2470*3fe401a5SEd Maste */ 2471*3fe401a5SEd Maste static void 2472*3fe401a5SEd Maste elf_print_gnu_hash(struct elfdump *ed, struct section *s) 2473*3fe401a5SEd Maste { 2474*3fe401a5SEd Maste struct section *ds; 2475*3fe401a5SEd Maste Elf_Data *data; 2476*3fe401a5SEd Maste uint32_t *buf; 2477*3fe401a5SEd Maste uint32_t *bucket, *chain; 2478*3fe401a5SEd Maste uint32_t nbucket, nchain, symndx, maskwords, shift2; 2479*3fe401a5SEd Maste uint32_t *bl, *c, maxl, total; 2480*3fe401a5SEd Maste int i, j, first, elferr, dynsymcount; 2481*3fe401a5SEd Maste char idx[10]; 2482*3fe401a5SEd Maste 2483*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2484*3fe401a5SEd Maste PRT("\nGNU Hash Section: %s\n", s->name); 2485*3fe401a5SEd Maste else 2486*3fe401a5SEd Maste PRT("\ngnu hash table (%s):\n", s->name); 2487*3fe401a5SEd Maste (void) elf_errno(); 2488*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2489*3fe401a5SEd Maste elferr = elf_errno(); 2490*3fe401a5SEd Maste if (elferr != 0) 2491*3fe401a5SEd Maste warnx("elf_getdata failed: %s", 2492*3fe401a5SEd Maste elf_errmsg(elferr)); 2493*3fe401a5SEd Maste return; 2494*3fe401a5SEd Maste } 2495*3fe401a5SEd Maste if (data->d_size < 4 * sizeof(uint32_t)) { 2496*3fe401a5SEd Maste warnx(".gnu.hash section too small"); 2497*3fe401a5SEd Maste return; 2498*3fe401a5SEd Maste } 2499*3fe401a5SEd Maste buf = data->d_buf; 2500*3fe401a5SEd Maste nbucket = buf[0]; 2501*3fe401a5SEd Maste symndx = buf[1]; 2502*3fe401a5SEd Maste maskwords = buf[2]; 2503*3fe401a5SEd Maste shift2 = buf[3]; 2504*3fe401a5SEd Maste buf += 4; 2505*3fe401a5SEd Maste ds = &ed->sl[s->link]; 2506*3fe401a5SEd Maste dynsymcount = ds->sz / ds->entsize; 2507*3fe401a5SEd Maste nchain = dynsymcount - symndx; 2508*3fe401a5SEd Maste if (data->d_size != 4 * sizeof(uint32_t) + maskwords * 2509*3fe401a5SEd Maste (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + 2510*3fe401a5SEd Maste (nbucket + nchain) * sizeof(uint32_t)) { 2511*3fe401a5SEd Maste warnx("Malformed .gnu.hash section"); 2512*3fe401a5SEd Maste return; 2513*3fe401a5SEd Maste } 2514*3fe401a5SEd Maste bucket = buf + (ed->ec == ELFCLASS32 ? maskwords : maskwords * 2); 2515*3fe401a5SEd Maste chain = bucket + nbucket; 2516*3fe401a5SEd Maste 2517*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2518*3fe401a5SEd Maste maxl = 0; 2519*3fe401a5SEd Maste if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 2520*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 2521*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 2522*3fe401a5SEd Maste for (j = bucket[i]; 2523*3fe401a5SEd Maste j > 0 && (uint32_t)j - symndx < nchain; 2524*3fe401a5SEd Maste j++) { 2525*3fe401a5SEd Maste if (++bl[i] > maxl) 2526*3fe401a5SEd Maste maxl = bl[i]; 2527*3fe401a5SEd Maste if (chain[j - symndx] & 1) 2528*3fe401a5SEd Maste break; 2529*3fe401a5SEd Maste } 2530*3fe401a5SEd Maste if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 2531*3fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 2532*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 2533*3fe401a5SEd Maste c[bl[i]]++; 2534*3fe401a5SEd Maste PRT(" bucket symndx name\n"); 2535*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) { 2536*3fe401a5SEd Maste first = 1; 2537*3fe401a5SEd Maste for (j = bucket[i]; 2538*3fe401a5SEd Maste j > 0 && (uint32_t)j - symndx < nchain; 2539*3fe401a5SEd Maste j++) { 2540*3fe401a5SEd Maste if (first) { 2541*3fe401a5SEd Maste PRT("%10d ", i); 2542*3fe401a5SEd Maste first = 0; 2543*3fe401a5SEd Maste } else 2544*3fe401a5SEd Maste PRT(" "); 2545*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j ); 2546*3fe401a5SEd Maste PRT("%-10s ", idx); 2547*3fe401a5SEd Maste PRT("%s\n", get_symbol_name(ed, s->link, j)); 2548*3fe401a5SEd Maste if (chain[j - symndx] & 1) 2549*3fe401a5SEd Maste break; 2550*3fe401a5SEd Maste } 2551*3fe401a5SEd Maste } 2552*3fe401a5SEd Maste PRT("\n"); 2553*3fe401a5SEd Maste total = 0; 2554*3fe401a5SEd Maste for (i = 0; (uint32_t)i <= maxl; i++) { 2555*3fe401a5SEd Maste total += c[i] * i; 2556*3fe401a5SEd Maste PRT("%10u buckets contain %8d symbols\n", c[i], i); 2557*3fe401a5SEd Maste } 2558*3fe401a5SEd Maste PRT("%10u buckets %8u symbols (globals)\n", nbucket, 2559*3fe401a5SEd Maste total); 2560*3fe401a5SEd Maste } else { 2561*3fe401a5SEd Maste PRT("\nnbucket: %u\n", nbucket); 2562*3fe401a5SEd Maste PRT("symndx: %u\n", symndx); 2563*3fe401a5SEd Maste PRT("maskwords: %u\n", maskwords); 2564*3fe401a5SEd Maste PRT("shift2: %u\n", shift2); 2565*3fe401a5SEd Maste PRT("nchain: %u\n\n", nchain); 2566*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 2567*3fe401a5SEd Maste PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 2568*3fe401a5SEd Maste for (i = 0; (uint32_t)i < nchain; i++) 2569*3fe401a5SEd Maste PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 2570*3fe401a5SEd Maste } 2571*3fe401a5SEd Maste } 2572*3fe401a5SEd Maste 2573*3fe401a5SEd Maste /* 2574*3fe401a5SEd Maste * Dump hash tables. 2575*3fe401a5SEd Maste */ 2576*3fe401a5SEd Maste static void 2577*3fe401a5SEd Maste elf_print_hash(struct elfdump *ed) 2578*3fe401a5SEd Maste { 2579*3fe401a5SEd Maste struct section *s; 2580*3fe401a5SEd Maste int i; 2581*3fe401a5SEd Maste 2582*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 2583*3fe401a5SEd Maste s = &ed->sl[i]; 2584*3fe401a5SEd Maste if ((s->type == SHT_HASH || s->type == SHT_GNU_HASH) && 2585*3fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 2586*3fe401a5SEd Maste if (s->type == SHT_GNU_HASH) 2587*3fe401a5SEd Maste elf_print_gnu_hash(ed, s); 2588*3fe401a5SEd Maste else if (ed->ehdr.e_machine == EM_ALPHA && 2589*3fe401a5SEd Maste s->entsize == 8) 2590*3fe401a5SEd Maste elf_print_svr4_hash64(ed, s); 2591*3fe401a5SEd Maste else 2592*3fe401a5SEd Maste elf_print_svr4_hash(ed, s); 2593*3fe401a5SEd Maste } 2594*3fe401a5SEd Maste } 2595*3fe401a5SEd Maste } 2596*3fe401a5SEd Maste 2597*3fe401a5SEd Maste /* 2598*3fe401a5SEd Maste * Dump the content of a Version Definition(SHT_SUNW_Verdef) Section. 2599*3fe401a5SEd Maste */ 2600*3fe401a5SEd Maste static void 2601*3fe401a5SEd Maste elf_print_verdef(struct elfdump *ed, struct section *s) 2602*3fe401a5SEd Maste { 2603*3fe401a5SEd Maste Elf_Data *data; 2604*3fe401a5SEd Maste Elf32_Verdef *vd; 2605*3fe401a5SEd Maste Elf32_Verdaux *vda; 2606*3fe401a5SEd Maste const char *str; 2607*3fe401a5SEd Maste char idx[10]; 2608*3fe401a5SEd Maste uint8_t *buf, *end, *buf2; 2609*3fe401a5SEd Maste int i, j, elferr, count; 2610*3fe401a5SEd Maste 2611*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2612*3fe401a5SEd Maste PRT("Version Definition Section: %s\n", s->name); 2613*3fe401a5SEd Maste else 2614*3fe401a5SEd Maste PRT("\nversion definition section (%s):\n", s->name); 2615*3fe401a5SEd Maste (void) elf_errno(); 2616*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2617*3fe401a5SEd Maste elferr = elf_errno(); 2618*3fe401a5SEd Maste if (elferr != 0) 2619*3fe401a5SEd Maste warnx("elf_getdata failed: %s", 2620*3fe401a5SEd Maste elf_errmsg(elferr)); 2621*3fe401a5SEd Maste return; 2622*3fe401a5SEd Maste } 2623*3fe401a5SEd Maste buf = data->d_buf; 2624*3fe401a5SEd Maste end = buf + data->d_size; 2625*3fe401a5SEd Maste i = 0; 2626*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2627*3fe401a5SEd Maste PRT(" index version dependency\n"); 2628*3fe401a5SEd Maste while (buf + sizeof(Elf32_Verdef) <= end) { 2629*3fe401a5SEd Maste vd = (Elf32_Verdef *) (uintptr_t) buf; 2630*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2631*3fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", vd->vd_ndx); 2632*3fe401a5SEd Maste PRT("%10s ", idx); 2633*3fe401a5SEd Maste } else { 2634*3fe401a5SEd Maste PRT("\nentry: %d\n", i++); 2635*3fe401a5SEd Maste PRT("\tvd_version: %u\n", vd->vd_version); 2636*3fe401a5SEd Maste PRT("\tvd_flags: %u\n", vd->vd_flags); 2637*3fe401a5SEd Maste PRT("\tvd_ndx: %u\n", vd->vd_ndx); 2638*3fe401a5SEd Maste PRT("\tvd_cnt: %u\n", vd->vd_cnt); 2639*3fe401a5SEd Maste PRT("\tvd_hash: %u\n", vd->vd_hash); 2640*3fe401a5SEd Maste PRT("\tvd_aux: %u\n", vd->vd_aux); 2641*3fe401a5SEd Maste PRT("\tvd_next: %u\n\n", vd->vd_next); 2642*3fe401a5SEd Maste } 2643*3fe401a5SEd Maste buf2 = buf + vd->vd_aux; 2644*3fe401a5SEd Maste j = 0; 2645*3fe401a5SEd Maste count = 0; 2646*3fe401a5SEd Maste while (buf2 + sizeof(Elf32_Verdaux) <= end && j < vd->vd_cnt) { 2647*3fe401a5SEd Maste vda = (Elf32_Verdaux *) (uintptr_t) buf2; 2648*3fe401a5SEd Maste str = get_string(ed, s->link, vda->vda_name); 2649*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2650*3fe401a5SEd Maste if (count == 0) 2651*3fe401a5SEd Maste PRT("%-26.26s", str); 2652*3fe401a5SEd Maste else if (count == 1) 2653*3fe401a5SEd Maste PRT(" %-20.20s", str); 2654*3fe401a5SEd Maste else { 2655*3fe401a5SEd Maste PRT("\n%40.40s", ""); 2656*3fe401a5SEd Maste PRT("%s", str); 2657*3fe401a5SEd Maste } 2658*3fe401a5SEd Maste } else { 2659*3fe401a5SEd Maste PRT("\t\tvda: %d\n", j++); 2660*3fe401a5SEd Maste PRT("\t\t\tvda_name: %s\n", str); 2661*3fe401a5SEd Maste PRT("\t\t\tvda_next: %u\n", vda->vda_next); 2662*3fe401a5SEd Maste } 2663*3fe401a5SEd Maste if (vda->vda_next == 0) { 2664*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2665*3fe401a5SEd Maste if (vd->vd_flags & VER_FLG_BASE) { 2666*3fe401a5SEd Maste if (count == 0) 2667*3fe401a5SEd Maste PRT("%-20.20s", ""); 2668*3fe401a5SEd Maste PRT("%s", "[ BASE ]"); 2669*3fe401a5SEd Maste } 2670*3fe401a5SEd Maste PRT("\n"); 2671*3fe401a5SEd Maste } 2672*3fe401a5SEd Maste break; 2673*3fe401a5SEd Maste } 2674*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2675*3fe401a5SEd Maste count++; 2676*3fe401a5SEd Maste buf2 += vda->vda_next; 2677*3fe401a5SEd Maste } 2678*3fe401a5SEd Maste if (vd->vd_next == 0) 2679*3fe401a5SEd Maste break; 2680*3fe401a5SEd Maste buf += vd->vd_next; 2681*3fe401a5SEd Maste } 2682*3fe401a5SEd Maste } 2683*3fe401a5SEd Maste 2684*3fe401a5SEd Maste /* 2685*3fe401a5SEd Maste * Dump the content of a Version Needed(SHT_SUNW_Verneed) Section. 2686*3fe401a5SEd Maste */ 2687*3fe401a5SEd Maste static void 2688*3fe401a5SEd Maste elf_print_verneed(struct elfdump *ed, struct section *s) 2689*3fe401a5SEd Maste { 2690*3fe401a5SEd Maste Elf_Data *data; 2691*3fe401a5SEd Maste Elf32_Verneed *vn; 2692*3fe401a5SEd Maste Elf32_Vernaux *vna; 2693*3fe401a5SEd Maste uint8_t *buf, *end, *buf2; 2694*3fe401a5SEd Maste int i, j, elferr, first; 2695*3fe401a5SEd Maste 2696*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2697*3fe401a5SEd Maste PRT("\nVersion Needed Section: %s\n", s->name); 2698*3fe401a5SEd Maste else 2699*3fe401a5SEd Maste PRT("\nversion need section (%s):\n", s->name); 2700*3fe401a5SEd Maste (void) elf_errno(); 2701*3fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2702*3fe401a5SEd Maste elferr = elf_errno(); 2703*3fe401a5SEd Maste if (elferr != 0) 2704*3fe401a5SEd Maste warnx("elf_getdata failed: %s", 2705*3fe401a5SEd Maste elf_errmsg(elferr)); 2706*3fe401a5SEd Maste return; 2707*3fe401a5SEd Maste } 2708*3fe401a5SEd Maste buf = data->d_buf; 2709*3fe401a5SEd Maste end = buf + data->d_size; 2710*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2711*3fe401a5SEd Maste PRT(" file version\n"); 2712*3fe401a5SEd Maste i = 0; 2713*3fe401a5SEd Maste while (buf + sizeof(Elf32_Verneed) <= end) { 2714*3fe401a5SEd Maste vn = (Elf32_Verneed *) (uintptr_t) buf; 2715*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2716*3fe401a5SEd Maste PRT(" %-26.26s ", 2717*3fe401a5SEd Maste get_string(ed, s->link, vn->vn_file)); 2718*3fe401a5SEd Maste else { 2719*3fe401a5SEd Maste PRT("\nentry: %d\n", i++); 2720*3fe401a5SEd Maste PRT("\tvn_version: %u\n", vn->vn_version); 2721*3fe401a5SEd Maste PRT("\tvn_cnt: %u\n", vn->vn_cnt); 2722*3fe401a5SEd Maste PRT("\tvn_file: %s\n", 2723*3fe401a5SEd Maste get_string(ed, s->link, vn->vn_file)); 2724*3fe401a5SEd Maste PRT("\tvn_aux: %u\n", vn->vn_aux); 2725*3fe401a5SEd Maste PRT("\tvn_next: %u\n\n", vn->vn_next); 2726*3fe401a5SEd Maste } 2727*3fe401a5SEd Maste buf2 = buf + vn->vn_aux; 2728*3fe401a5SEd Maste j = 0; 2729*3fe401a5SEd Maste first = 1; 2730*3fe401a5SEd Maste while (buf2 + sizeof(Elf32_Vernaux) <= end && j < vn->vn_cnt) { 2731*3fe401a5SEd Maste vna = (Elf32_Vernaux *) (uintptr_t) buf2; 2732*3fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 2733*3fe401a5SEd Maste if (!first) 2734*3fe401a5SEd Maste PRT("%40.40s", ""); 2735*3fe401a5SEd Maste else 2736*3fe401a5SEd Maste first = 0; 2737*3fe401a5SEd Maste PRT("%s\n", get_string(ed, s->link, 2738*3fe401a5SEd Maste vna->vna_name)); 2739*3fe401a5SEd Maste } else { 2740*3fe401a5SEd Maste PRT("\t\tvna: %d\n", j++); 2741*3fe401a5SEd Maste PRT("\t\t\tvna_hash: %u\n", vna->vna_hash); 2742*3fe401a5SEd Maste PRT("\t\t\tvna_flags: %u\n", vna->vna_flags); 2743*3fe401a5SEd Maste PRT("\t\t\tvna_other: %u\n", vna->vna_other); 2744*3fe401a5SEd Maste PRT("\t\t\tvna_name: %s\n", 2745*3fe401a5SEd Maste get_string(ed, s->link, vna->vna_name)); 2746*3fe401a5SEd Maste PRT("\t\t\tvna_next: %u\n", vna->vna_next); 2747*3fe401a5SEd Maste } 2748*3fe401a5SEd Maste if (vna->vna_next == 0) 2749*3fe401a5SEd Maste break; 2750*3fe401a5SEd Maste buf2 += vna->vna_next; 2751*3fe401a5SEd Maste } 2752*3fe401a5SEd Maste if (vn->vn_next == 0) 2753*3fe401a5SEd Maste break; 2754*3fe401a5SEd Maste buf += vn->vn_next; 2755*3fe401a5SEd Maste } 2756*3fe401a5SEd Maste } 2757*3fe401a5SEd Maste 2758*3fe401a5SEd Maste /* 2759*3fe401a5SEd Maste * Dump the symbol-versioning sections. 2760*3fe401a5SEd Maste */ 2761*3fe401a5SEd Maste static void 2762*3fe401a5SEd Maste elf_print_symver(struct elfdump *ed) 2763*3fe401a5SEd Maste { 2764*3fe401a5SEd Maste struct section *s; 2765*3fe401a5SEd Maste int i; 2766*3fe401a5SEd Maste 2767*3fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 2768*3fe401a5SEd Maste s = &ed->sl[i]; 2769*3fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl) && !find_name(ed, s->name)) 2770*3fe401a5SEd Maste continue; 2771*3fe401a5SEd Maste if (s->type == SHT_SUNW_verdef) 2772*3fe401a5SEd Maste elf_print_verdef(ed, s); 2773*3fe401a5SEd Maste if (s->type == SHT_SUNW_verneed) 2774*3fe401a5SEd Maste elf_print_verneed(ed, s); 2775*3fe401a5SEd Maste } 2776*3fe401a5SEd Maste } 2777*3fe401a5SEd Maste 2778*3fe401a5SEd Maste /* 2779*3fe401a5SEd Maste * Dump the ELF checksum. See gelf_checksum(3) for details. 2780*3fe401a5SEd Maste */ 2781*3fe401a5SEd Maste static void 2782*3fe401a5SEd Maste elf_print_checksum(struct elfdump *ed) 2783*3fe401a5SEd Maste { 2784*3fe401a5SEd Maste 2785*3fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 2786*3fe401a5SEd Maste return; 2787*3fe401a5SEd Maste 2788*3fe401a5SEd Maste PRT("\nelf checksum: %#lx\n", gelf_checksum(ed->elf)); 2789*3fe401a5SEd Maste } 2790*3fe401a5SEd Maste 2791*3fe401a5SEd Maste #define USAGE_MESSAGE "\ 2792*3fe401a5SEd Maste Usage: %s [options] file...\n\ 2793*3fe401a5SEd Maste Display information about ELF objects and ar(1) archives.\n\n\ 2794*3fe401a5SEd Maste Options:\n\ 2795*3fe401a5SEd Maste -a Show all information.\n\ 2796*3fe401a5SEd Maste -c Show shared headers.\n\ 2797*3fe401a5SEd Maste -d Show dynamic symbols.\n\ 2798*3fe401a5SEd Maste -e Show the ELF header.\n\ 2799*3fe401a5SEd Maste -G Show the GOT.\n\ 2800*3fe401a5SEd Maste -H | --help Show a usage message and exit.\n\ 2801*3fe401a5SEd Maste -h Show hash values.\n\ 2802*3fe401a5SEd Maste -i Show the dynamic interpreter.\n\ 2803*3fe401a5SEd Maste -k Show the ELF checksum.\n\ 2804*3fe401a5SEd Maste -n Show the contents of note sections.\n\ 2805*3fe401a5SEd Maste -N NAME Show the section named \"NAME\".\n\ 2806*3fe401a5SEd Maste -p Show the program header.\n\ 2807*3fe401a5SEd Maste -r Show relocations.\n\ 2808*3fe401a5SEd Maste -s Show the symbol table.\n\ 2809*3fe401a5SEd Maste -S Use the Solaris elfdump format.\n\ 2810*3fe401a5SEd Maste -v Show symbol-versioning information.\n\ 2811*3fe401a5SEd Maste -V | --version Print a version identifier and exit.\n\ 2812*3fe401a5SEd Maste -w FILE Write output to \"FILE\".\n" 2813*3fe401a5SEd Maste 2814*3fe401a5SEd Maste static void 2815*3fe401a5SEd Maste usage(void) 2816*3fe401a5SEd Maste { 2817*3fe401a5SEd Maste fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 2818*3fe401a5SEd Maste exit(EXIT_FAILURE); 2819*3fe401a5SEd Maste } 2820