13fe401a5SEd Maste /*- 23fe401a5SEd Maste * Copyright (c) 2007-2012 Kai Wang 33fe401a5SEd Maste * Copyright (c) 2003 David O'Brien. All rights reserved. 43fe401a5SEd Maste * Copyright (c) 2001 Jake Burkholder 53fe401a5SEd Maste * All rights reserved. 63fe401a5SEd Maste * 73fe401a5SEd Maste * Redistribution and use in source and binary forms, with or without 83fe401a5SEd Maste * modification, are permitted provided that the following conditions 93fe401a5SEd Maste * are met: 103fe401a5SEd Maste * 1. Redistributions of source code must retain the above copyright 113fe401a5SEd Maste * notice, this list of conditions and the following disclaimer. 123fe401a5SEd Maste * 2. Redistributions in binary form must reproduce the above copyright 133fe401a5SEd Maste * notice, this list of conditions and the following disclaimer in the 143fe401a5SEd Maste * documentation and/or other materials provided with the distribution. 153fe401a5SEd Maste * 163fe401a5SEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 173fe401a5SEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 183fe401a5SEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 193fe401a5SEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 203fe401a5SEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 213fe401a5SEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 223fe401a5SEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 233fe401a5SEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 243fe401a5SEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 253fe401a5SEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263fe401a5SEd Maste * SUCH DAMAGE. 273fe401a5SEd Maste */ 283fe401a5SEd Maste 293fe401a5SEd Maste #include <sys/param.h> 303fe401a5SEd Maste #include <sys/queue.h> 313fe401a5SEd Maste #include <sys/stat.h> 323fe401a5SEd Maste 333fe401a5SEd Maste #include <ar.h> 343fe401a5SEd Maste #include <assert.h> 353fe401a5SEd Maste #include <err.h> 363fe401a5SEd Maste #include <fcntl.h> 373fe401a5SEd Maste #include <gelf.h> 383fe401a5SEd Maste #include <getopt.h> 393fe401a5SEd Maste #include <libelftc.h> 403fe401a5SEd Maste #include <inttypes.h> 413fe401a5SEd Maste #include <stdio.h> 423fe401a5SEd Maste #include <stdlib.h> 433fe401a5SEd Maste #include <string.h> 443fe401a5SEd Maste #include <unistd.h> 453fe401a5SEd Maste 463fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 473fe401a5SEd Maste #include <archive.h> 483fe401a5SEd Maste #include <archive_entry.h> 493fe401a5SEd Maste #endif 503fe401a5SEd Maste 513fe401a5SEd Maste #include "_elftc.h" 523fe401a5SEd Maste 53*656f49f8SEd Maste ELFTC_VCSID("$Id: elfdump.c 3250 2015-10-06 13:56:15Z emaste $"); 543fe401a5SEd Maste 553fe401a5SEd Maste #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION) 563fe401a5SEd Maste #include "native-elf-format.h" 573fe401a5SEd Maste #if ELFTC_CLASS == ELFCLASS32 583fe401a5SEd Maste typedef Elf32_Nhdr Elf_Note; 593fe401a5SEd Maste #else 603fe401a5SEd Maste typedef Elf64_Nhdr Elf_Note; 613fe401a5SEd Maste #endif 623fe401a5SEd Maste #endif 633fe401a5SEd Maste 643fe401a5SEd Maste /* elfdump(1) options. */ 653fe401a5SEd Maste #define ED_DYN (1<<0) 663fe401a5SEd Maste #define ED_EHDR (1<<1) 673fe401a5SEd Maste #define ED_GOT (1<<2) 683fe401a5SEd Maste #define ED_HASH (1<<3) 693fe401a5SEd Maste #define ED_INTERP (1<<4) 703fe401a5SEd Maste #define ED_NOTE (1<<5) 713fe401a5SEd Maste #define ED_PHDR (1<<6) 723fe401a5SEd Maste #define ED_REL (1<<7) 733fe401a5SEd Maste #define ED_SHDR (1<<8) 743fe401a5SEd Maste #define ED_SYMTAB (1<<9) 753fe401a5SEd Maste #define ED_SYMVER (1<<10) 763fe401a5SEd Maste #define ED_CHECKSUM (1<<11) 773fe401a5SEd Maste #define ED_ALL ((1<<12)-1) 783fe401a5SEd Maste 793fe401a5SEd Maste /* elfdump(1) run control flags. */ 803fe401a5SEd Maste #define SOLARIS_FMT (1<<0) 813fe401a5SEd Maste #define PRINT_FILENAME (1<<1) 823fe401a5SEd Maste #define PRINT_ARSYM (1<<2) 833fe401a5SEd Maste #define ONLY_ARSYM (1<<3) 843fe401a5SEd Maste 853fe401a5SEd Maste /* Convenient print macro. */ 863fe401a5SEd Maste #define PRT(...) fprintf(ed->out, __VA_ARGS__) 873fe401a5SEd Maste 883fe401a5SEd Maste /* Internal data structure for sections. */ 893fe401a5SEd Maste struct section { 903fe401a5SEd Maste const char *name; /* section name */ 913fe401a5SEd Maste Elf_Scn *scn; /* section scn */ 923fe401a5SEd Maste uint64_t off; /* section offset */ 933fe401a5SEd Maste uint64_t sz; /* section size */ 943fe401a5SEd Maste uint64_t entsize; /* section entsize */ 953fe401a5SEd Maste uint64_t align; /* section alignment */ 963fe401a5SEd Maste uint64_t type; /* section type */ 973fe401a5SEd Maste uint64_t flags; /* section flags */ 983fe401a5SEd Maste uint64_t addr; /* section virtual addr */ 993fe401a5SEd Maste uint32_t link; /* section link ndx */ 1003fe401a5SEd Maste uint32_t info; /* section info ndx */ 1013fe401a5SEd Maste }; 1023fe401a5SEd Maste 1033fe401a5SEd Maste struct spec_name { 1043fe401a5SEd Maste const char *name; 1053fe401a5SEd Maste STAILQ_ENTRY(spec_name) sn_list; 1063fe401a5SEd Maste }; 1073fe401a5SEd Maste 1083fe401a5SEd Maste /* Structure encapsulates the global data for readelf(1). */ 1093fe401a5SEd Maste struct elfdump { 1103fe401a5SEd Maste FILE *out; /* output redirection. */ 1113fe401a5SEd Maste const char *filename; /* current processing file. */ 1123fe401a5SEd Maste const char *archive; /* archive name */ 1133fe401a5SEd Maste int options; /* command line options. */ 1143fe401a5SEd Maste int flags; /* run control flags. */ 1153fe401a5SEd Maste Elf *elf; /* underlying ELF descriptor. */ 1163fe401a5SEd Maste #ifndef USE_LIBARCHIVE_AR 1173fe401a5SEd Maste Elf *ar; /* ar(1) archive descriptor. */ 1183fe401a5SEd Maste #endif 1193fe401a5SEd Maste GElf_Ehdr ehdr; /* ELF header. */ 1203fe401a5SEd Maste int ec; /* ELF class. */ 1213fe401a5SEd Maste size_t shnum; /* #sections. */ 1223fe401a5SEd Maste struct section *sl; /* list of sections. */ 1233fe401a5SEd Maste STAILQ_HEAD(, spec_name) snl; /* list of names specified by -N. */ 1243fe401a5SEd Maste }; 1253fe401a5SEd Maste 1263fe401a5SEd Maste /* Relocation entry. */ 1273fe401a5SEd Maste struct rel_entry { 1283fe401a5SEd Maste union { 1293fe401a5SEd Maste GElf_Rel rel; 1303fe401a5SEd Maste GElf_Rela rela; 1313fe401a5SEd Maste } u_r; 1323fe401a5SEd Maste const char *symn; 1333fe401a5SEd Maste uint32_t type; 1343fe401a5SEd Maste }; 1353fe401a5SEd Maste 1363fe401a5SEd Maste #if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS) 1373fe401a5SEd Maste static __inline uint32_t 1383fe401a5SEd Maste be32dec(const void *pp) 1393fe401a5SEd Maste { 1403fe401a5SEd Maste unsigned char const *p = (unsigned char const *)pp; 1413fe401a5SEd Maste 1423fe401a5SEd Maste return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); 1433fe401a5SEd Maste } 1443fe401a5SEd Maste 1453fe401a5SEd Maste static __inline uint32_t 1463fe401a5SEd Maste le32dec(const void *pp) 1473fe401a5SEd Maste { 1483fe401a5SEd Maste unsigned char const *p = (unsigned char const *)pp; 1493fe401a5SEd Maste 1503fe401a5SEd Maste return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); 1513fe401a5SEd Maste } 1523fe401a5SEd Maste #endif 1533fe401a5SEd Maste 1543fe401a5SEd Maste /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 1553fe401a5SEd Maste static const char * 1563fe401a5SEd Maste d_tags(uint64_t tag) 1573fe401a5SEd Maste { 1583fe401a5SEd Maste switch (tag) { 1593fe401a5SEd Maste case 0: return "DT_NULL"; 1603fe401a5SEd Maste case 1: return "DT_NEEDED"; 1613fe401a5SEd Maste case 2: return "DT_PLTRELSZ"; 1623fe401a5SEd Maste case 3: return "DT_PLTGOT"; 1633fe401a5SEd Maste case 4: return "DT_HASH"; 1643fe401a5SEd Maste case 5: return "DT_STRTAB"; 1653fe401a5SEd Maste case 6: return "DT_SYMTAB"; 1663fe401a5SEd Maste case 7: return "DT_RELA"; 1673fe401a5SEd Maste case 8: return "DT_RELASZ"; 1683fe401a5SEd Maste case 9: return "DT_RELAENT"; 1693fe401a5SEd Maste case 10: return "DT_STRSZ"; 1703fe401a5SEd Maste case 11: return "DT_SYMENT"; 1713fe401a5SEd Maste case 12: return "DT_INIT"; 1723fe401a5SEd Maste case 13: return "DT_FINI"; 1733fe401a5SEd Maste case 14: return "DT_SONAME"; 1743fe401a5SEd Maste case 15: return "DT_RPATH"; 1753fe401a5SEd Maste case 16: return "DT_SYMBOLIC"; 1763fe401a5SEd Maste case 17: return "DT_REL"; 1773fe401a5SEd Maste case 18: return "DT_RELSZ"; 1783fe401a5SEd Maste case 19: return "DT_RELENT"; 1793fe401a5SEd Maste case 20: return "DT_PLTREL"; 1803fe401a5SEd Maste case 21: return "DT_DEBUG"; 1813fe401a5SEd Maste case 22: return "DT_TEXTREL"; 1823fe401a5SEd Maste case 23: return "DT_JMPREL"; 1833fe401a5SEd Maste case 24: return "DT_BIND_NOW"; 1843fe401a5SEd Maste case 25: return "DT_INIT_ARRAY"; 1853fe401a5SEd Maste case 26: return "DT_FINI_ARRAY"; 1863fe401a5SEd Maste case 27: return "DT_INIT_ARRAYSZ"; 1873fe401a5SEd Maste case 28: return "DT_FINI_ARRAYSZ"; 1883fe401a5SEd Maste case 29: return "DT_RUNPATH"; 1893fe401a5SEd Maste case 30: return "DT_FLAGS"; 1903fe401a5SEd Maste case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ 1913fe401a5SEd Maste case 33: return "DT_PREINIT_ARRAYSZ"; 1923fe401a5SEd Maste /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 1933fe401a5SEd Maste case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 1943fe401a5SEd Maste case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 1953fe401a5SEd Maste case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 1963fe401a5SEd Maste case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 1973fe401a5SEd Maste case 0x6ffffdf9: return "DT_PLTPADSZ"; 1983fe401a5SEd Maste case 0x6ffffdfa: return "DT_MOVEENT"; 1993fe401a5SEd Maste case 0x6ffffdfb: return "DT_MOVESZ"; 2003fe401a5SEd Maste case 0x6ffffdfc: return "DT_FEATURE"; 2013fe401a5SEd Maste case 0x6ffffdfd: return "DT_POSFLAG_1"; 2023fe401a5SEd Maste case 0x6ffffdfe: return "DT_SYMINSZ"; 2033fe401a5SEd Maste case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; 2043fe401a5SEd Maste case 0x6ffffe00: return "DT_ADDRRNGLO"; 2053fe401a5SEd Maste case 0x6ffffef5: return "DT_GNU_HASH"; 2063fe401a5SEd Maste case 0x6ffffef8: return "DT_GNU_CONFLICT"; 2073fe401a5SEd Maste case 0x6ffffef9: return "DT_GNU_LIBLIST"; 208*656f49f8SEd Maste case 0x6ffffefa: return "DT_CONFIG"; 209*656f49f8SEd Maste case 0x6ffffefb: return "DT_DEPAUDIT"; 210*656f49f8SEd Maste case 0x6ffffefc: return "DT_AUDIT"; 211*656f49f8SEd Maste case 0x6ffffefd: return "DT_PLTPAD"; 212*656f49f8SEd Maste case 0x6ffffefe: return "DT_MOVETAB"; 2133fe401a5SEd Maste case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; 2143fe401a5SEd Maste case 0x6ffffff9: return "DT_RELACOUNT"; 2153fe401a5SEd Maste case 0x6ffffffa: return "DT_RELCOUNT"; 2163fe401a5SEd Maste case 0x6ffffffb: return "DT_FLAGS_1"; 2173fe401a5SEd Maste case 0x6ffffffc: return "DT_VERDEF"; 2183fe401a5SEd Maste case 0x6ffffffd: return "DT_VERDEFNUM"; 2193fe401a5SEd Maste case 0x6ffffffe: return "DT_VERNEED"; 2203fe401a5SEd Maste case 0x6fffffff: return "DT_VERNEEDNUM"; 2213fe401a5SEd Maste case 0x6ffffff0: return "DT_GNU_VERSYM"; 2223fe401a5SEd Maste /* 0x70000000 - 0x7fffffff processor-specific semantics */ 2233fe401a5SEd Maste case 0x70000000: return "DT_IA_64_PLT_RESERVE"; 2243fe401a5SEd Maste case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; 2253fe401a5SEd Maste case 0x7ffffffe: return "DT_SUNW_USED"; 2263fe401a5SEd Maste case 0x7fffffff: return "DT_SUNW_FILTER"; 2273fe401a5SEd Maste default: return "ERROR: TAG NOT DEFINED"; 2283fe401a5SEd Maste } 2293fe401a5SEd Maste } 2303fe401a5SEd Maste 2313fe401a5SEd Maste static const char * 2323fe401a5SEd Maste e_machines(unsigned int mach) 2333fe401a5SEd Maste { 2343fe401a5SEd Maste static char machdesc[64]; 2353fe401a5SEd Maste 2363fe401a5SEd Maste switch (mach) { 2373fe401a5SEd Maste case EM_NONE: return "EM_NONE"; 2383fe401a5SEd Maste case EM_M32: return "EM_M32"; 2393fe401a5SEd Maste case EM_SPARC: return "EM_SPARC"; 2403fe401a5SEd Maste case EM_386: return "EM_386"; 2413fe401a5SEd Maste case EM_68K: return "EM_68K"; 2423fe401a5SEd Maste case EM_88K: return "EM_88K"; 2433fe401a5SEd Maste case EM_IAMCU: return "EM_IAMCU"; 2443fe401a5SEd Maste case EM_860: return "EM_860"; 2453fe401a5SEd Maste case EM_MIPS: return "EM_MIPS"; 2463fe401a5SEd Maste case EM_PPC: return "EM_PPC"; 247*656f49f8SEd Maste case EM_PPC64: return "EM_PPC64"; 2483fe401a5SEd Maste case EM_ARM: return "EM_ARM"; 2493fe401a5SEd Maste case EM_ALPHA: return "EM_ALPHA (legacy)"; 2503fe401a5SEd Maste case EM_SPARCV9:return "EM_SPARCV9"; 2513fe401a5SEd Maste case EM_IA_64: return "EM_IA_64"; 2523fe401a5SEd Maste case EM_X86_64: return "EM_X86_64"; 253*656f49f8SEd Maste case EM_AARCH64:return "EM_AARCH64"; 254*656f49f8SEd Maste case EM_RISCV: return "EM_RISCV"; 2553fe401a5SEd Maste } 2563fe401a5SEd Maste snprintf(machdesc, sizeof(machdesc), 2573fe401a5SEd Maste "(unknown machine) -- type 0x%x", mach); 2583fe401a5SEd Maste return (machdesc); 2593fe401a5SEd Maste } 2603fe401a5SEd Maste 2613fe401a5SEd Maste static const char *e_types[] = { 2623fe401a5SEd Maste "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 2633fe401a5SEd Maste }; 2643fe401a5SEd Maste 2653fe401a5SEd Maste static const char *ei_versions[] = { 2663fe401a5SEd Maste "EV_NONE", "EV_CURRENT" 2673fe401a5SEd Maste }; 2683fe401a5SEd Maste 2693fe401a5SEd Maste static const char *ei_classes[] = { 2703fe401a5SEd Maste "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 2713fe401a5SEd Maste }; 2723fe401a5SEd Maste 2733fe401a5SEd Maste static const char *ei_data[] = { 2743fe401a5SEd Maste "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 2753fe401a5SEd Maste }; 2763fe401a5SEd Maste 277*656f49f8SEd Maste static const char *ei_abis[256] = { 278453b09caSEd Maste "ELFOSABI_NONE", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 279*656f49f8SEd Maste "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX", 280*656f49f8SEd Maste "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64", 281*656f49f8SEd Maste "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD", 282*656f49f8SEd Maste [255] = "ELFOSABI_STANDALONE" 2833fe401a5SEd Maste }; 2843fe401a5SEd Maste 2853fe401a5SEd Maste static const char *p_types[] = { 2863fe401a5SEd Maste "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 2873fe401a5SEd Maste "PT_SHLIB", "PT_PHDR", "PT_TLS" 2883fe401a5SEd Maste }; 2893fe401a5SEd Maste 2903fe401a5SEd Maste static const char *p_flags[] = { 2913fe401a5SEd Maste "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 2923fe401a5SEd Maste "PF_X|PF_W|PF_R" 2933fe401a5SEd Maste }; 2943fe401a5SEd Maste 2953fe401a5SEd Maste static const char * 2963fe401a5SEd Maste sh_name(struct elfdump *ed, int ndx) 2973fe401a5SEd Maste { 2983fe401a5SEd Maste static char num[10]; 2993fe401a5SEd Maste 3003fe401a5SEd Maste switch (ndx) { 3013fe401a5SEd Maste case SHN_UNDEF: return "UNDEF"; 3023fe401a5SEd Maste case SHN_ABS: return "ABS"; 3033fe401a5SEd Maste case SHN_COMMON: return "COMMON"; 3043fe401a5SEd Maste default: 3053fe401a5SEd Maste if ((uint64_t)ndx < ed->shnum) 3063fe401a5SEd Maste return (ed->sl[ndx].name); 3073fe401a5SEd Maste else { 3083fe401a5SEd Maste snprintf(num, sizeof(num), "%d", ndx); 3093fe401a5SEd Maste return (num); 3103fe401a5SEd Maste } 3113fe401a5SEd Maste } 3123fe401a5SEd Maste } 3133fe401a5SEd Maste 3143fe401a5SEd Maste /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 3153fe401a5SEd Maste static const char * 3163fe401a5SEd Maste sh_types(u_int64_t sht) { 3173fe401a5SEd Maste switch (sht) { 3183fe401a5SEd Maste case 0: return "SHT_NULL"; 3193fe401a5SEd Maste case 1: return "SHT_PROGBITS"; 3203fe401a5SEd Maste case 2: return "SHT_SYMTAB"; 3213fe401a5SEd Maste case 3: return "SHT_STRTAB"; 3223fe401a5SEd Maste case 4: return "SHT_RELA"; 3233fe401a5SEd Maste case 5: return "SHT_HASH"; 3243fe401a5SEd Maste case 6: return "SHT_DYNAMIC"; 3253fe401a5SEd Maste case 7: return "SHT_NOTE"; 3263fe401a5SEd Maste case 8: return "SHT_NOBITS"; 3273fe401a5SEd Maste case 9: return "SHT_REL"; 3283fe401a5SEd Maste case 10: return "SHT_SHLIB"; 3293fe401a5SEd Maste case 11: return "SHT_DYNSYM"; 3303fe401a5SEd Maste case 14: return "SHT_INIT_ARRAY"; 3313fe401a5SEd Maste case 15: return "SHT_FINI_ARRAY"; 3323fe401a5SEd Maste case 16: return "SHT_PREINIT_ARRAY"; 3333fe401a5SEd Maste case 17: return "SHT_GROUP"; 3343fe401a5SEd Maste case 18: return "SHT_SYMTAB_SHNDX"; 3353fe401a5SEd Maste /* 0x60000000 - 0x6fffffff operating system-specific semantics */ 3363fe401a5SEd Maste case 0x6ffffff0: return "XXX:VERSYM"; 337*656f49f8SEd Maste case 0x6ffffff4: return "SHT_SUNW_dof"; 3383fe401a5SEd Maste case 0x6ffffff6: return "SHT_GNU_HASH"; 3393fe401a5SEd Maste case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 3403fe401a5SEd Maste case 0x6ffffffc: return "XXX:VERDEF"; 3413fe401a5SEd Maste case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; 3423fe401a5SEd Maste case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; 3433fe401a5SEd Maste case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; 3443fe401a5SEd Maste /* 0x70000000 - 0x7fffffff processor-specific semantics */ 3453fe401a5SEd Maste case 0x70000000: return "SHT_IA_64_EXT"; 3463fe401a5SEd Maste case 0x70000001: return "SHT_IA_64_UNWIND"; 3473fe401a5SEd Maste case 0x7ffffffd: return "XXX:AUXILIARY"; 3483fe401a5SEd Maste case 0x7fffffff: return "XXX:FILTER"; 3493fe401a5SEd Maste /* 0x80000000 - 0xffffffff application programs */ 3503fe401a5SEd Maste default: return "ERROR: SHT NOT DEFINED"; 3513fe401a5SEd Maste } 3523fe401a5SEd Maste } 3533fe401a5SEd Maste 3543fe401a5SEd Maste /* 3553fe401a5SEd Maste * Define known section flags. These flags are defined in the order 3563fe401a5SEd Maste * they are to be printed out. 3573fe401a5SEd Maste */ 3583fe401a5SEd Maste #define DEFINE_SHFLAGS() \ 3593fe401a5SEd Maste DEFINE_SHF(WRITE) \ 3603fe401a5SEd Maste DEFINE_SHF(ALLOC) \ 3613fe401a5SEd Maste DEFINE_SHF(EXECINSTR) \ 3623fe401a5SEd Maste DEFINE_SHF(MERGE) \ 3633fe401a5SEd Maste DEFINE_SHF(STRINGS) \ 3643fe401a5SEd Maste DEFINE_SHF(INFO_LINK) \ 3653fe401a5SEd Maste DEFINE_SHF(LINK_ORDER) \ 3663fe401a5SEd Maste DEFINE_SHF(OS_NONCONFORMING) \ 3673fe401a5SEd Maste DEFINE_SHF(GROUP) \ 3683fe401a5SEd Maste DEFINE_SHF(TLS) 3693fe401a5SEd Maste 3703fe401a5SEd Maste #undef DEFINE_SHF 3713fe401a5SEd Maste #define DEFINE_SHF(F) "SHF_" #F "|" 3723fe401a5SEd Maste #define ALLSHFLAGS DEFINE_SHFLAGS() 3733fe401a5SEd Maste 3743fe401a5SEd Maste static const char * 3753fe401a5SEd Maste sh_flags(uint64_t shf) 3763fe401a5SEd Maste { 3773fe401a5SEd Maste static char flg[sizeof(ALLSHFLAGS)+1]; 3783fe401a5SEd Maste 3793fe401a5SEd Maste flg[0] = '\0'; 3803fe401a5SEd Maste 3813fe401a5SEd Maste #undef DEFINE_SHF 3823fe401a5SEd Maste #define DEFINE_SHF(N) \ 3833fe401a5SEd Maste if (shf & SHF_##N) \ 3843fe401a5SEd Maste strcat(flg, "SHF_" #N "|"); \ 3853fe401a5SEd Maste 3863fe401a5SEd Maste DEFINE_SHFLAGS() 3873fe401a5SEd Maste 3883fe401a5SEd Maste flg[strlen(flg) - 1] = '\0'; /* Remove the trailing "|". */ 3893fe401a5SEd Maste 3903fe401a5SEd Maste return (flg); 3913fe401a5SEd Maste } 3923fe401a5SEd Maste 3933fe401a5SEd Maste static const char *st_types[] = { 3943fe401a5SEd Maste "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE", 3953fe401a5SEd Maste "STT_COMMON", "STT_TLS" 3963fe401a5SEd Maste }; 3973fe401a5SEd Maste 3983fe401a5SEd Maste static const char *st_types_S[] = { 3993fe401a5SEd Maste "NOTY", "OBJT", "FUNC", "SECT", "FILE" 4003fe401a5SEd Maste }; 4013fe401a5SEd Maste 4023fe401a5SEd Maste static const char *st_bindings[] = { 4033fe401a5SEd Maste "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 4043fe401a5SEd Maste }; 4053fe401a5SEd Maste 4063fe401a5SEd Maste static const char *st_bindings_S[] = { 4073fe401a5SEd Maste "LOCL", "GLOB", "WEAK" 4083fe401a5SEd Maste }; 4093fe401a5SEd Maste 4103fe401a5SEd Maste static unsigned char st_others[] = { 4113fe401a5SEd Maste 'D', 'I', 'H', 'P' 4123fe401a5SEd Maste }; 4133fe401a5SEd Maste 4143fe401a5SEd Maste static const char * 4153fe401a5SEd Maste r_type(unsigned int mach, unsigned int type) 4163fe401a5SEd Maste { 4173fe401a5SEd Maste switch(mach) { 4183fe401a5SEd Maste case EM_NONE: return ""; 4193fe401a5SEd Maste case EM_386: 4203fe401a5SEd Maste case EM_IAMCU: 4213fe401a5SEd Maste switch(type) { 4223fe401a5SEd Maste case 0: return "R_386_NONE"; 4233fe401a5SEd Maste case 1: return "R_386_32"; 4243fe401a5SEd Maste case 2: return "R_386_PC32"; 4253fe401a5SEd Maste case 3: return "R_386_GOT32"; 4263fe401a5SEd Maste case 4: return "R_386_PLT32"; 4273fe401a5SEd Maste case 5: return "R_386_COPY"; 4283fe401a5SEd Maste case 6: return "R_386_GLOB_DAT"; 4293fe401a5SEd Maste case 7: return "R_386_JMP_SLOT"; 4303fe401a5SEd Maste case 8: return "R_386_RELATIVE"; 4313fe401a5SEd Maste case 9: return "R_386_GOTOFF"; 4323fe401a5SEd Maste case 10: return "R_386_GOTPC"; 4333fe401a5SEd Maste case 14: return "R_386_TLS_TPOFF"; 4343fe401a5SEd Maste case 15: return "R_386_TLS_IE"; 4353fe401a5SEd Maste case 16: return "R_386_TLS_GOTIE"; 4363fe401a5SEd Maste case 17: return "R_386_TLS_LE"; 4373fe401a5SEd Maste case 18: return "R_386_TLS_GD"; 4383fe401a5SEd Maste case 19: return "R_386_TLS_LDM"; 4393fe401a5SEd Maste case 24: return "R_386_TLS_GD_32"; 4403fe401a5SEd Maste case 25: return "R_386_TLS_GD_PUSH"; 4413fe401a5SEd Maste case 26: return "R_386_TLS_GD_CALL"; 4423fe401a5SEd Maste case 27: return "R_386_TLS_GD_POP"; 4433fe401a5SEd Maste case 28: return "R_386_TLS_LDM_32"; 4443fe401a5SEd Maste case 29: return "R_386_TLS_LDM_PUSH"; 4453fe401a5SEd Maste case 30: return "R_386_TLS_LDM_CALL"; 4463fe401a5SEd Maste case 31: return "R_386_TLS_LDM_POP"; 4473fe401a5SEd Maste case 32: return "R_386_TLS_LDO_32"; 4483fe401a5SEd Maste case 33: return "R_386_TLS_IE_32"; 4493fe401a5SEd Maste case 34: return "R_386_TLS_LE_32"; 4503fe401a5SEd Maste case 35: return "R_386_TLS_DTPMOD32"; 4513fe401a5SEd Maste case 36: return "R_386_TLS_DTPOFF32"; 4523fe401a5SEd Maste case 37: return "R_386_TLS_TPOFF32"; 4533fe401a5SEd Maste default: return ""; 4543fe401a5SEd Maste } 4553fe401a5SEd Maste case EM_ARM: 4563fe401a5SEd Maste switch(type) { 4573fe401a5SEd Maste case 0: return "R_ARM_NONE"; 4583fe401a5SEd Maste case 1: return "R_ARM_PC24"; 4593fe401a5SEd Maste case 2: return "R_ARM_ABS32"; 4603fe401a5SEd Maste case 3: return "R_ARM_REL32"; 4613fe401a5SEd Maste case 4: return "R_ARM_PC13"; 4623fe401a5SEd Maste case 5: return "R_ARM_ABS16"; 4633fe401a5SEd Maste case 6: return "R_ARM_ABS12"; 4643fe401a5SEd Maste case 7: return "R_ARM_THM_ABS5"; 4653fe401a5SEd Maste case 8: return "R_ARM_ABS8"; 4663fe401a5SEd Maste case 9: return "R_ARM_SBREL32"; 4673fe401a5SEd Maste case 10: return "R_ARM_THM_PC22"; 4683fe401a5SEd Maste case 11: return "R_ARM_THM_PC8"; 4693fe401a5SEd Maste case 12: return "R_ARM_AMP_VCALL9"; 4703fe401a5SEd Maste case 13: return "R_ARM_SWI24"; 4713fe401a5SEd Maste case 14: return "R_ARM_THM_SWI8"; 4723fe401a5SEd Maste case 15: return "R_ARM_XPC25"; 4733fe401a5SEd Maste case 16: return "R_ARM_THM_XPC22"; 4743fe401a5SEd Maste case 20: return "R_ARM_COPY"; 4753fe401a5SEd Maste case 21: return "R_ARM_GLOB_DAT"; 4763fe401a5SEd Maste case 22: return "R_ARM_JUMP_SLOT"; 4773fe401a5SEd Maste case 23: return "R_ARM_RELATIVE"; 4783fe401a5SEd Maste case 24: return "R_ARM_GOTOFF"; 4793fe401a5SEd Maste case 25: return "R_ARM_GOTPC"; 4803fe401a5SEd Maste case 26: return "R_ARM_GOT32"; 4813fe401a5SEd Maste case 27: return "R_ARM_PLT32"; 4823fe401a5SEd Maste case 100: return "R_ARM_GNU_VTENTRY"; 4833fe401a5SEd Maste case 101: return "R_ARM_GNU_VTINHERIT"; 4843fe401a5SEd Maste case 250: return "R_ARM_RSBREL32"; 4853fe401a5SEd Maste case 251: return "R_ARM_THM_RPC22"; 4863fe401a5SEd Maste case 252: return "R_ARM_RREL32"; 4873fe401a5SEd Maste case 253: return "R_ARM_RABS32"; 4883fe401a5SEd Maste case 254: return "R_ARM_RPC24"; 4893fe401a5SEd Maste case 255: return "R_ARM_RBASE"; 4903fe401a5SEd Maste default: return ""; 4913fe401a5SEd Maste } 4923fe401a5SEd Maste case EM_IA_64: 4933fe401a5SEd Maste switch(type) { 4943fe401a5SEd Maste case 0: return "R_IA_64_NONE"; 4953fe401a5SEd Maste case 33: return "R_IA_64_IMM14"; 4963fe401a5SEd Maste case 34: return "R_IA_64_IMM22"; 4973fe401a5SEd Maste case 35: return "R_IA_64_IMM64"; 4983fe401a5SEd Maste case 36: return "R_IA_64_DIR32MSB"; 4993fe401a5SEd Maste case 37: return "R_IA_64_DIR32LSB"; 5003fe401a5SEd Maste case 38: return "R_IA_64_DIR64MSB"; 5013fe401a5SEd Maste case 39: return "R_IA_64_DIR64LSB"; 5023fe401a5SEd Maste case 42: return "R_IA_64_GPREL22"; 5033fe401a5SEd Maste case 43: return "R_IA_64_GPREL64I"; 5043fe401a5SEd Maste case 44: return "R_IA_64_GPREL32MSB"; 5053fe401a5SEd Maste case 45: return "R_IA_64_GPREL32LSB"; 5063fe401a5SEd Maste case 46: return "R_IA_64_GPREL64MSB"; 5073fe401a5SEd Maste case 47: return "R_IA_64_GPREL64LSB"; 5083fe401a5SEd Maste case 50: return "R_IA_64_LTOFF22"; 5093fe401a5SEd Maste case 51: return "R_IA_64_LTOFF64I"; 5103fe401a5SEd Maste case 58: return "R_IA_64_PLTOFF22"; 5113fe401a5SEd Maste case 59: return "R_IA_64_PLTOFF64I"; 5123fe401a5SEd Maste case 62: return "R_IA_64_PLTOFF64MSB"; 5133fe401a5SEd Maste case 63: return "R_IA_64_PLTOFF64LSB"; 5143fe401a5SEd Maste case 67: return "R_IA_64_FPTR64I"; 5153fe401a5SEd Maste case 68: return "R_IA_64_FPTR32MSB"; 5163fe401a5SEd Maste case 69: return "R_IA_64_FPTR32LSB"; 5173fe401a5SEd Maste case 70: return "R_IA_64_FPTR64MSB"; 5183fe401a5SEd Maste case 71: return "R_IA_64_FPTR64LSB"; 5193fe401a5SEd Maste case 72: return "R_IA_64_PCREL60B"; 5203fe401a5SEd Maste case 73: return "R_IA_64_PCREL21B"; 5213fe401a5SEd Maste case 74: return "R_IA_64_PCREL21M"; 5223fe401a5SEd Maste case 75: return "R_IA_64_PCREL21F"; 5233fe401a5SEd Maste case 76: return "R_IA_64_PCREL32MSB"; 5243fe401a5SEd Maste case 77: return "R_IA_64_PCREL32LSB"; 5253fe401a5SEd Maste case 78: return "R_IA_64_PCREL64MSB"; 5263fe401a5SEd Maste case 79: return "R_IA_64_PCREL64LSB"; 5273fe401a5SEd Maste case 82: return "R_IA_64_LTOFF_FPTR22"; 5283fe401a5SEd Maste case 83: return "R_IA_64_LTOFF_FPTR64I"; 5293fe401a5SEd Maste case 84: return "R_IA_64_LTOFF_FPTR32MSB"; 5303fe401a5SEd Maste case 85: return "R_IA_64_LTOFF_FPTR32LSB"; 5313fe401a5SEd Maste case 86: return "R_IA_64_LTOFF_FPTR64MSB"; 5323fe401a5SEd Maste case 87: return "R_IA_64_LTOFF_FPTR64LSB"; 5333fe401a5SEd Maste case 92: return "R_IA_64_SEGREL32MSB"; 5343fe401a5SEd Maste case 93: return "R_IA_64_SEGREL32LSB"; 5353fe401a5SEd Maste case 94: return "R_IA_64_SEGREL64MSB"; 5363fe401a5SEd Maste case 95: return "R_IA_64_SEGREL64LSB"; 5373fe401a5SEd Maste case 100: return "R_IA_64_SECREL32MSB"; 5383fe401a5SEd Maste case 101: return "R_IA_64_SECREL32LSB"; 5393fe401a5SEd Maste case 102: return "R_IA_64_SECREL64MSB"; 5403fe401a5SEd Maste case 103: return "R_IA_64_SECREL64LSB"; 5413fe401a5SEd Maste case 108: return "R_IA_64_REL32MSB"; 5423fe401a5SEd Maste case 109: return "R_IA_64_REL32LSB"; 5433fe401a5SEd Maste case 110: return "R_IA_64_REL64MSB"; 5443fe401a5SEd Maste case 111: return "R_IA_64_REL64LSB"; 5453fe401a5SEd Maste case 116: return "R_IA_64_LTV32MSB"; 5463fe401a5SEd Maste case 117: return "R_IA_64_LTV32LSB"; 5473fe401a5SEd Maste case 118: return "R_IA_64_LTV64MSB"; 5483fe401a5SEd Maste case 119: return "R_IA_64_LTV64LSB"; 5493fe401a5SEd Maste case 121: return "R_IA_64_PCREL21BI"; 5503fe401a5SEd Maste case 122: return "R_IA_64_PCREL22"; 5513fe401a5SEd Maste case 123: return "R_IA_64_PCREL64I"; 5523fe401a5SEd Maste case 128: return "R_IA_64_IPLTMSB"; 5533fe401a5SEd Maste case 129: return "R_IA_64_IPLTLSB"; 5543fe401a5SEd Maste case 133: return "R_IA_64_SUB"; 5553fe401a5SEd Maste case 134: return "R_IA_64_LTOFF22X"; 5563fe401a5SEd Maste case 135: return "R_IA_64_LDXMOV"; 5573fe401a5SEd Maste case 145: return "R_IA_64_TPREL14"; 5583fe401a5SEd Maste case 146: return "R_IA_64_TPREL22"; 5593fe401a5SEd Maste case 147: return "R_IA_64_TPREL64I"; 5603fe401a5SEd Maste case 150: return "R_IA_64_TPREL64MSB"; 5613fe401a5SEd Maste case 151: return "R_IA_64_TPREL64LSB"; 5623fe401a5SEd Maste case 154: return "R_IA_64_LTOFF_TPREL22"; 5633fe401a5SEd Maste case 166: return "R_IA_64_DTPMOD64MSB"; 5643fe401a5SEd Maste case 167: return "R_IA_64_DTPMOD64LSB"; 5653fe401a5SEd Maste case 170: return "R_IA_64_LTOFF_DTPMOD22"; 5663fe401a5SEd Maste case 177: return "R_IA_64_DTPREL14"; 5673fe401a5SEd Maste case 178: return "R_IA_64_DTPREL22"; 5683fe401a5SEd Maste case 179: return "R_IA_64_DTPREL64I"; 5693fe401a5SEd Maste case 180: return "R_IA_64_DTPREL32MSB"; 5703fe401a5SEd Maste case 181: return "R_IA_64_DTPREL32LSB"; 5713fe401a5SEd Maste case 182: return "R_IA_64_DTPREL64MSB"; 5723fe401a5SEd Maste case 183: return "R_IA_64_DTPREL64LSB"; 5733fe401a5SEd Maste case 186: return "R_IA_64_LTOFF_DTPREL22"; 5743fe401a5SEd Maste default: return ""; 5753fe401a5SEd Maste } 5763fe401a5SEd Maste case EM_MIPS: 5773fe401a5SEd Maste switch(type) { 5783fe401a5SEd Maste case 0: return "R_MIPS_NONE"; 5793fe401a5SEd Maste case 1: return "R_MIPS_16"; 5803fe401a5SEd Maste case 2: return "R_MIPS_32"; 5813fe401a5SEd Maste case 3: return "R_MIPS_REL32"; 5823fe401a5SEd Maste case 4: return "R_MIPS_26"; 5833fe401a5SEd Maste case 5: return "R_MIPS_HI16"; 5843fe401a5SEd Maste case 6: return "R_MIPS_LO16"; 5853fe401a5SEd Maste case 7: return "R_MIPS_GPREL16"; 5863fe401a5SEd Maste case 8: return "R_MIPS_LITERAL"; 5873fe401a5SEd Maste case 9: return "R_MIPS_GOT16"; 5883fe401a5SEd Maste case 10: return "R_MIPS_PC16"; 5893fe401a5SEd Maste case 11: return "R_MIPS_CALL16"; 5903fe401a5SEd Maste case 12: return "R_MIPS_GPREL32"; 5913fe401a5SEd Maste case 21: return "R_MIPS_GOTHI16"; 5923fe401a5SEd Maste case 22: return "R_MIPS_GOTLO16"; 5933fe401a5SEd Maste case 30: return "R_MIPS_CALLHI16"; 5943fe401a5SEd Maste case 31: return "R_MIPS_CALLLO16"; 5953fe401a5SEd Maste default: return ""; 5963fe401a5SEd Maste } 5973fe401a5SEd Maste case EM_PPC: 5983fe401a5SEd Maste switch(type) { 5993fe401a5SEd Maste case 0: return "R_PPC_NONE"; 6003fe401a5SEd Maste case 1: return "R_PPC_ADDR32"; 6013fe401a5SEd Maste case 2: return "R_PPC_ADDR24"; 6023fe401a5SEd Maste case 3: return "R_PPC_ADDR16"; 6033fe401a5SEd Maste case 4: return "R_PPC_ADDR16_LO"; 6043fe401a5SEd Maste case 5: return "R_PPC_ADDR16_HI"; 6053fe401a5SEd Maste case 6: return "R_PPC_ADDR16_HA"; 6063fe401a5SEd Maste case 7: return "R_PPC_ADDR14"; 6073fe401a5SEd Maste case 8: return "R_PPC_ADDR14_BRTAKEN"; 6083fe401a5SEd Maste case 9: return "R_PPC_ADDR14_BRNTAKEN"; 6093fe401a5SEd Maste case 10: return "R_PPC_REL24"; 6103fe401a5SEd Maste case 11: return "R_PPC_REL14"; 6113fe401a5SEd Maste case 12: return "R_PPC_REL14_BRTAKEN"; 6123fe401a5SEd Maste case 13: return "R_PPC_REL14_BRNTAKEN"; 6133fe401a5SEd Maste case 14: return "R_PPC_GOT16"; 6143fe401a5SEd Maste case 15: return "R_PPC_GOT16_LO"; 6153fe401a5SEd Maste case 16: return "R_PPC_GOT16_HI"; 6163fe401a5SEd Maste case 17: return "R_PPC_GOT16_HA"; 6173fe401a5SEd Maste case 18: return "R_PPC_PLTREL24"; 6183fe401a5SEd Maste case 19: return "R_PPC_COPY"; 6193fe401a5SEd Maste case 20: return "R_PPC_GLOB_DAT"; 6203fe401a5SEd Maste case 21: return "R_PPC_JMP_SLOT"; 6213fe401a5SEd Maste case 22: return "R_PPC_RELATIVE"; 6223fe401a5SEd Maste case 23: return "R_PPC_LOCAL24PC"; 6233fe401a5SEd Maste case 24: return "R_PPC_UADDR32"; 6243fe401a5SEd Maste case 25: return "R_PPC_UADDR16"; 6253fe401a5SEd Maste case 26: return "R_PPC_REL32"; 6263fe401a5SEd Maste case 27: return "R_PPC_PLT32"; 6273fe401a5SEd Maste case 28: return "R_PPC_PLTREL32"; 6283fe401a5SEd Maste case 29: return "R_PPC_PLT16_LO"; 6293fe401a5SEd Maste case 30: return "R_PPC_PLT16_HI"; 6303fe401a5SEd Maste case 31: return "R_PPC_PLT16_HA"; 6313fe401a5SEd Maste case 32: return "R_PPC_SDAREL16"; 6323fe401a5SEd Maste case 33: return "R_PPC_SECTOFF"; 6333fe401a5SEd Maste case 34: return "R_PPC_SECTOFF_LO"; 6343fe401a5SEd Maste case 35: return "R_PPC_SECTOFF_HI"; 6353fe401a5SEd Maste case 36: return "R_PPC_SECTOFF_HA"; 6363fe401a5SEd Maste case 67: return "R_PPC_TLS"; 6373fe401a5SEd Maste case 68: return "R_PPC_DTPMOD32"; 6383fe401a5SEd Maste case 69: return "R_PPC_TPREL16"; 6393fe401a5SEd Maste case 70: return "R_PPC_TPREL16_LO"; 6403fe401a5SEd Maste case 71: return "R_PPC_TPREL16_HI"; 6413fe401a5SEd Maste case 72: return "R_PPC_TPREL16_HA"; 6423fe401a5SEd Maste case 73: return "R_PPC_TPREL32"; 6433fe401a5SEd Maste case 74: return "R_PPC_DTPREL16"; 6443fe401a5SEd Maste case 75: return "R_PPC_DTPREL16_LO"; 6453fe401a5SEd Maste case 76: return "R_PPC_DTPREL16_HI"; 6463fe401a5SEd Maste case 77: return "R_PPC_DTPREL16_HA"; 6473fe401a5SEd Maste case 78: return "R_PPC_DTPREL32"; 6483fe401a5SEd Maste case 79: return "R_PPC_GOT_TLSGD16"; 6493fe401a5SEd Maste case 80: return "R_PPC_GOT_TLSGD16_LO"; 6503fe401a5SEd Maste case 81: return "R_PPC_GOT_TLSGD16_HI"; 6513fe401a5SEd Maste case 82: return "R_PPC_GOT_TLSGD16_HA"; 6523fe401a5SEd Maste case 83: return "R_PPC_GOT_TLSLD16"; 6533fe401a5SEd Maste case 84: return "R_PPC_GOT_TLSLD16_LO"; 6543fe401a5SEd Maste case 85: return "R_PPC_GOT_TLSLD16_HI"; 6553fe401a5SEd Maste case 86: return "R_PPC_GOT_TLSLD16_HA"; 6563fe401a5SEd Maste case 87: return "R_PPC_GOT_TPREL16"; 6573fe401a5SEd Maste case 88: return "R_PPC_GOT_TPREL16_LO"; 6583fe401a5SEd Maste case 89: return "R_PPC_GOT_TPREL16_HI"; 6593fe401a5SEd Maste case 90: return "R_PPC_GOT_TPREL16_HA"; 6603fe401a5SEd Maste case 101: return "R_PPC_EMB_NADDR32"; 6613fe401a5SEd Maste case 102: return "R_PPC_EMB_NADDR16"; 6623fe401a5SEd Maste case 103: return "R_PPC_EMB_NADDR16_LO"; 6633fe401a5SEd Maste case 104: return "R_PPC_EMB_NADDR16_HI"; 6643fe401a5SEd Maste case 105: return "R_PPC_EMB_NADDR16_HA"; 6653fe401a5SEd Maste case 106: return "R_PPC_EMB_SDAI16"; 6663fe401a5SEd Maste case 107: return "R_PPC_EMB_SDA2I16"; 6673fe401a5SEd Maste case 108: return "R_PPC_EMB_SDA2REL"; 6683fe401a5SEd Maste case 109: return "R_PPC_EMB_SDA21"; 6693fe401a5SEd Maste case 110: return "R_PPC_EMB_MRKREF"; 6703fe401a5SEd Maste case 111: return "R_PPC_EMB_RELSEC16"; 6713fe401a5SEd Maste case 112: return "R_PPC_EMB_RELST_LO"; 6723fe401a5SEd Maste case 113: return "R_PPC_EMB_RELST_HI"; 6733fe401a5SEd Maste case 114: return "R_PPC_EMB_RELST_HA"; 6743fe401a5SEd Maste case 115: return "R_PPC_EMB_BIT_FLD"; 6753fe401a5SEd Maste case 116: return "R_PPC_EMB_RELSDA"; 6763fe401a5SEd Maste default: return ""; 6773fe401a5SEd Maste } 6783fe401a5SEd Maste case EM_SPARC: 6793fe401a5SEd Maste case EM_SPARCV9: 6803fe401a5SEd Maste switch(type) { 6813fe401a5SEd Maste case 0: return "R_SPARC_NONE"; 6823fe401a5SEd Maste case 1: return "R_SPARC_8"; 6833fe401a5SEd Maste case 2: return "R_SPARC_16"; 6843fe401a5SEd Maste case 3: return "R_SPARC_32"; 6853fe401a5SEd Maste case 4: return "R_SPARC_DISP8"; 6863fe401a5SEd Maste case 5: return "R_SPARC_DISP16"; 6873fe401a5SEd Maste case 6: return "R_SPARC_DISP32"; 6883fe401a5SEd Maste case 7: return "R_SPARC_WDISP30"; 6893fe401a5SEd Maste case 8: return "R_SPARC_WDISP22"; 6903fe401a5SEd Maste case 9: return "R_SPARC_HI22"; 6913fe401a5SEd Maste case 10: return "R_SPARC_22"; 6923fe401a5SEd Maste case 11: return "R_SPARC_13"; 6933fe401a5SEd Maste case 12: return "R_SPARC_LO10"; 6943fe401a5SEd Maste case 13: return "R_SPARC_GOT10"; 6953fe401a5SEd Maste case 14: return "R_SPARC_GOT13"; 6963fe401a5SEd Maste case 15: return "R_SPARC_GOT22"; 6973fe401a5SEd Maste case 16: return "R_SPARC_PC10"; 6983fe401a5SEd Maste case 17: return "R_SPARC_PC22"; 6993fe401a5SEd Maste case 18: return "R_SPARC_WPLT30"; 7003fe401a5SEd Maste case 19: return "R_SPARC_COPY"; 7013fe401a5SEd Maste case 20: return "R_SPARC_GLOB_DAT"; 7023fe401a5SEd Maste case 21: return "R_SPARC_JMP_SLOT"; 7033fe401a5SEd Maste case 22: return "R_SPARC_RELATIVE"; 7043fe401a5SEd Maste case 23: return "R_SPARC_UA32"; 7053fe401a5SEd Maste case 24: return "R_SPARC_PLT32"; 7063fe401a5SEd Maste case 25: return "R_SPARC_HIPLT22"; 7073fe401a5SEd Maste case 26: return "R_SPARC_LOPLT10"; 7083fe401a5SEd Maste case 27: return "R_SPARC_PCPLT32"; 7093fe401a5SEd Maste case 28: return "R_SPARC_PCPLT22"; 7103fe401a5SEd Maste case 29: return "R_SPARC_PCPLT10"; 7113fe401a5SEd Maste case 30: return "R_SPARC_10"; 7123fe401a5SEd Maste case 31: return "R_SPARC_11"; 7133fe401a5SEd Maste case 32: return "R_SPARC_64"; 7143fe401a5SEd Maste case 33: return "R_SPARC_OLO10"; 7153fe401a5SEd Maste case 34: return "R_SPARC_HH22"; 7163fe401a5SEd Maste case 35: return "R_SPARC_HM10"; 7173fe401a5SEd Maste case 36: return "R_SPARC_LM22"; 7183fe401a5SEd Maste case 37: return "R_SPARC_PC_HH22"; 7193fe401a5SEd Maste case 38: return "R_SPARC_PC_HM10"; 7203fe401a5SEd Maste case 39: return "R_SPARC_PC_LM22"; 7213fe401a5SEd Maste case 40: return "R_SPARC_WDISP16"; 7223fe401a5SEd Maste case 41: return "R_SPARC_WDISP19"; 7233fe401a5SEd Maste case 42: return "R_SPARC_GLOB_JMP"; 7243fe401a5SEd Maste case 43: return "R_SPARC_7"; 7253fe401a5SEd Maste case 44: return "R_SPARC_5"; 7263fe401a5SEd Maste case 45: return "R_SPARC_6"; 7273fe401a5SEd Maste case 46: return "R_SPARC_DISP64"; 7283fe401a5SEd Maste case 47: return "R_SPARC_PLT64"; 7293fe401a5SEd Maste case 48: return "R_SPARC_HIX22"; 7303fe401a5SEd Maste case 49: return "R_SPARC_LOX10"; 7313fe401a5SEd Maste case 50: return "R_SPARC_H44"; 7323fe401a5SEd Maste case 51: return "R_SPARC_M44"; 7333fe401a5SEd Maste case 52: return "R_SPARC_L44"; 7343fe401a5SEd Maste case 53: return "R_SPARC_REGISTER"; 7353fe401a5SEd Maste case 54: return "R_SPARC_UA64"; 7363fe401a5SEd Maste case 55: return "R_SPARC_UA16"; 7373fe401a5SEd Maste case 56: return "R_SPARC_TLS_GD_HI22"; 7383fe401a5SEd Maste case 57: return "R_SPARC_TLS_GD_LO10"; 7393fe401a5SEd Maste case 58: return "R_SPARC_TLS_GD_ADD"; 7403fe401a5SEd Maste case 59: return "R_SPARC_TLS_GD_CALL"; 7413fe401a5SEd Maste case 60: return "R_SPARC_TLS_LDM_HI22"; 7423fe401a5SEd Maste case 61: return "R_SPARC_TLS_LDM_LO10"; 7433fe401a5SEd Maste case 62: return "R_SPARC_TLS_LDM_ADD"; 7443fe401a5SEd Maste case 63: return "R_SPARC_TLS_LDM_CALL"; 7453fe401a5SEd Maste case 64: return "R_SPARC_TLS_LDO_HIX22"; 7463fe401a5SEd Maste case 65: return "R_SPARC_TLS_LDO_LOX10"; 7473fe401a5SEd Maste case 66: return "R_SPARC_TLS_LDO_ADD"; 7483fe401a5SEd Maste case 67: return "R_SPARC_TLS_IE_HI22"; 7493fe401a5SEd Maste case 68: return "R_SPARC_TLS_IE_LO10"; 7503fe401a5SEd Maste case 69: return "R_SPARC_TLS_IE_LD"; 7513fe401a5SEd Maste case 70: return "R_SPARC_TLS_IE_LDX"; 7523fe401a5SEd Maste case 71: return "R_SPARC_TLS_IE_ADD"; 7533fe401a5SEd Maste case 72: return "R_SPARC_TLS_LE_HIX22"; 7543fe401a5SEd Maste case 73: return "R_SPARC_TLS_LE_LOX10"; 7553fe401a5SEd Maste case 74: return "R_SPARC_TLS_DTPMOD32"; 7563fe401a5SEd Maste case 75: return "R_SPARC_TLS_DTPMOD64"; 7573fe401a5SEd Maste case 76: return "R_SPARC_TLS_DTPOFF32"; 7583fe401a5SEd Maste case 77: return "R_SPARC_TLS_DTPOFF64"; 7593fe401a5SEd Maste case 78: return "R_SPARC_TLS_TPOFF32"; 7603fe401a5SEd Maste case 79: return "R_SPARC_TLS_TPOFF64"; 7613fe401a5SEd Maste default: return ""; 7623fe401a5SEd Maste } 7633fe401a5SEd Maste case EM_X86_64: 7643fe401a5SEd Maste switch(type) { 7653fe401a5SEd Maste case 0: return "R_X86_64_NONE"; 7663fe401a5SEd Maste case 1: return "R_X86_64_64"; 7673fe401a5SEd Maste case 2: return "R_X86_64_PC32"; 7683fe401a5SEd Maste case 3: return "R_X86_64_GOT32"; 7693fe401a5SEd Maste case 4: return "R_X86_64_PLT32"; 7703fe401a5SEd Maste case 5: return "R_X86_64_COPY"; 7713fe401a5SEd Maste case 6: return "R_X86_64_GLOB_DAT"; 7723fe401a5SEd Maste case 7: return "R_X86_64_JMP_SLOT"; 7733fe401a5SEd Maste case 8: return "R_X86_64_RELATIVE"; 7743fe401a5SEd Maste case 9: return "R_X86_64_GOTPCREL"; 7753fe401a5SEd Maste case 10: return "R_X86_64_32"; 7763fe401a5SEd Maste case 11: return "R_X86_64_32S"; 7773fe401a5SEd Maste case 12: return "R_X86_64_16"; 7783fe401a5SEd Maste case 13: return "R_X86_64_PC16"; 7793fe401a5SEd Maste case 14: return "R_X86_64_8"; 7803fe401a5SEd Maste case 15: return "R_X86_64_PC8"; 7813fe401a5SEd Maste case 16: return "R_X86_64_DTPMOD64"; 7823fe401a5SEd Maste case 17: return "R_X86_64_DTPOFF64"; 7833fe401a5SEd Maste case 18: return "R_X86_64_TPOFF64"; 7843fe401a5SEd Maste case 19: return "R_X86_64_TLSGD"; 7853fe401a5SEd Maste case 20: return "R_X86_64_TLSLD"; 7863fe401a5SEd Maste case 21: return "R_X86_64_DTPOFF32"; 7873fe401a5SEd Maste case 22: return "R_X86_64_GOTTPOFF"; 7883fe401a5SEd Maste case 23: return "R_X86_64_TPOFF32"; 7893fe401a5SEd Maste default: return ""; 7903fe401a5SEd Maste } 7913fe401a5SEd Maste default: return ""; 7923fe401a5SEd Maste } 7933fe401a5SEd Maste } 7943fe401a5SEd Maste 7953fe401a5SEd Maste static void add_name(struct elfdump *ed, const char *name); 7963fe401a5SEd Maste static void elf_print_object(struct elfdump *ed); 7973fe401a5SEd Maste static void elf_print_elf(struct elfdump *ed); 7983fe401a5SEd Maste static void elf_print_ehdr(struct elfdump *ed); 7993fe401a5SEd Maste static void elf_print_phdr(struct elfdump *ed); 8003fe401a5SEd Maste static void elf_print_shdr(struct elfdump *ed); 8013fe401a5SEd Maste static void elf_print_symtab(struct elfdump *ed, int i); 8023fe401a5SEd Maste static void elf_print_symtabs(struct elfdump *ed); 8033fe401a5SEd Maste static void elf_print_symver(struct elfdump *ed); 8043fe401a5SEd Maste static void elf_print_verdef(struct elfdump *ed, struct section *s); 8053fe401a5SEd Maste static void elf_print_verneed(struct elfdump *ed, struct section *s); 8063fe401a5SEd Maste static void elf_print_interp(struct elfdump *ed); 8073fe401a5SEd Maste static void elf_print_dynamic(struct elfdump *ed); 8083fe401a5SEd Maste static void elf_print_rel_entry(struct elfdump *ed, struct section *s, 8093fe401a5SEd Maste int j, struct rel_entry *r); 8103fe401a5SEd Maste static void elf_print_rela(struct elfdump *ed, struct section *s, 8113fe401a5SEd Maste Elf_Data *data); 8123fe401a5SEd Maste static void elf_print_rel(struct elfdump *ed, struct section *s, 8133fe401a5SEd Maste Elf_Data *data); 8143fe401a5SEd Maste static void elf_print_reloc(struct elfdump *ed); 8153fe401a5SEd Maste static void elf_print_got(struct elfdump *ed); 8163fe401a5SEd Maste static void elf_print_got_section(struct elfdump *ed, struct section *s); 8173fe401a5SEd Maste static void elf_print_note(struct elfdump *ed); 8183fe401a5SEd Maste static void elf_print_svr4_hash(struct elfdump *ed, struct section *s); 8193fe401a5SEd Maste static void elf_print_svr4_hash64(struct elfdump *ed, struct section *s); 8203fe401a5SEd Maste static void elf_print_gnu_hash(struct elfdump *ed, struct section *s); 8213fe401a5SEd Maste static void elf_print_hash(struct elfdump *ed); 8223fe401a5SEd Maste static void elf_print_checksum(struct elfdump *ed); 8233fe401a5SEd Maste static void find_gotrel(struct elfdump *ed, struct section *gs, 8243fe401a5SEd Maste struct rel_entry *got); 8253fe401a5SEd Maste static struct spec_name *find_name(struct elfdump *ed, const char *name); 826*656f49f8SEd Maste static int get_ent_count(const struct section *s, int *ent_count); 8273fe401a5SEd Maste static const char *get_symbol_name(struct elfdump *ed, int symtab, int i); 8283fe401a5SEd Maste static const char *get_string(struct elfdump *ed, int strtab, size_t off); 8293fe401a5SEd Maste static void get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs); 8303fe401a5SEd Maste static void load_sections(struct elfdump *ed); 8313fe401a5SEd Maste static void unload_sections(struct elfdump *ed); 8323fe401a5SEd Maste static void usage(void); 8333fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 8343fe401a5SEd Maste static int ac_detect_ar(int fd); 8353fe401a5SEd Maste static void ac_print_ar(struct elfdump *ed, int fd); 8363fe401a5SEd Maste #else 8373fe401a5SEd Maste static void elf_print_ar(struct elfdump *ed, int fd); 8383fe401a5SEd Maste #endif /* USE_LIBARCHIVE_AR */ 8393fe401a5SEd Maste 8403fe401a5SEd Maste static struct option elfdump_longopts[] = 8413fe401a5SEd Maste { 8423fe401a5SEd Maste { "help", no_argument, NULL, 'H' }, 8433fe401a5SEd Maste { "version", no_argument, NULL, 'V' }, 8443fe401a5SEd Maste { NULL, 0, NULL, 0 } 8453fe401a5SEd Maste }; 8463fe401a5SEd Maste 8473fe401a5SEd Maste int 8483fe401a5SEd Maste main(int ac, char **av) 8493fe401a5SEd Maste { 8503fe401a5SEd Maste struct elfdump *ed, ed_storage; 8513fe401a5SEd Maste struct spec_name *sn; 8523fe401a5SEd Maste int ch, i; 8533fe401a5SEd Maste 8543fe401a5SEd Maste ed = &ed_storage; 8553fe401a5SEd Maste memset(ed, 0, sizeof(*ed)); 8563fe401a5SEd Maste STAILQ_INIT(&ed->snl); 8573fe401a5SEd Maste ed->out = stdout; 8583fe401a5SEd Maste while ((ch = getopt_long(ac, av, "acdeiGHhknN:prsSvVw:", 8593fe401a5SEd Maste elfdump_longopts, NULL)) != -1) 8603fe401a5SEd Maste switch (ch) { 8613fe401a5SEd Maste case 'a': 8623fe401a5SEd Maste ed->options = ED_ALL; 8633fe401a5SEd Maste break; 8643fe401a5SEd Maste case 'c': 8653fe401a5SEd Maste ed->options |= ED_SHDR; 8663fe401a5SEd Maste break; 8673fe401a5SEd Maste case 'd': 8683fe401a5SEd Maste ed->options |= ED_DYN; 8693fe401a5SEd Maste break; 8703fe401a5SEd Maste case 'e': 8713fe401a5SEd Maste ed->options |= ED_EHDR; 8723fe401a5SEd Maste break; 8733fe401a5SEd Maste case 'i': 8743fe401a5SEd Maste ed->options |= ED_INTERP; 8753fe401a5SEd Maste break; 8763fe401a5SEd Maste case 'G': 8773fe401a5SEd Maste ed->options |= ED_GOT; 8783fe401a5SEd Maste break; 8793fe401a5SEd Maste case 'h': 8803fe401a5SEd Maste ed->options |= ED_HASH; 8813fe401a5SEd Maste break; 8823fe401a5SEd Maste case 'k': 8833fe401a5SEd Maste ed->options |= ED_CHECKSUM; 8843fe401a5SEd Maste break; 8853fe401a5SEd Maste case 'n': 8863fe401a5SEd Maste ed->options |= ED_NOTE; 8873fe401a5SEd Maste break; 8883fe401a5SEd Maste case 'N': 8893fe401a5SEd Maste add_name(ed, optarg); 8903fe401a5SEd Maste break; 8913fe401a5SEd Maste case 'p': 8923fe401a5SEd Maste ed->options |= ED_PHDR; 8933fe401a5SEd Maste break; 8943fe401a5SEd Maste case 'r': 8953fe401a5SEd Maste ed->options |= ED_REL; 8963fe401a5SEd Maste break; 8973fe401a5SEd Maste case 's': 8983fe401a5SEd Maste ed->options |= ED_SYMTAB; 8993fe401a5SEd Maste break; 9003fe401a5SEd Maste case 'S': 9013fe401a5SEd Maste ed->flags |= SOLARIS_FMT; 9023fe401a5SEd Maste break; 9033fe401a5SEd Maste case 'v': 9043fe401a5SEd Maste ed->options |= ED_SYMVER; 9053fe401a5SEd Maste break; 9063fe401a5SEd Maste case 'V': 9073fe401a5SEd Maste (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), 9083fe401a5SEd Maste elftc_version()); 9093fe401a5SEd Maste exit(EXIT_SUCCESS); 9103fe401a5SEd Maste break; 9113fe401a5SEd Maste case 'w': 9123fe401a5SEd Maste if ((ed->out = fopen(optarg, "w")) == NULL) 9133fe401a5SEd Maste err(EXIT_FAILURE, "%s", optarg); 9143fe401a5SEd Maste break; 9153fe401a5SEd Maste case '?': 9163fe401a5SEd Maste case 'H': 9173fe401a5SEd Maste default: 9183fe401a5SEd Maste usage(); 9193fe401a5SEd Maste } 9203fe401a5SEd Maste 9213fe401a5SEd Maste ac -= optind; 9223fe401a5SEd Maste av += optind; 9233fe401a5SEd Maste 9243fe401a5SEd Maste if (ed->options == 0) 9253fe401a5SEd Maste ed->options = ED_ALL; 9263fe401a5SEd Maste sn = NULL; 9273fe401a5SEd Maste if (ed->options & ED_SYMTAB && 9283fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || (sn = find_name(ed, "ARSYM")) != NULL)) { 9293fe401a5SEd Maste ed->flags |= PRINT_ARSYM; 9303fe401a5SEd Maste if (sn != NULL) { 9313fe401a5SEd Maste STAILQ_REMOVE(&ed->snl, sn, spec_name, sn_list); 9323fe401a5SEd Maste if (STAILQ_EMPTY(&ed->snl)) 9333fe401a5SEd Maste ed->flags |= ONLY_ARSYM; 9343fe401a5SEd Maste } 9353fe401a5SEd Maste } 9363fe401a5SEd Maste if (ac == 0) 9373fe401a5SEd Maste usage(); 9383fe401a5SEd Maste if (ac > 1) 9393fe401a5SEd Maste ed->flags |= PRINT_FILENAME; 9403fe401a5SEd Maste if (elf_version(EV_CURRENT) == EV_NONE) 9413fe401a5SEd Maste errx(EXIT_FAILURE, "ELF library initialization failed: %s", 9423fe401a5SEd Maste elf_errmsg(-1)); 9433fe401a5SEd Maste 9443fe401a5SEd Maste for (i = 0; i < ac; i++) { 9453fe401a5SEd Maste ed->filename = av[i]; 9463fe401a5SEd Maste ed->archive = NULL; 9473fe401a5SEd Maste elf_print_object(ed); 9483fe401a5SEd Maste } 9493fe401a5SEd Maste 9503fe401a5SEd Maste exit(EXIT_SUCCESS); 9513fe401a5SEd Maste } 9523fe401a5SEd Maste 9533fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 9543fe401a5SEd Maste 9553fe401a5SEd Maste /* Archive symbol table entry. */ 9563fe401a5SEd Maste struct arsym_entry { 9573fe401a5SEd Maste char *sym_name; 9583fe401a5SEd Maste size_t off; 9593fe401a5SEd Maste }; 9603fe401a5SEd Maste 9613fe401a5SEd Maste /* 9623fe401a5SEd Maste * Convenient wrapper for general libarchive error handling. 9633fe401a5SEd Maste */ 9643fe401a5SEd Maste #define AC(CALL) do { \ 9653fe401a5SEd Maste if ((CALL)) { \ 9663fe401a5SEd Maste warnx("%s", archive_error_string(a)); \ 9673fe401a5SEd Maste return; \ 9683fe401a5SEd Maste } \ 9693fe401a5SEd Maste } while (0) 9703fe401a5SEd Maste 9713fe401a5SEd Maste /* 9723fe401a5SEd Maste * Detect an ar(1) archive using libarchive(3). 9733fe401a5SEd Maste */ 9743fe401a5SEd Maste static int 9753fe401a5SEd Maste ac_detect_ar(int fd) 9763fe401a5SEd Maste { 9773fe401a5SEd Maste struct archive *a; 9783fe401a5SEd Maste struct archive_entry *entry; 9793fe401a5SEd Maste int r; 9803fe401a5SEd Maste 9813fe401a5SEd Maste r = -1; 9823fe401a5SEd Maste if ((a = archive_read_new()) == NULL) 9833fe401a5SEd Maste return (0); 9843fe401a5SEd Maste archive_read_support_format_ar(a); 9853fe401a5SEd Maste if (archive_read_open_fd(a, fd, 10240) == ARCHIVE_OK) 9863fe401a5SEd Maste r = archive_read_next_header(a, &entry); 9873fe401a5SEd Maste archive_read_close(a); 9883fe401a5SEd Maste archive_read_free(a); 9893fe401a5SEd Maste 9903fe401a5SEd Maste return (r == ARCHIVE_OK); 9913fe401a5SEd Maste } 9923fe401a5SEd Maste 9933fe401a5SEd Maste /* 9943fe401a5SEd Maste * Dump an ar(1) archive using libarchive(3). 9953fe401a5SEd Maste */ 9963fe401a5SEd Maste static void 9973fe401a5SEd Maste ac_print_ar(struct elfdump *ed, int fd) 9983fe401a5SEd Maste { 9993fe401a5SEd Maste struct archive *a; 10003fe401a5SEd Maste struct archive_entry *entry; 10013fe401a5SEd Maste struct arsym_entry *arsym; 10023fe401a5SEd Maste const char *name; 10033fe401a5SEd Maste char idx[10], *b; 10043fe401a5SEd Maste void *buff; 10053fe401a5SEd Maste size_t size; 10063fe401a5SEd Maste uint32_t cnt; 10073fe401a5SEd Maste int i, r; 10083fe401a5SEd Maste 10093fe401a5SEd Maste if (lseek(fd, 0, SEEK_SET) == -1) 10103fe401a5SEd Maste err(EXIT_FAILURE, "lseek failed"); 10113fe401a5SEd Maste if ((a = archive_read_new()) == NULL) 10123fe401a5SEd Maste errx(EXIT_FAILURE, "%s", archive_error_string(a)); 10133fe401a5SEd Maste archive_read_support_format_ar(a); 10143fe401a5SEd Maste AC(archive_read_open_fd(a, fd, 10240)); 10153fe401a5SEd Maste for(;;) { 10163fe401a5SEd Maste r = archive_read_next_header(a, &entry); 10173fe401a5SEd Maste if (r == ARCHIVE_FATAL) 10183fe401a5SEd Maste errx(EXIT_FAILURE, "%s", archive_error_string(a)); 10193fe401a5SEd Maste if (r == ARCHIVE_EOF) 10203fe401a5SEd Maste break; 10213fe401a5SEd Maste if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY) 10223fe401a5SEd Maste warnx("%s", archive_error_string(a)); 10233fe401a5SEd Maste if (r == ARCHIVE_RETRY) 10243fe401a5SEd Maste continue; 10253fe401a5SEd Maste name = archive_entry_pathname(entry); 10263fe401a5SEd Maste size = archive_entry_size(entry); 10273fe401a5SEd Maste if (size == 0) 10283fe401a5SEd Maste continue; 10293fe401a5SEd Maste if ((buff = malloc(size)) == NULL) { 10303fe401a5SEd Maste warn("malloc failed"); 10313fe401a5SEd Maste continue; 10323fe401a5SEd Maste } 10333fe401a5SEd Maste if (archive_read_data(a, buff, size) != (ssize_t)size) { 10343fe401a5SEd Maste warnx("%s", archive_error_string(a)); 10353fe401a5SEd Maste free(buff); 10363fe401a5SEd Maste continue; 10373fe401a5SEd Maste } 10383fe401a5SEd Maste 10393fe401a5SEd Maste /* 10403fe401a5SEd Maste * Note that when processing arsym via libarchive, there is 10413fe401a5SEd Maste * no way to tell which member a certain symbol belongs to, 10423fe401a5SEd Maste * since we can not just "lseek" to a member offset and read 10433fe401a5SEd Maste * the member header. 10443fe401a5SEd Maste */ 10453fe401a5SEd Maste if (!strcmp(name, "/") && ed->flags & PRINT_ARSYM) { 10463fe401a5SEd Maste b = buff; 10473fe401a5SEd Maste cnt = be32dec(b); 10483fe401a5SEd Maste if (cnt == 0) { 10493fe401a5SEd Maste free(buff); 10503fe401a5SEd Maste continue; 10513fe401a5SEd Maste } 10523fe401a5SEd Maste arsym = calloc(cnt, sizeof(*arsym)); 10533fe401a5SEd Maste if (arsym == NULL) 10543fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 10553fe401a5SEd Maste b += sizeof(uint32_t); 10563fe401a5SEd Maste for (i = 0; (size_t)i < cnt; i++) { 10573fe401a5SEd Maste arsym[i].off = be32dec(b); 10583fe401a5SEd Maste b += sizeof(uint32_t); 10593fe401a5SEd Maste } 10603fe401a5SEd Maste for (i = 0; (size_t)i < cnt; i++) { 10613fe401a5SEd Maste arsym[i].sym_name = b; 10623fe401a5SEd Maste b += strlen(b) + 1; 10633fe401a5SEd Maste } 10643fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 10653fe401a5SEd Maste PRT("\nSymbol Table: (archive)\n"); 10663fe401a5SEd Maste PRT(" index offset symbol\n"); 10673fe401a5SEd Maste } else 10683fe401a5SEd Maste PRT("\nsymbol table (archive):\n"); 10693fe401a5SEd Maste for (i = 0; (size_t)i < cnt; i++) { 10703fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 10713fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", i); 10723fe401a5SEd Maste PRT("%10s ", idx); 10733fe401a5SEd Maste PRT("0x%8.8jx ", 10743fe401a5SEd Maste (uintmax_t)arsym[i].off); 10753fe401a5SEd Maste PRT("%s\n", arsym[i].sym_name); 10763fe401a5SEd Maste } else { 10773fe401a5SEd Maste PRT("\nentry: %d\n", i); 10783fe401a5SEd Maste PRT("\toffset: %#jx\n", 10793fe401a5SEd Maste (uintmax_t)arsym[i].off); 10803fe401a5SEd Maste PRT("\tsymbol: %s\n", 10813fe401a5SEd Maste arsym[i].sym_name); 10823fe401a5SEd Maste } 10833fe401a5SEd Maste } 10843fe401a5SEd Maste free(arsym); 10853fe401a5SEd Maste free(buff); 10863fe401a5SEd Maste /* No need to continue if we only dump ARSYM. */ 10873fe401a5SEd Maste if (ed->flags & ONLY_ARSYM) { 10883fe401a5SEd Maste AC(archive_read_close(a)); 10893fe401a5SEd Maste AC(archive_read_free(a)); 10903fe401a5SEd Maste return; 10913fe401a5SEd Maste } 10923fe401a5SEd Maste continue; 10933fe401a5SEd Maste } 10943fe401a5SEd Maste if ((ed->elf = elf_memory(buff, size)) == NULL) { 10953fe401a5SEd Maste warnx("elf_memroy() failed: %s", 10963fe401a5SEd Maste elf_errmsg(-1)); 10973fe401a5SEd Maste free(buff); 10983fe401a5SEd Maste continue; 10993fe401a5SEd Maste } 11003fe401a5SEd Maste /* Skip non-ELF member. */ 11013fe401a5SEd Maste if (elf_kind(ed->elf) == ELF_K_ELF) { 11023fe401a5SEd Maste printf("\n%s(%s):\n", ed->archive, name); 11033fe401a5SEd Maste elf_print_elf(ed); 11043fe401a5SEd Maste } 11053fe401a5SEd Maste elf_end(ed->elf); 11063fe401a5SEd Maste free(buff); 11073fe401a5SEd Maste } 11083fe401a5SEd Maste AC(archive_read_close(a)); 11093fe401a5SEd Maste AC(archive_read_free(a)); 11103fe401a5SEd Maste } 11113fe401a5SEd Maste 11123fe401a5SEd Maste #else /* USE_LIBARCHIVE_AR */ 11133fe401a5SEd Maste 11143fe401a5SEd Maste /* 11153fe401a5SEd Maste * Dump an ar(1) archive. 11163fe401a5SEd Maste */ 11173fe401a5SEd Maste static void 11183fe401a5SEd Maste elf_print_ar(struct elfdump *ed, int fd) 11193fe401a5SEd Maste { 11203fe401a5SEd Maste Elf *e; 11213fe401a5SEd Maste Elf_Arhdr *arh; 11223fe401a5SEd Maste Elf_Arsym *arsym; 11233fe401a5SEd Maste Elf_Cmd cmd; 11243fe401a5SEd Maste char idx[10]; 11253fe401a5SEd Maste size_t cnt; 11263fe401a5SEd Maste int i; 11273fe401a5SEd Maste 11283fe401a5SEd Maste ed->ar = ed->elf; 11293fe401a5SEd Maste 11303fe401a5SEd Maste if (ed->flags & PRINT_ARSYM) { 11313fe401a5SEd Maste cnt = 0; 11323fe401a5SEd Maste if ((arsym = elf_getarsym(ed->ar, &cnt)) == NULL) { 11333fe401a5SEd Maste warnx("elf_getarsym failed: %s", elf_errmsg(-1)); 11343fe401a5SEd Maste goto print_members; 11353fe401a5SEd Maste } 11363fe401a5SEd Maste if (cnt == 0) 11373fe401a5SEd Maste goto print_members; 11383fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 11393fe401a5SEd Maste PRT("\nSymbol Table: (archive)\n"); 11403fe401a5SEd Maste PRT(" index offset member name and symbol\n"); 11413fe401a5SEd Maste } else 11423fe401a5SEd Maste PRT("\nsymbol table (archive):\n"); 11433fe401a5SEd Maste for (i = 0; (size_t)i < cnt - 1; i++) { 11443fe401a5SEd Maste if (elf_rand(ed->ar, arsym[i].as_off) != 11453fe401a5SEd Maste arsym[i].as_off) { 11463fe401a5SEd Maste warnx("elf_rand failed: %s", elf_errmsg(-1)); 11473fe401a5SEd Maste break; 11483fe401a5SEd Maste } 11493fe401a5SEd Maste if ((e = elf_begin(fd, ELF_C_READ, ed->ar)) == NULL) { 11503fe401a5SEd Maste warnx("elf_begin failed: %s", elf_errmsg(-1)); 11513fe401a5SEd Maste break; 11523fe401a5SEd Maste } 11533fe401a5SEd Maste if ((arh = elf_getarhdr(e)) == NULL) { 11543fe401a5SEd Maste warnx("elf_getarhdr failed: %s", 11553fe401a5SEd Maste elf_errmsg(-1)); 11563fe401a5SEd Maste break; 11573fe401a5SEd Maste } 11583fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 11593fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", i); 11603fe401a5SEd Maste PRT("%10s ", idx); 11613fe401a5SEd Maste PRT("0x%8.8jx ", 11623fe401a5SEd Maste (uintmax_t)arsym[i].as_off); 11633fe401a5SEd Maste PRT("(%s):%s\n", arh->ar_name, 11643fe401a5SEd Maste arsym[i].as_name); 11653fe401a5SEd Maste } else { 11663fe401a5SEd Maste PRT("\nentry: %d\n", i); 11673fe401a5SEd Maste PRT("\toffset: %#jx\n", 11683fe401a5SEd Maste (uintmax_t)arsym[i].as_off); 11693fe401a5SEd Maste PRT("\tmember: %s\n", arh->ar_name); 11703fe401a5SEd Maste PRT("\tsymbol: %s\n", arsym[i].as_name); 11713fe401a5SEd Maste } 11723fe401a5SEd Maste elf_end(e); 11733fe401a5SEd Maste } 11743fe401a5SEd Maste 11753fe401a5SEd Maste /* No need to continue if we only dump ARSYM. */ 11763fe401a5SEd Maste if (ed->flags & ONLY_ARSYM) 11773fe401a5SEd Maste return; 11783fe401a5SEd Maste } 11793fe401a5SEd Maste 11803fe401a5SEd Maste print_members: 11813fe401a5SEd Maste 11823fe401a5SEd Maste /* Rewind the archive. */ 11833fe401a5SEd Maste if (elf_rand(ed->ar, SARMAG) != SARMAG) { 11843fe401a5SEd Maste warnx("elf_rand failed: %s", elf_errmsg(-1)); 11853fe401a5SEd Maste return; 11863fe401a5SEd Maste } 11873fe401a5SEd Maste 11883fe401a5SEd Maste /* Dump each member of the archive. */ 11893fe401a5SEd Maste cmd = ELF_C_READ; 11903fe401a5SEd Maste while ((ed->elf = elf_begin(fd, cmd, ed->ar)) != NULL) { 11913fe401a5SEd Maste /* Skip non-ELF member. */ 11923fe401a5SEd Maste if (elf_kind(ed->elf) == ELF_K_ELF) { 11933fe401a5SEd Maste if ((arh = elf_getarhdr(ed->elf)) == NULL) { 11943fe401a5SEd Maste warnx("elf_getarhdr failed: %s", 11953fe401a5SEd Maste elf_errmsg(-1)); 11963fe401a5SEd Maste break; 11973fe401a5SEd Maste } 11983fe401a5SEd Maste printf("\n%s(%s):\n", ed->archive, arh->ar_name); 11993fe401a5SEd Maste elf_print_elf(ed); 12003fe401a5SEd Maste } 12013fe401a5SEd Maste cmd = elf_next(ed->elf); 12023fe401a5SEd Maste elf_end(ed->elf); 12033fe401a5SEd Maste } 12043fe401a5SEd Maste } 12053fe401a5SEd Maste 12063fe401a5SEd Maste #endif /* USE_LIBARCHIVE_AR */ 12073fe401a5SEd Maste 12083fe401a5SEd Maste /* 12093fe401a5SEd Maste * Dump an object. (ELF object or ar(1) archive) 12103fe401a5SEd Maste */ 12113fe401a5SEd Maste static void 12123fe401a5SEd Maste elf_print_object(struct elfdump *ed) 12133fe401a5SEd Maste { 12143fe401a5SEd Maste int fd; 12153fe401a5SEd Maste 12163fe401a5SEd Maste if ((fd = open(ed->filename, O_RDONLY)) == -1) { 12173fe401a5SEd Maste warn("open %s failed", ed->filename); 12183fe401a5SEd Maste return; 12193fe401a5SEd Maste } 12203fe401a5SEd Maste 12213fe401a5SEd Maste #ifdef USE_LIBARCHIVE_AR 12223fe401a5SEd Maste if (ac_detect_ar(fd)) { 12233fe401a5SEd Maste ed->archive = ed->filename; 12243fe401a5SEd Maste ac_print_ar(ed, fd); 12253fe401a5SEd Maste return; 12263fe401a5SEd Maste } 12273fe401a5SEd Maste #endif /* USE_LIBARCHIVE_AR */ 12283fe401a5SEd Maste 12293fe401a5SEd Maste if ((ed->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 12303fe401a5SEd Maste warnx("elf_begin() failed: %s", elf_errmsg(-1)); 12313fe401a5SEd Maste return; 12323fe401a5SEd Maste } 12333fe401a5SEd Maste 12343fe401a5SEd Maste switch (elf_kind(ed->elf)) { 12353fe401a5SEd Maste case ELF_K_NONE: 12363fe401a5SEd Maste warnx("Not an ELF file."); 12373fe401a5SEd Maste return; 12383fe401a5SEd Maste case ELF_K_ELF: 12393fe401a5SEd Maste if (ed->flags & PRINT_FILENAME) 12403fe401a5SEd Maste printf("\n%s:\n", ed->filename); 12413fe401a5SEd Maste elf_print_elf(ed); 12423fe401a5SEd Maste break; 12433fe401a5SEd Maste case ELF_K_AR: 12443fe401a5SEd Maste #ifndef USE_LIBARCHIVE_AR 12453fe401a5SEd Maste ed->archive = ed->filename; 12463fe401a5SEd Maste elf_print_ar(ed, fd); 12473fe401a5SEd Maste #endif 12483fe401a5SEd Maste break; 12493fe401a5SEd Maste default: 12503fe401a5SEd Maste warnx("Internal: libelf returned unknown elf kind."); 12513fe401a5SEd Maste return; 12523fe401a5SEd Maste } 12533fe401a5SEd Maste 12543fe401a5SEd Maste elf_end(ed->elf); 12553fe401a5SEd Maste } 12563fe401a5SEd Maste 12573fe401a5SEd Maste /* 12583fe401a5SEd Maste * Dump an ELF object. 12593fe401a5SEd Maste */ 12603fe401a5SEd Maste static void 12613fe401a5SEd Maste elf_print_elf(struct elfdump *ed) 12623fe401a5SEd Maste { 12633fe401a5SEd Maste 12643fe401a5SEd Maste if (gelf_getehdr(ed->elf, &ed->ehdr) == NULL) { 12653fe401a5SEd Maste warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 12663fe401a5SEd Maste return; 12673fe401a5SEd Maste } 12683fe401a5SEd Maste if ((ed->ec = gelf_getclass(ed->elf)) == ELFCLASSNONE) { 12693fe401a5SEd Maste warnx("gelf_getclass failed: %s", elf_errmsg(-1)); 12703fe401a5SEd Maste return; 12713fe401a5SEd Maste } 12723fe401a5SEd Maste 12733fe401a5SEd Maste if (ed->options & (ED_SHDR | ED_DYN | ED_REL | ED_GOT | ED_SYMTAB | 12743fe401a5SEd Maste ED_SYMVER | ED_NOTE | ED_HASH)) 12753fe401a5SEd Maste load_sections(ed); 12763fe401a5SEd Maste 12773fe401a5SEd Maste if (ed->options & ED_EHDR) 12783fe401a5SEd Maste elf_print_ehdr(ed); 12793fe401a5SEd Maste if (ed->options & ED_PHDR) 12803fe401a5SEd Maste elf_print_phdr(ed); 12813fe401a5SEd Maste if (ed->options & ED_INTERP) 12823fe401a5SEd Maste elf_print_interp(ed); 12833fe401a5SEd Maste if (ed->options & ED_SHDR) 12843fe401a5SEd Maste elf_print_shdr(ed); 12853fe401a5SEd Maste if (ed->options & ED_DYN) 12863fe401a5SEd Maste elf_print_dynamic(ed); 12873fe401a5SEd Maste if (ed->options & ED_REL) 12883fe401a5SEd Maste elf_print_reloc(ed); 12893fe401a5SEd Maste if (ed->options & ED_GOT) 12903fe401a5SEd Maste elf_print_got(ed); 12913fe401a5SEd Maste if (ed->options & ED_SYMTAB) 12923fe401a5SEd Maste elf_print_symtabs(ed); 12933fe401a5SEd Maste if (ed->options & ED_SYMVER) 12943fe401a5SEd Maste elf_print_symver(ed); 12953fe401a5SEd Maste if (ed->options & ED_NOTE) 12963fe401a5SEd Maste elf_print_note(ed); 12973fe401a5SEd Maste if (ed->options & ED_HASH) 12983fe401a5SEd Maste elf_print_hash(ed); 12993fe401a5SEd Maste if (ed->options & ED_CHECKSUM) 13003fe401a5SEd Maste elf_print_checksum(ed); 13013fe401a5SEd Maste 13023fe401a5SEd Maste unload_sections(ed); 13033fe401a5SEd Maste } 13043fe401a5SEd Maste 13053fe401a5SEd Maste /* 13063fe401a5SEd Maste * Read the section headers from ELF object and store them in the 13073fe401a5SEd Maste * internal cache. 13083fe401a5SEd Maste */ 13093fe401a5SEd Maste static void 13103fe401a5SEd Maste load_sections(struct elfdump *ed) 13113fe401a5SEd Maste { 13123fe401a5SEd Maste struct section *s; 13133fe401a5SEd Maste const char *name; 13143fe401a5SEd Maste Elf_Scn *scn; 13153fe401a5SEd Maste GElf_Shdr sh; 13163fe401a5SEd Maste size_t shstrndx, ndx; 13173fe401a5SEd Maste int elferr; 13183fe401a5SEd Maste 13193fe401a5SEd Maste assert(ed->sl == NULL); 13203fe401a5SEd Maste 13213fe401a5SEd Maste if (!elf_getshnum(ed->elf, &ed->shnum)) { 13223fe401a5SEd Maste warnx("elf_getshnum failed: %s", elf_errmsg(-1)); 13233fe401a5SEd Maste return; 13243fe401a5SEd Maste } 13253fe401a5SEd Maste if (ed->shnum == 0) 13263fe401a5SEd Maste return; 13273fe401a5SEd Maste if ((ed->sl = calloc(ed->shnum, sizeof(*ed->sl))) == NULL) 13283fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 13293fe401a5SEd Maste if (!elf_getshstrndx(ed->elf, &shstrndx)) { 13303fe401a5SEd Maste warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 13313fe401a5SEd Maste return; 13323fe401a5SEd Maste } 13333fe401a5SEd Maste if ((scn = elf_getscn(ed->elf, 0)) == NULL) { 13343fe401a5SEd Maste warnx("elf_getscn failed: %s", elf_errmsg(-1)); 13353fe401a5SEd Maste return; 13363fe401a5SEd Maste } 13373fe401a5SEd Maste (void) elf_errno(); 13383fe401a5SEd Maste do { 13393fe401a5SEd Maste if (gelf_getshdr(scn, &sh) == NULL) { 13403fe401a5SEd Maste warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 13413fe401a5SEd Maste (void) elf_errno(); 13423fe401a5SEd Maste continue; 13433fe401a5SEd Maste } 13443fe401a5SEd Maste if ((name = elf_strptr(ed->elf, shstrndx, sh.sh_name)) == NULL) { 13453fe401a5SEd Maste (void) elf_errno(); 13463fe401a5SEd Maste name = "ERROR"; 13473fe401a5SEd Maste } 13483fe401a5SEd Maste if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) 13493fe401a5SEd Maste if ((elferr = elf_errno()) != 0) { 13503fe401a5SEd Maste warnx("elf_ndxscn failed: %s", 13513fe401a5SEd Maste elf_errmsg(elferr)); 13523fe401a5SEd Maste continue; 13533fe401a5SEd Maste } 13543fe401a5SEd Maste if (ndx >= ed->shnum) { 13553fe401a5SEd Maste warnx("section index of '%s' out of range", name); 13563fe401a5SEd Maste continue; 13573fe401a5SEd Maste } 13583fe401a5SEd Maste s = &ed->sl[ndx]; 13593fe401a5SEd Maste s->name = name; 13603fe401a5SEd Maste s->scn = scn; 13613fe401a5SEd Maste s->off = sh.sh_offset; 13623fe401a5SEd Maste s->sz = sh.sh_size; 13633fe401a5SEd Maste s->entsize = sh.sh_entsize; 13643fe401a5SEd Maste s->align = sh.sh_addralign; 13653fe401a5SEd Maste s->type = sh.sh_type; 13663fe401a5SEd Maste s->flags = sh.sh_flags; 13673fe401a5SEd Maste s->addr = sh.sh_addr; 13683fe401a5SEd Maste s->link = sh.sh_link; 13693fe401a5SEd Maste s->info = sh.sh_info; 13703fe401a5SEd Maste } while ((scn = elf_nextscn(ed->elf, scn)) != NULL); 13713fe401a5SEd Maste elferr = elf_errno(); 13723fe401a5SEd Maste if (elferr != 0) 13733fe401a5SEd Maste warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 13743fe401a5SEd Maste } 13753fe401a5SEd Maste 13763fe401a5SEd Maste /* 13773fe401a5SEd Maste * Release section related resources. 13783fe401a5SEd Maste */ 13793fe401a5SEd Maste static void 13803fe401a5SEd Maste unload_sections(struct elfdump *ed) 13813fe401a5SEd Maste { 13823fe401a5SEd Maste if (ed->sl != NULL) { 13833fe401a5SEd Maste free(ed->sl); 13843fe401a5SEd Maste ed->sl = NULL; 13853fe401a5SEd Maste } 13863fe401a5SEd Maste } 13873fe401a5SEd Maste 13883fe401a5SEd Maste /* 13893fe401a5SEd Maste * Add a name to the '-N' name list. 13903fe401a5SEd Maste */ 13913fe401a5SEd Maste static void 13923fe401a5SEd Maste add_name(struct elfdump *ed, const char *name) 13933fe401a5SEd Maste { 13943fe401a5SEd Maste struct spec_name *sn; 13953fe401a5SEd Maste 13963fe401a5SEd Maste if (find_name(ed, name)) 13973fe401a5SEd Maste return; 13983fe401a5SEd Maste if ((sn = malloc(sizeof(*sn))) == NULL) { 13993fe401a5SEd Maste warn("malloc failed"); 14003fe401a5SEd Maste return; 14013fe401a5SEd Maste } 14023fe401a5SEd Maste sn->name = name; 14033fe401a5SEd Maste STAILQ_INSERT_TAIL(&ed->snl, sn, sn_list); 14043fe401a5SEd Maste } 14053fe401a5SEd Maste 14063fe401a5SEd Maste /* 14073fe401a5SEd Maste * Lookup a name in the '-N' name list. 14083fe401a5SEd Maste */ 14093fe401a5SEd Maste static struct spec_name * 14103fe401a5SEd Maste find_name(struct elfdump *ed, const char *name) 14113fe401a5SEd Maste { 14123fe401a5SEd Maste struct spec_name *sn; 14133fe401a5SEd Maste 14143fe401a5SEd Maste STAILQ_FOREACH(sn, &ed->snl, sn_list) { 14153fe401a5SEd Maste if (!strcmp(sn->name, name)) 14163fe401a5SEd Maste return (sn); 14173fe401a5SEd Maste } 14183fe401a5SEd Maste 14193fe401a5SEd Maste return (NULL); 14203fe401a5SEd Maste } 14213fe401a5SEd Maste 14223fe401a5SEd Maste /* 14233fe401a5SEd Maste * Retrieve the name of a symbol using the section index of the symbol 14243fe401a5SEd Maste * table and the index of the symbol within that table. 14253fe401a5SEd Maste */ 14263fe401a5SEd Maste static const char * 14273fe401a5SEd Maste get_symbol_name(struct elfdump *ed, int symtab, int i) 14283fe401a5SEd Maste { 14293fe401a5SEd Maste static char sname[64]; 14303fe401a5SEd Maste struct section *s; 14313fe401a5SEd Maste const char *name; 14323fe401a5SEd Maste GElf_Sym sym; 14333fe401a5SEd Maste Elf_Data *data; 14343fe401a5SEd Maste int elferr; 14353fe401a5SEd Maste 14363fe401a5SEd Maste s = &ed->sl[symtab]; 14373fe401a5SEd Maste if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) 14383fe401a5SEd Maste return (""); 14393fe401a5SEd Maste (void) elf_errno(); 14403fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 14413fe401a5SEd Maste elferr = elf_errno(); 14423fe401a5SEd Maste if (elferr != 0) 14433fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 14443fe401a5SEd Maste return (""); 14453fe401a5SEd Maste } 14463fe401a5SEd Maste if (gelf_getsym(data, i, &sym) != &sym) 14473fe401a5SEd Maste return (""); 14483fe401a5SEd Maste if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) { 14493fe401a5SEd Maste if (sym.st_shndx < ed->shnum) { 14503fe401a5SEd Maste snprintf(sname, sizeof(sname), "%s (section)", 14513fe401a5SEd Maste ed->sl[sym.st_shndx].name); 14523fe401a5SEd Maste return (sname); 14533fe401a5SEd Maste } else 14543fe401a5SEd Maste return (""); 14553fe401a5SEd Maste } 14563fe401a5SEd Maste if ((name = elf_strptr(ed->elf, s->link, sym.st_name)) == NULL) 14573fe401a5SEd Maste return (""); 14583fe401a5SEd Maste 14593fe401a5SEd Maste return (name); 14603fe401a5SEd Maste } 14613fe401a5SEd Maste 14623fe401a5SEd Maste /* 14633fe401a5SEd Maste * Retrieve a string using string table section index and the string offset. 14643fe401a5SEd Maste */ 14653fe401a5SEd Maste static const char* 14663fe401a5SEd Maste get_string(struct elfdump *ed, int strtab, size_t off) 14673fe401a5SEd Maste { 14683fe401a5SEd Maste const char *name; 14693fe401a5SEd Maste 14703fe401a5SEd Maste if ((name = elf_strptr(ed->elf, strtab, off)) == NULL) 14713fe401a5SEd Maste return (""); 14723fe401a5SEd Maste 14733fe401a5SEd Maste return (name); 14743fe401a5SEd Maste } 14753fe401a5SEd Maste 14763fe401a5SEd Maste /* 14773fe401a5SEd Maste * Dump the ELF Executable Header. 14783fe401a5SEd Maste */ 14793fe401a5SEd Maste static void 14803fe401a5SEd Maste elf_print_ehdr(struct elfdump *ed) 14813fe401a5SEd Maste { 14823fe401a5SEd Maste 14833fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 14843fe401a5SEd Maste return; 14853fe401a5SEd Maste 14863fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 14873fe401a5SEd Maste PRT("\nELF Header\n"); 14883fe401a5SEd Maste PRT(" ei_magic: { %#x, %c, %c, %c }\n", 14893fe401a5SEd Maste ed->ehdr.e_ident[0], ed->ehdr.e_ident[1], 14903fe401a5SEd Maste ed->ehdr.e_ident[2], ed->ehdr.e_ident[3]); 14913fe401a5SEd Maste PRT(" ei_class: %-18s", 14923fe401a5SEd Maste ei_classes[ed->ehdr.e_ident[EI_CLASS]]); 14933fe401a5SEd Maste PRT(" ei_data: %s\n", ei_data[ed->ehdr.e_ident[EI_DATA]]); 14943fe401a5SEd Maste PRT(" e_machine: %-18s", e_machines(ed->ehdr.e_machine)); 14953fe401a5SEd Maste PRT(" e_version: %s\n", ei_versions[ed->ehdr.e_version]); 14963fe401a5SEd Maste PRT(" e_type: %s\n", e_types[ed->ehdr.e_type]); 14973fe401a5SEd Maste PRT(" e_flags: %18d\n", ed->ehdr.e_flags); 14983fe401a5SEd Maste PRT(" e_entry: %#18jx", (uintmax_t)ed->ehdr.e_entry); 14993fe401a5SEd Maste PRT(" e_ehsize: %6d", ed->ehdr.e_ehsize); 15003fe401a5SEd Maste PRT(" e_shstrndx:%5d\n", ed->ehdr.e_shstrndx); 15013fe401a5SEd Maste PRT(" e_shoff: %#18jx", (uintmax_t)ed->ehdr.e_shoff); 15023fe401a5SEd Maste PRT(" e_shentsize: %3d", ed->ehdr.e_shentsize); 15033fe401a5SEd Maste PRT(" e_shnum: %5d\n", ed->ehdr.e_shnum); 15043fe401a5SEd Maste PRT(" e_phoff: %#18jx", (uintmax_t)ed->ehdr.e_phoff); 15053fe401a5SEd Maste PRT(" e_phentsize: %3d", ed->ehdr.e_phentsize); 15063fe401a5SEd Maste PRT(" e_phnum: %5d\n", ed->ehdr.e_phnum); 15073fe401a5SEd Maste } else { 15083fe401a5SEd Maste PRT("\nelf header:\n"); 15093fe401a5SEd Maste PRT("\n"); 15103fe401a5SEd Maste PRT("\te_ident: %s %s %s\n", 15113fe401a5SEd Maste ei_classes[ed->ehdr.e_ident[EI_CLASS]], 15123fe401a5SEd Maste ei_data[ed->ehdr.e_ident[EI_DATA]], 15133fe401a5SEd Maste ei_abis[ed->ehdr.e_ident[EI_OSABI]]); 15143fe401a5SEd Maste PRT("\te_type: %s\n", e_types[ed->ehdr.e_type]); 15153fe401a5SEd Maste PRT("\te_machine: %s\n", e_machines(ed->ehdr.e_machine)); 15163fe401a5SEd Maste PRT("\te_version: %s\n", ei_versions[ed->ehdr.e_version]); 15173fe401a5SEd Maste PRT("\te_entry: %#jx\n", (uintmax_t)ed->ehdr.e_entry); 15183fe401a5SEd Maste PRT("\te_phoff: %ju\n", (uintmax_t)ed->ehdr.e_phoff); 15193fe401a5SEd Maste PRT("\te_shoff: %ju\n", (uintmax_t) ed->ehdr.e_shoff); 15203fe401a5SEd Maste PRT("\te_flags: %u\n", ed->ehdr.e_flags); 15213fe401a5SEd Maste PRT("\te_ehsize: %u\n", ed->ehdr.e_ehsize); 15223fe401a5SEd Maste PRT("\te_phentsize: %u\n", ed->ehdr.e_phentsize); 15233fe401a5SEd Maste PRT("\te_phnum: %u\n", ed->ehdr.e_phnum); 15243fe401a5SEd Maste PRT("\te_shentsize: %u\n", ed->ehdr.e_shentsize); 15253fe401a5SEd Maste PRT("\te_shnum: %u\n", ed->ehdr.e_shnum); 15263fe401a5SEd Maste PRT("\te_shstrndx: %u\n", ed->ehdr.e_shstrndx); 15273fe401a5SEd Maste } 15283fe401a5SEd Maste } 15293fe401a5SEd Maste 15303fe401a5SEd Maste /* 15313fe401a5SEd Maste * Dump the ELF Program Header Table. 15323fe401a5SEd Maste */ 15333fe401a5SEd Maste static void 15343fe401a5SEd Maste elf_print_phdr(struct elfdump *ed) 15353fe401a5SEd Maste { 15363fe401a5SEd Maste GElf_Phdr ph; 15373fe401a5SEd Maste size_t phnum; 15383fe401a5SEd Maste int header, i; 15393fe401a5SEd Maste 15403fe401a5SEd Maste if (elf_getphnum(ed->elf, &phnum) == 0) { 15413fe401a5SEd Maste warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 15423fe401a5SEd Maste return; 15433fe401a5SEd Maste } 15443fe401a5SEd Maste header = 0; 15453fe401a5SEd Maste for (i = 0; (u_int64_t) i < phnum; i++) { 15463fe401a5SEd Maste if (gelf_getphdr(ed->elf, i, &ph) != &ph) { 15473fe401a5SEd Maste warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 15483fe401a5SEd Maste continue; 15493fe401a5SEd Maste } 15503fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl) && 15513fe401a5SEd Maste find_name(ed, p_types[ph.p_type & 0x7]) == NULL) 15523fe401a5SEd Maste continue; 15533fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 15543fe401a5SEd Maste PRT("\nProgram Header[%d]:\n", i); 15553fe401a5SEd Maste PRT(" p_vaddr: %#-14jx", (uintmax_t)ph.p_vaddr); 15563fe401a5SEd Maste PRT(" p_flags: [ %s ]\n", p_flags[ph.p_flags]); 15573fe401a5SEd Maste PRT(" p_paddr: %#-14jx", (uintmax_t)ph.p_paddr); 15583fe401a5SEd Maste PRT(" p_type: [ %s ]\n", p_types[ph.p_type & 0x7]); 15593fe401a5SEd Maste PRT(" p_filesz: %#-14jx", 15603fe401a5SEd Maste (uintmax_t)ph.p_filesz); 15613fe401a5SEd Maste PRT(" p_memsz: %#jx\n", (uintmax_t)ph.p_memsz); 15623fe401a5SEd Maste PRT(" p_offset: %#-14jx", 15633fe401a5SEd Maste (uintmax_t)ph.p_offset); 15643fe401a5SEd Maste PRT(" p_align: %#jx\n", (uintmax_t)ph.p_align); 15653fe401a5SEd Maste } else { 15663fe401a5SEd Maste if (!header) { 15673fe401a5SEd Maste PRT("\nprogram header:\n"); 15683fe401a5SEd Maste header = 1; 15693fe401a5SEd Maste } 15703fe401a5SEd Maste PRT("\n"); 15713fe401a5SEd Maste PRT("entry: %d\n", i); 15723fe401a5SEd Maste PRT("\tp_type: %s\n", p_types[ph.p_type & 0x7]); 15733fe401a5SEd Maste PRT("\tp_offset: %ju\n", (uintmax_t)ph.p_offset); 15743fe401a5SEd Maste PRT("\tp_vaddr: %#jx\n", (uintmax_t)ph.p_vaddr); 15753fe401a5SEd Maste PRT("\tp_paddr: %#jx\n", (uintmax_t)ph.p_paddr); 15763fe401a5SEd Maste PRT("\tp_filesz: %ju\n", (uintmax_t)ph.p_filesz); 15773fe401a5SEd Maste PRT("\tp_memsz: %ju\n", (uintmax_t)ph.p_memsz); 15783fe401a5SEd Maste PRT("\tp_flags: %s\n", p_flags[ph.p_flags]); 15793fe401a5SEd Maste PRT("\tp_align: %ju\n", (uintmax_t)ph.p_align); 15803fe401a5SEd Maste } 15813fe401a5SEd Maste } 15823fe401a5SEd Maste } 15833fe401a5SEd Maste 15843fe401a5SEd Maste /* 15853fe401a5SEd Maste * Dump the ELF Section Header Table. 15863fe401a5SEd Maste */ 15873fe401a5SEd Maste static void 15883fe401a5SEd Maste elf_print_shdr(struct elfdump *ed) 15893fe401a5SEd Maste { 15903fe401a5SEd Maste struct section *s; 15913fe401a5SEd Maste int i; 15923fe401a5SEd Maste 15933fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 15943fe401a5SEd Maste return; 15953fe401a5SEd Maste 15963fe401a5SEd Maste if ((ed->flags & SOLARIS_FMT) == 0) 15973fe401a5SEd Maste PRT("\nsection header:\n"); 15983fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 15993fe401a5SEd Maste s = &ed->sl[i]; 16003fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 16013fe401a5SEd Maste if (i == 0) 16023fe401a5SEd Maste continue; 16033fe401a5SEd Maste PRT("\nSection Header[%d]:", i); 16043fe401a5SEd Maste PRT(" sh_name: %s\n", s->name); 16053fe401a5SEd Maste PRT(" sh_addr: %#-14jx", (uintmax_t)s->addr); 16063fe401a5SEd Maste if (s->flags != 0) 16073fe401a5SEd Maste PRT(" sh_flags: [ %s ]\n", sh_flags(s->flags)); 16083fe401a5SEd Maste else 16093fe401a5SEd Maste PRT(" sh_flags: 0\n"); 16103fe401a5SEd Maste PRT(" sh_size: %#-14jx", (uintmax_t)s->sz); 16113fe401a5SEd Maste PRT(" sh_type: [ %s ]\n", sh_types(s->type)); 16123fe401a5SEd Maste PRT(" sh_offset: %#-14jx", (uintmax_t)s->off); 16133fe401a5SEd Maste PRT(" sh_entsize: %#jx\n", (uintmax_t)s->entsize); 16143fe401a5SEd Maste PRT(" sh_link: %-14u", s->link); 16153fe401a5SEd Maste PRT(" sh_info: %u\n", s->info); 16163fe401a5SEd Maste PRT(" sh_addralign: %#jx\n", (uintmax_t)s->align); 16173fe401a5SEd Maste } else { 16183fe401a5SEd Maste PRT("\n"); 16193fe401a5SEd Maste PRT("entry: %ju\n", (uintmax_t)i); 16203fe401a5SEd Maste PRT("\tsh_name: %s\n", s->name); 16213fe401a5SEd Maste PRT("\tsh_type: %s\n", sh_types(s->type)); 16223fe401a5SEd Maste PRT("\tsh_flags: %s\n", sh_flags(s->flags)); 16233fe401a5SEd Maste PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr); 16243fe401a5SEd Maste PRT("\tsh_offset: %ju\n", (uintmax_t)s->off); 16253fe401a5SEd Maste PRT("\tsh_size: %ju\n", (uintmax_t)s->sz); 16263fe401a5SEd Maste PRT("\tsh_link: %u\n", s->link); 16273fe401a5SEd Maste PRT("\tsh_info: %u\n", s->info); 16283fe401a5SEd Maste PRT("\tsh_addralign: %ju\n", (uintmax_t)s->align); 16293fe401a5SEd Maste PRT("\tsh_entsize: %ju\n", (uintmax_t)s->entsize); 16303fe401a5SEd Maste } 16313fe401a5SEd Maste } 16323fe401a5SEd Maste } 16333fe401a5SEd Maste 16343fe401a5SEd Maste /* 1635*656f49f8SEd Maste * Return number of entries in the given section. We'd prefer ent_count be a 1636*656f49f8SEd Maste * size_t, but libelf APIs already use int for section indices. 1637*656f49f8SEd Maste */ 1638*656f49f8SEd Maste static int 1639*656f49f8SEd Maste get_ent_count(const struct section *s, int *ent_count) 1640*656f49f8SEd Maste { 1641*656f49f8SEd Maste if (s->entsize == 0) { 1642*656f49f8SEd Maste warnx("section %s has entry size 0", s->name); 1643*656f49f8SEd Maste return (0); 1644*656f49f8SEd Maste } else if (s->sz / s->entsize > INT_MAX) { 1645*656f49f8SEd Maste warnx("section %s has invalid section count", s->name); 1646*656f49f8SEd Maste return (0); 1647*656f49f8SEd Maste } 1648*656f49f8SEd Maste *ent_count = (int)(s->sz / s->entsize); 1649*656f49f8SEd Maste return (1); 1650*656f49f8SEd Maste } 1651*656f49f8SEd Maste 1652*656f49f8SEd Maste /* 16533fe401a5SEd Maste * Retrieve the content of the corresponding SHT_SUNW_versym section for 16543fe401a5SEd Maste * a symbol table section. 16553fe401a5SEd Maste */ 16563fe401a5SEd Maste static void 16573fe401a5SEd Maste get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs) 16583fe401a5SEd Maste { 16593fe401a5SEd Maste struct section *s; 16603fe401a5SEd Maste Elf_Data *data; 16613fe401a5SEd Maste int j, elferr; 16623fe401a5SEd Maste 16633fe401a5SEd Maste s = NULL; 16643fe401a5SEd Maste for (j = 0; (size_t)j < ed->shnum; j++) { 16653fe401a5SEd Maste s = &ed->sl[j]; 16663fe401a5SEd Maste if (s->type == SHT_SUNW_versym && s->link == (uint32_t)i) 16673fe401a5SEd Maste break; 16683fe401a5SEd Maste } 16693fe401a5SEd Maste if ((size_t)j >= ed->shnum) { 16703fe401a5SEd Maste *vs = NULL; 16713fe401a5SEd Maste return; 16723fe401a5SEd Maste } 16733fe401a5SEd Maste (void) elf_errno(); 16743fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 16753fe401a5SEd Maste elferr = elf_errno(); 16763fe401a5SEd Maste if (elferr != 0) 16773fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 16783fe401a5SEd Maste *vs = NULL; 16793fe401a5SEd Maste return; 16803fe401a5SEd Maste } 16813fe401a5SEd Maste 16823fe401a5SEd Maste *vs = data->d_buf; 1683*656f49f8SEd Maste assert(data->d_size == s->sz); 1684*656f49f8SEd Maste if (!get_ent_count(s, nvs)) 1685*656f49f8SEd Maste *nvs = 0; 16863fe401a5SEd Maste } 16873fe401a5SEd Maste 16883fe401a5SEd Maste /* 16893fe401a5SEd Maste * Dump the symbol table section. 16903fe401a5SEd Maste */ 16913fe401a5SEd Maste static void 16923fe401a5SEd Maste elf_print_symtab(struct elfdump *ed, int i) 16933fe401a5SEd Maste { 16943fe401a5SEd Maste struct section *s; 16953fe401a5SEd Maste const char *name; 16963fe401a5SEd Maste uint16_t *vs; 16973fe401a5SEd Maste char idx[10]; 16983fe401a5SEd Maste Elf_Data *data; 16993fe401a5SEd Maste GElf_Sym sym; 17003fe401a5SEd Maste int len, j, elferr, nvs; 17013fe401a5SEd Maste 17023fe401a5SEd Maste s = &ed->sl[i]; 17033fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 17043fe401a5SEd Maste PRT("\nSymbol Table Section: %s\n", s->name); 17053fe401a5SEd Maste else 17063fe401a5SEd Maste PRT("\nsymbol table (%s):\n", s->name); 17073fe401a5SEd Maste (void) elf_errno(); 17083fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 17093fe401a5SEd Maste elferr = elf_errno(); 17103fe401a5SEd Maste if (elferr != 0) 17113fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 17123fe401a5SEd Maste return; 17133fe401a5SEd Maste } 17143fe401a5SEd Maste vs = NULL; 17153fe401a5SEd Maste nvs = 0; 1716*656f49f8SEd Maste assert(data->d_size == s->sz); 1717*656f49f8SEd Maste if (!get_ent_count(s, &len)) 1718*656f49f8SEd Maste return; 17193fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 17203fe401a5SEd Maste if (ed->ec == ELFCLASS32) 17213fe401a5SEd Maste PRT(" index value "); 17223fe401a5SEd Maste else 17233fe401a5SEd Maste PRT(" index value "); 17243fe401a5SEd Maste PRT("size type bind oth ver shndx name\n"); 17253fe401a5SEd Maste get_versym(ed, i, &vs, &nvs); 17263fe401a5SEd Maste if (vs != NULL && nvs != len) { 17273fe401a5SEd Maste warnx("#symbol not equal to #versym"); 17283fe401a5SEd Maste vs = NULL; 17293fe401a5SEd Maste } 17303fe401a5SEd Maste } 17313fe401a5SEd Maste for (j = 0; j < len; j++) { 17323fe401a5SEd Maste if (gelf_getsym(data, j, &sym) != &sym) { 17333fe401a5SEd Maste warnx("gelf_getsym failed: %s", elf_errmsg(-1)); 17343fe401a5SEd Maste continue; 17353fe401a5SEd Maste } 17363fe401a5SEd Maste name = get_string(ed, s->link, sym.st_name); 17373fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 17383fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j); 17393fe401a5SEd Maste if (ed->ec == ELFCLASS32) 17403fe401a5SEd Maste PRT("%10s ", idx); 17413fe401a5SEd Maste else 17423fe401a5SEd Maste PRT("%10s ", idx); 17433fe401a5SEd Maste PRT("0x%8.8jx ", (uintmax_t)sym.st_value); 17443fe401a5SEd Maste if (ed->ec == ELFCLASS32) 17453fe401a5SEd Maste PRT("0x%8.8jx ", (uintmax_t)sym.st_size); 17463fe401a5SEd Maste else 17473fe401a5SEd Maste PRT("0x%12.12jx ", (uintmax_t)sym.st_size); 17483fe401a5SEd Maste PRT("%s ", st_types_S[GELF_ST_TYPE(sym.st_info)]); 17493fe401a5SEd Maste PRT("%s ", st_bindings_S[GELF_ST_BIND(sym.st_info)]); 17503fe401a5SEd Maste PRT("%c ", st_others[sym.st_other]); 17513fe401a5SEd Maste PRT("%3u ", (vs == NULL ? 0 : vs[j])); 17523fe401a5SEd Maste PRT("%-11.11s ", sh_name(ed, sym.st_shndx)); 17533fe401a5SEd Maste PRT("%s\n", name); 17543fe401a5SEd Maste } else { 17553fe401a5SEd Maste PRT("\nentry: %d\n", j); 17563fe401a5SEd Maste PRT("\tst_name: %s\n", name); 17573fe401a5SEd Maste PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value); 17583fe401a5SEd Maste PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size); 17593fe401a5SEd Maste PRT("\tst_info: %s %s\n", 17603fe401a5SEd Maste st_types[GELF_ST_TYPE(sym.st_info)], 17613fe401a5SEd Maste st_bindings[GELF_ST_BIND(sym.st_info)]); 17623fe401a5SEd Maste PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx); 17633fe401a5SEd Maste } 17643fe401a5SEd Maste } 17653fe401a5SEd Maste } 17663fe401a5SEd Maste 17673fe401a5SEd Maste /* 17683fe401a5SEd Maste * Dump the symbol tables. (.dynsym and .symtab) 17693fe401a5SEd Maste */ 17703fe401a5SEd Maste static void 17713fe401a5SEd Maste elf_print_symtabs(struct elfdump *ed) 17723fe401a5SEd Maste { 17733fe401a5SEd Maste int i; 17743fe401a5SEd Maste 17753fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) 17763fe401a5SEd Maste if ((ed->sl[i].type == SHT_SYMTAB || 17773fe401a5SEd Maste ed->sl[i].type == SHT_DYNSYM) && 17783fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, ed->sl[i].name))) 17793fe401a5SEd Maste elf_print_symtab(ed, i); 17803fe401a5SEd Maste } 17813fe401a5SEd Maste 17823fe401a5SEd Maste /* 17833fe401a5SEd Maste * Dump the content of .dynamic section. 17843fe401a5SEd Maste */ 17853fe401a5SEd Maste static void 17863fe401a5SEd Maste elf_print_dynamic(struct elfdump *ed) 17873fe401a5SEd Maste { 17883fe401a5SEd Maste struct section *s; 17893fe401a5SEd Maste const char *name; 17903fe401a5SEd Maste char idx[10]; 17913fe401a5SEd Maste Elf_Data *data; 17923fe401a5SEd Maste GElf_Dyn dyn; 17933fe401a5SEd Maste int elferr, i, len; 17943fe401a5SEd Maste 17953fe401a5SEd Maste s = NULL; 17963fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 17973fe401a5SEd Maste s = &ed->sl[i]; 17983fe401a5SEd Maste if (s->type == SHT_DYNAMIC && 17993fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 18003fe401a5SEd Maste break; 18013fe401a5SEd Maste } 18023fe401a5SEd Maste if ((size_t)i >= ed->shnum) 18033fe401a5SEd Maste return; 18043fe401a5SEd Maste 18053fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 18063fe401a5SEd Maste PRT("Dynamic Section: %s\n", s->name); 18073fe401a5SEd Maste PRT(" index tag value\n"); 18083fe401a5SEd Maste } else 18093fe401a5SEd Maste PRT("\ndynamic:\n"); 18103fe401a5SEd Maste (void) elf_errno(); 18113fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 18123fe401a5SEd Maste elferr = elf_errno(); 18133fe401a5SEd Maste if (elferr != 0) 18143fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 18153fe401a5SEd Maste return; 18163fe401a5SEd Maste } 1817*656f49f8SEd Maste assert(data->d_size == s->sz); 1818*656f49f8SEd Maste if (!get_ent_count(s, &len)) 1819*656f49f8SEd Maste return; 18203fe401a5SEd Maste for (i = 0; i < len; i++) { 18213fe401a5SEd Maste if (gelf_getdyn(data, i, &dyn) != &dyn) { 18223fe401a5SEd Maste warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); 18233fe401a5SEd Maste continue; 18243fe401a5SEd Maste } 18253fe401a5SEd Maste 18263fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 18273fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", i); 18283fe401a5SEd Maste PRT("%10s %-16s ", idx, d_tags(dyn.d_tag)); 18293fe401a5SEd Maste } else { 18303fe401a5SEd Maste PRT("\n"); 18313fe401a5SEd Maste PRT("entry: %d\n", i); 18323fe401a5SEd Maste PRT("\td_tag: %s\n", d_tags(dyn.d_tag)); 18333fe401a5SEd Maste } 18343fe401a5SEd Maste switch(dyn.d_tag) { 18353fe401a5SEd Maste case DT_NEEDED: 18363fe401a5SEd Maste case DT_SONAME: 18373fe401a5SEd Maste case DT_RPATH: 18383fe401a5SEd Maste if ((name = elf_strptr(ed->elf, s->link, 18393fe401a5SEd Maste dyn.d_un.d_val)) == NULL) 18403fe401a5SEd Maste name = ""; 18413fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 18423fe401a5SEd Maste PRT("%#-16jx %s\n", (uintmax_t)dyn.d_un.d_val, 18433fe401a5SEd Maste name); 18443fe401a5SEd Maste else 18453fe401a5SEd Maste PRT("\td_val: %s\n", name); 18463fe401a5SEd Maste break; 18473fe401a5SEd Maste case DT_PLTRELSZ: 18483fe401a5SEd Maste case DT_RELA: 18493fe401a5SEd Maste case DT_RELASZ: 18503fe401a5SEd Maste case DT_RELAENT: 18513fe401a5SEd Maste case DT_RELACOUNT: 18523fe401a5SEd Maste case DT_STRSZ: 18533fe401a5SEd Maste case DT_SYMENT: 18543fe401a5SEd Maste case DT_RELSZ: 18553fe401a5SEd Maste case DT_RELENT: 18563fe401a5SEd Maste case DT_PLTREL: 18573fe401a5SEd Maste case DT_VERDEF: 18583fe401a5SEd Maste case DT_VERDEFNUM: 18593fe401a5SEd Maste case DT_VERNEED: 18603fe401a5SEd Maste case DT_VERNEEDNUM: 18613fe401a5SEd Maste case DT_VERSYM: 18623fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 18633fe401a5SEd Maste PRT("%#jx\n", (uintmax_t)dyn.d_un.d_val); 18643fe401a5SEd Maste else 18653fe401a5SEd Maste PRT("\td_val: %ju\n", 18663fe401a5SEd Maste (uintmax_t)dyn.d_un.d_val); 18673fe401a5SEd Maste break; 18683fe401a5SEd Maste case DT_PLTGOT: 18693fe401a5SEd Maste case DT_HASH: 18703fe401a5SEd Maste case DT_GNU_HASH: 18713fe401a5SEd Maste case DT_STRTAB: 18723fe401a5SEd Maste case DT_SYMTAB: 18733fe401a5SEd Maste case DT_INIT: 18743fe401a5SEd Maste case DT_FINI: 18753fe401a5SEd Maste case DT_REL: 18763fe401a5SEd Maste case DT_JMPREL: 18773fe401a5SEd Maste case DT_DEBUG: 18783fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 18793fe401a5SEd Maste PRT("%#jx\n", (uintmax_t)dyn.d_un.d_ptr); 18803fe401a5SEd Maste else 18813fe401a5SEd Maste PRT("\td_ptr: %#jx\n", 18823fe401a5SEd Maste (uintmax_t)dyn.d_un.d_ptr); 18833fe401a5SEd Maste break; 18843fe401a5SEd Maste case DT_NULL: 18853fe401a5SEd Maste case DT_SYMBOLIC: 18863fe401a5SEd Maste case DT_TEXTREL: 18873fe401a5SEd Maste default: 18883fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 18893fe401a5SEd Maste PRT("\n"); 18903fe401a5SEd Maste break; 18913fe401a5SEd Maste } 18923fe401a5SEd Maste } 18933fe401a5SEd Maste } 18943fe401a5SEd Maste 18953fe401a5SEd Maste /* 18963fe401a5SEd Maste * Dump a .rel/.rela section entry. 18973fe401a5SEd Maste */ 18983fe401a5SEd Maste static void 18993fe401a5SEd Maste elf_print_rel_entry(struct elfdump *ed, struct section *s, int j, 19003fe401a5SEd Maste struct rel_entry *r) 19013fe401a5SEd Maste { 19023fe401a5SEd Maste 19033fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 19043fe401a5SEd Maste PRT(" %-23s ", r_type(ed->ehdr.e_machine, 19053fe401a5SEd Maste GELF_R_TYPE(r->u_r.rel.r_info))); 19063fe401a5SEd Maste PRT("%#12jx ", (uintmax_t)r->u_r.rel.r_offset); 19073fe401a5SEd Maste if (r->type == SHT_RELA) 19083fe401a5SEd Maste PRT("%10jd ", (intmax_t)r->u_r.rela.r_addend); 19093fe401a5SEd Maste else 19103fe401a5SEd Maste PRT(" "); 19113fe401a5SEd Maste PRT("%-14s ", s->name); 19123fe401a5SEd Maste PRT("%s\n", r->symn); 19133fe401a5SEd Maste } else { 19143fe401a5SEd Maste PRT("\n"); 19153fe401a5SEd Maste PRT("entry: %d\n", j); 19163fe401a5SEd Maste PRT("\tr_offset: %#jx\n", (uintmax_t)r->u_r.rel.r_offset); 19173fe401a5SEd Maste if (ed->ec == ELFCLASS32) 19183fe401a5SEd Maste PRT("\tr_info: %#jx\n", (uintmax_t) 19193fe401a5SEd Maste ELF32_R_INFO(ELF64_R_SYM(r->u_r.rel.r_info), 19203fe401a5SEd Maste ELF64_R_TYPE(r->u_r.rel.r_info))); 19213fe401a5SEd Maste else 19223fe401a5SEd Maste PRT("\tr_info: %#jx\n", (uintmax_t)r->u_r.rel.r_info); 19233fe401a5SEd Maste if (r->type == SHT_RELA) 19243fe401a5SEd Maste PRT("\tr_addend: %jd\n", 19253fe401a5SEd Maste (intmax_t)r->u_r.rela.r_addend); 19263fe401a5SEd Maste } 19273fe401a5SEd Maste } 19283fe401a5SEd Maste 19293fe401a5SEd Maste /* 19303fe401a5SEd Maste * Dump a relocation section of type SHT_RELA. 19313fe401a5SEd Maste */ 19323fe401a5SEd Maste static void 19333fe401a5SEd Maste elf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data) 19343fe401a5SEd Maste { 19353fe401a5SEd Maste struct rel_entry r; 19363fe401a5SEd Maste int j, len; 19373fe401a5SEd Maste 19383fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 19393fe401a5SEd Maste PRT("\nRelocation Section: %s\n", s->name); 19403fe401a5SEd Maste PRT(" type offset " 19413fe401a5SEd Maste "addend section with respect to\n"); 19423fe401a5SEd Maste } else 19433fe401a5SEd Maste PRT("\nrelocation with addend (%s):\n", s->name); 19443fe401a5SEd Maste r.type = SHT_RELA; 1945*656f49f8SEd Maste assert(data->d_size == s->sz); 1946*656f49f8SEd Maste if (!get_ent_count(s, &len)) 1947*656f49f8SEd Maste return; 19483fe401a5SEd Maste for (j = 0; j < len; j++) { 19493fe401a5SEd Maste if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) { 19503fe401a5SEd Maste warnx("gelf_getrela failed: %s", 19513fe401a5SEd Maste elf_errmsg(-1)); 19523fe401a5SEd Maste continue; 19533fe401a5SEd Maste } 19543fe401a5SEd Maste r.symn = get_symbol_name(ed, s->link, 19553fe401a5SEd Maste GELF_R_SYM(r.u_r.rela.r_info)); 19563fe401a5SEd Maste elf_print_rel_entry(ed, s, j, &r); 19573fe401a5SEd Maste } 19583fe401a5SEd Maste } 19593fe401a5SEd Maste 19603fe401a5SEd Maste /* 19613fe401a5SEd Maste * Dump a relocation section of type SHT_REL. 19623fe401a5SEd Maste */ 19633fe401a5SEd Maste static void 19643fe401a5SEd Maste elf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data) 19653fe401a5SEd Maste { 19663fe401a5SEd Maste struct rel_entry r; 19673fe401a5SEd Maste int j, len; 19683fe401a5SEd Maste 19693fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 19703fe401a5SEd Maste PRT("\nRelocation Section: %s\n", s->name); 19713fe401a5SEd Maste PRT(" type offset " 19723fe401a5SEd Maste "section with respect to\n"); 19733fe401a5SEd Maste } else 19743fe401a5SEd Maste PRT("\nrelocation (%s):\n", s->name); 19753fe401a5SEd Maste r.type = SHT_REL; 1976*656f49f8SEd Maste assert(data->d_size == s->sz); 1977*656f49f8SEd Maste if (!get_ent_count(s, &len)) 1978*656f49f8SEd Maste return; 19793fe401a5SEd Maste for (j = 0; j < len; j++) { 19803fe401a5SEd Maste if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) { 19813fe401a5SEd Maste warnx("gelf_getrel failed: %s", elf_errmsg(-1)); 19823fe401a5SEd Maste continue; 19833fe401a5SEd Maste } 19843fe401a5SEd Maste r.symn = get_symbol_name(ed, s->link, 19853fe401a5SEd Maste GELF_R_SYM(r.u_r.rel.r_info)); 19863fe401a5SEd Maste elf_print_rel_entry(ed, s, j, &r); 19873fe401a5SEd Maste } 19883fe401a5SEd Maste } 19893fe401a5SEd Maste 19903fe401a5SEd Maste /* 19913fe401a5SEd Maste * Dump relocation sections. 19923fe401a5SEd Maste */ 19933fe401a5SEd Maste static void 19943fe401a5SEd Maste elf_print_reloc(struct elfdump *ed) 19953fe401a5SEd Maste { 19963fe401a5SEd Maste struct section *s; 19973fe401a5SEd Maste Elf_Data *data; 19983fe401a5SEd Maste int i, elferr; 19993fe401a5SEd Maste 20003fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 20013fe401a5SEd Maste s = &ed->sl[i]; 20023fe401a5SEd Maste if ((s->type == SHT_REL || s->type == SHT_RELA) && 20033fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 20043fe401a5SEd Maste (void) elf_errno(); 20053fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 20063fe401a5SEd Maste elferr = elf_errno(); 20073fe401a5SEd Maste if (elferr != 0) 20083fe401a5SEd Maste warnx("elf_getdata failed: %s", 20093fe401a5SEd Maste elf_errmsg(elferr)); 20103fe401a5SEd Maste continue; 20113fe401a5SEd Maste } 20123fe401a5SEd Maste if (s->type == SHT_REL) 20133fe401a5SEd Maste elf_print_rel(ed, s, data); 20143fe401a5SEd Maste else 20153fe401a5SEd Maste elf_print_rela(ed, s, data); 20163fe401a5SEd Maste } 20173fe401a5SEd Maste } 20183fe401a5SEd Maste } 20193fe401a5SEd Maste 20203fe401a5SEd Maste /* 20213fe401a5SEd Maste * Dump the content of PT_INTERP segment. 20223fe401a5SEd Maste */ 20233fe401a5SEd Maste static void 20243fe401a5SEd Maste elf_print_interp(struct elfdump *ed) 20253fe401a5SEd Maste { 20263fe401a5SEd Maste const char *s; 20273fe401a5SEd Maste GElf_Phdr phdr; 20283fe401a5SEd Maste size_t phnum; 20293fe401a5SEd Maste int i; 20303fe401a5SEd Maste 20313fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl) && find_name(ed, "PT_INTERP") == NULL) 20323fe401a5SEd Maste return; 20333fe401a5SEd Maste 20343fe401a5SEd Maste if ((s = elf_rawfile(ed->elf, NULL)) == NULL) { 20353fe401a5SEd Maste warnx("elf_rawfile failed: %s", elf_errmsg(-1)); 20363fe401a5SEd Maste return; 20373fe401a5SEd Maste } 20383fe401a5SEd Maste if (!elf_getphnum(ed->elf, &phnum)) { 20393fe401a5SEd Maste warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 20403fe401a5SEd Maste return; 20413fe401a5SEd Maste } 20423fe401a5SEd Maste for (i = 0; (size_t)i < phnum; i++) { 20433fe401a5SEd Maste if (gelf_getphdr(ed->elf, i, &phdr) != &phdr) { 20443fe401a5SEd Maste warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 20453fe401a5SEd Maste continue; 20463fe401a5SEd Maste } 20473fe401a5SEd Maste if (phdr.p_type == PT_INTERP) { 20483fe401a5SEd Maste PRT("\ninterp:\n"); 20493fe401a5SEd Maste PRT("\t%s\n", s + phdr.p_offset); 20503fe401a5SEd Maste } 20513fe401a5SEd Maste } 20523fe401a5SEd Maste } 20533fe401a5SEd Maste 20543fe401a5SEd Maste /* 20553fe401a5SEd Maste * Search the relocation sections for entries refering to the .got section. 20563fe401a5SEd Maste */ 20573fe401a5SEd Maste static void 20583fe401a5SEd Maste find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got) 20593fe401a5SEd Maste { 20603fe401a5SEd Maste struct section *s; 20613fe401a5SEd Maste struct rel_entry r; 20623fe401a5SEd Maste Elf_Data *data; 20633fe401a5SEd Maste int elferr, i, j, k, len; 20643fe401a5SEd Maste 20653fe401a5SEd Maste for(i = 0; (size_t)i < ed->shnum; i++) { 20663fe401a5SEd Maste s = &ed->sl[i]; 20673fe401a5SEd Maste if (s->type != SHT_REL && s->type != SHT_RELA) 20683fe401a5SEd Maste continue; 20693fe401a5SEd Maste (void) elf_errno(); 20703fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 20713fe401a5SEd Maste elferr = elf_errno(); 20723fe401a5SEd Maste if (elferr != 0) 20733fe401a5SEd Maste warnx("elf_getdata failed: %s", 20743fe401a5SEd Maste elf_errmsg(elferr)); 20753fe401a5SEd Maste return; 20763fe401a5SEd Maste } 20773fe401a5SEd Maste memset(&r, 0, sizeof(struct rel_entry)); 20783fe401a5SEd Maste r.type = s->type; 2079*656f49f8SEd Maste assert(data->d_size == s->sz); 2080*656f49f8SEd Maste if (!get_ent_count(s, &len)) 2081*656f49f8SEd Maste return; 20823fe401a5SEd Maste for (j = 0; j < len; j++) { 20833fe401a5SEd Maste if (s->type == SHT_REL) { 20843fe401a5SEd Maste if (gelf_getrel(data, j, &r.u_r.rel) != 20853fe401a5SEd Maste &r.u_r.rel) { 20863fe401a5SEd Maste warnx("gelf_getrel failed: %s", 20873fe401a5SEd Maste elf_errmsg(-1)); 20883fe401a5SEd Maste continue; 20893fe401a5SEd Maste } 20903fe401a5SEd Maste } else { 20913fe401a5SEd Maste if (gelf_getrela(data, j, &r.u_r.rela) != 20923fe401a5SEd Maste &r.u_r.rela) { 20933fe401a5SEd Maste warnx("gelf_getrel failed: %s", 20943fe401a5SEd Maste elf_errmsg(-1)); 20953fe401a5SEd Maste continue; 20963fe401a5SEd Maste } 20973fe401a5SEd Maste } 20983fe401a5SEd Maste if (r.u_r.rel.r_offset >= gs->addr && 20993fe401a5SEd Maste r.u_r.rel.r_offset < gs->addr + gs->sz) { 21003fe401a5SEd Maste r.symn = get_symbol_name(ed, s->link, 21013fe401a5SEd Maste GELF_R_SYM(r.u_r.rel.r_info)); 21023fe401a5SEd Maste k = (r.u_r.rel.r_offset - gs->addr) / 21033fe401a5SEd Maste gs->entsize; 21043fe401a5SEd Maste memcpy(&got[k], &r, sizeof(struct rel_entry)); 21053fe401a5SEd Maste } 21063fe401a5SEd Maste } 21073fe401a5SEd Maste } 21083fe401a5SEd Maste } 21093fe401a5SEd Maste 21103fe401a5SEd Maste static void 21113fe401a5SEd Maste elf_print_got_section(struct elfdump *ed, struct section *s) 21123fe401a5SEd Maste { 21133fe401a5SEd Maste struct rel_entry *got; 21143fe401a5SEd Maste Elf_Data *data, dst; 21153fe401a5SEd Maste int elferr, i, len; 21163fe401a5SEd Maste 21173fe401a5SEd Maste if (s->entsize == 0) { 21183fe401a5SEd Maste /* XXX IA64 GOT section generated by gcc has entry size 0. */ 21193fe401a5SEd Maste if (s->align != 0) 21203fe401a5SEd Maste s->entsize = s->align; 21213fe401a5SEd Maste else 21223fe401a5SEd Maste return; 21233fe401a5SEd Maste } 21243fe401a5SEd Maste 2125*656f49f8SEd Maste if (!get_ent_count(s, &len)) 2126*656f49f8SEd Maste return; 21273fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 2128*656f49f8SEd Maste PRT("\nGlobal Offset Table Section: %s (%d entries)\n", 2129*656f49f8SEd Maste s->name, len); 21303fe401a5SEd Maste else 21313fe401a5SEd Maste PRT("\nglobal offset table: %s\n", s->name); 21323fe401a5SEd Maste (void) elf_errno(); 21333fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 21343fe401a5SEd Maste elferr = elf_errno(); 21353fe401a5SEd Maste if (elferr != 0) 21363fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 21373fe401a5SEd Maste return; 21383fe401a5SEd Maste } 21393fe401a5SEd Maste 21403fe401a5SEd Maste /* 21413fe401a5SEd Maste * GOT section has section type SHT_PROGBITS, thus libelf treats it as 21423fe401a5SEd Maste * byte stream and will not perfrom any translation on it. As a result, 21433fe401a5SEd Maste * an exlicit call to gelf_xlatetom is needed here. Depends on arch, 21443fe401a5SEd Maste * GOT section should be translated to either WORD or XWORD. 21453fe401a5SEd Maste */ 21463fe401a5SEd Maste if (ed->ec == ELFCLASS32) 21473fe401a5SEd Maste data->d_type = ELF_T_WORD; 21483fe401a5SEd Maste else 21493fe401a5SEd Maste data->d_type = ELF_T_XWORD; 21503fe401a5SEd Maste memcpy(&dst, data, sizeof(Elf_Data)); 21513fe401a5SEd Maste if (gelf_xlatetom(ed->elf, &dst, data, ed->ehdr.e_ident[EI_DATA]) != 21523fe401a5SEd Maste &dst) { 21533fe401a5SEd Maste warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 21543fe401a5SEd Maste return; 21553fe401a5SEd Maste } 2156*656f49f8SEd Maste assert(dst.d_size == s->sz); 21573fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 21583fe401a5SEd Maste /* 21593fe401a5SEd Maste * In verbose/Solaris mode, we search the relocation sections 21603fe401a5SEd Maste * and try to find the corresponding reloc entry for each GOT 21613fe401a5SEd Maste * section entry. 21623fe401a5SEd Maste */ 21633fe401a5SEd Maste if ((got = calloc(len, sizeof(struct rel_entry))) == NULL) 21643fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 21653fe401a5SEd Maste find_gotrel(ed, s, got); 21663fe401a5SEd Maste if (ed->ec == ELFCLASS32) { 21673fe401a5SEd Maste PRT(" ndx addr value reloc "); 21683fe401a5SEd Maste PRT("addend symbol\n"); 21693fe401a5SEd Maste } else { 21703fe401a5SEd Maste PRT(" ndx addr value "); 21713fe401a5SEd Maste PRT("reloc addend symbol\n"); 21723fe401a5SEd Maste } 21733fe401a5SEd Maste for(i = 0; i < len; i++) { 21743fe401a5SEd Maste PRT("[%5.5d] ", i); 21753fe401a5SEd Maste if (ed->ec == ELFCLASS32) { 21763fe401a5SEd Maste PRT("%-8.8jx ", s->addr + i * s->entsize); 21773fe401a5SEd Maste PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i)); 21783fe401a5SEd Maste } else { 21793fe401a5SEd Maste PRT("%-16.16jx ", s->addr + i * s->entsize); 21803fe401a5SEd Maste PRT("%-16.16jx ", *((uint64_t *)dst.d_buf + i)); 21813fe401a5SEd Maste } 21823fe401a5SEd Maste PRT("%-18s ", r_type(ed->ehdr.e_machine, 21833fe401a5SEd Maste GELF_R_TYPE(got[i].u_r.rel.r_info))); 21843fe401a5SEd Maste if (ed->ec == ELFCLASS32) 21853fe401a5SEd Maste PRT("%-8.8jd ", 21863fe401a5SEd Maste (intmax_t)got[i].u_r.rela.r_addend); 21873fe401a5SEd Maste else 21883fe401a5SEd Maste PRT("%-12.12jd ", 21893fe401a5SEd Maste (intmax_t)got[i].u_r.rela.r_addend); 21903fe401a5SEd Maste if (got[i].symn == NULL) 21913fe401a5SEd Maste got[i].symn = ""; 21923fe401a5SEd Maste PRT("%s\n", got[i].symn); 21933fe401a5SEd Maste } 21943fe401a5SEd Maste free(got); 21953fe401a5SEd Maste } else { 21963fe401a5SEd Maste for(i = 0; i < len; i++) { 21973fe401a5SEd Maste PRT("\nentry: %d\n", i); 21983fe401a5SEd Maste if (ed->ec == ELFCLASS32) 21993fe401a5SEd Maste PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i)); 22003fe401a5SEd Maste else 22013fe401a5SEd Maste PRT("\t%#jx\n", *((uint64_t *)dst.d_buf + i)); 22023fe401a5SEd Maste } 22033fe401a5SEd Maste } 22043fe401a5SEd Maste } 22053fe401a5SEd Maste 22063fe401a5SEd Maste /* 22073fe401a5SEd Maste * Dump the content of Global Offset Table section. 22083fe401a5SEd Maste */ 22093fe401a5SEd Maste static void 22103fe401a5SEd Maste elf_print_got(struct elfdump *ed) 22113fe401a5SEd Maste { 22123fe401a5SEd Maste struct section *s; 22133fe401a5SEd Maste int i; 22143fe401a5SEd Maste 22153fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 22163fe401a5SEd Maste return; 22173fe401a5SEd Maste 22183fe401a5SEd Maste s = NULL; 22193fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 22203fe401a5SEd Maste s = &ed->sl[i]; 22213fe401a5SEd Maste if (s->name && !strncmp(s->name, ".got", 4) && 22223fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 22233fe401a5SEd Maste elf_print_got_section(ed, s); 22243fe401a5SEd Maste } 22253fe401a5SEd Maste } 22263fe401a5SEd Maste 22273fe401a5SEd Maste /* 22283fe401a5SEd Maste * Dump the content of .note.ABI-tag section. 22293fe401a5SEd Maste */ 22303fe401a5SEd Maste static void 22313fe401a5SEd Maste elf_print_note(struct elfdump *ed) 22323fe401a5SEd Maste { 22333fe401a5SEd Maste struct section *s; 22343fe401a5SEd Maste Elf_Data *data; 22353fe401a5SEd Maste Elf_Note *en; 22363fe401a5SEd Maste uint32_t namesz; 22373fe401a5SEd Maste uint32_t descsz; 22383fe401a5SEd Maste uint32_t desc; 22393fe401a5SEd Maste size_t count; 22403fe401a5SEd Maste int elferr, i; 22413fe401a5SEd Maste char *src, idx[10]; 22423fe401a5SEd Maste 22433fe401a5SEd Maste s = NULL; 22443fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 22453fe401a5SEd Maste s = &ed->sl[i]; 22463fe401a5SEd Maste if (s->type == SHT_NOTE && s->name && 22473fe401a5SEd Maste !strcmp(s->name, ".note.ABI-tag") && 22483fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 22493fe401a5SEd Maste break; 22503fe401a5SEd Maste } 22513fe401a5SEd Maste if ((size_t)i >= ed->shnum) 22523fe401a5SEd Maste return; 22533fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 22543fe401a5SEd Maste PRT("\nNote Section: %s\n", s->name); 22553fe401a5SEd Maste else 22563fe401a5SEd Maste PRT("\nnote (%s):\n", s->name); 22573fe401a5SEd Maste (void) elf_errno(); 22583fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 22593fe401a5SEd Maste elferr = elf_errno(); 22603fe401a5SEd Maste if (elferr != 0) 22613fe401a5SEd Maste warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 22623fe401a5SEd Maste return; 22633fe401a5SEd Maste } 22643fe401a5SEd Maste src = data->d_buf; 22653fe401a5SEd Maste count = data->d_size; 22663fe401a5SEd Maste while (count > sizeof(Elf_Note)) { 22673fe401a5SEd Maste en = (Elf_Note *) (uintptr_t) src; 22683fe401a5SEd Maste namesz = en->n_namesz; 22693fe401a5SEd Maste descsz = en->n_descsz; 22703fe401a5SEd Maste src += sizeof(Elf_Note); 22713fe401a5SEd Maste count -= sizeof(Elf_Note); 22723fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 22733fe401a5SEd Maste PRT("\n type %#x\n", en->n_type); 22743fe401a5SEd Maste PRT(" namesz %#x:\n", en->n_namesz); 22753fe401a5SEd Maste PRT("%s\n", src); 22763fe401a5SEd Maste } else 22773fe401a5SEd Maste PRT("\t%s ", src); 22783fe401a5SEd Maste src += roundup2(namesz, 4); 22793fe401a5SEd Maste count -= roundup2(namesz, 4); 22803fe401a5SEd Maste 22813fe401a5SEd Maste /* 22823fe401a5SEd Maste * Note that we dump the whole desc part if we're in 22833fe401a5SEd Maste * "Solaris mode", while in the normal mode, we only look 22843fe401a5SEd Maste * at the first 4 bytes (a 32bit word) of the desc, i.e, 22853fe401a5SEd Maste * we assume that it's always a FreeBSD version number. 22863fe401a5SEd Maste */ 22873fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 22883fe401a5SEd Maste PRT(" descsz %#x:", en->n_descsz); 22893fe401a5SEd Maste for (i = 0; (uint32_t)i < descsz; i++) { 22903fe401a5SEd Maste if ((i & 0xF) == 0) { 22913fe401a5SEd Maste snprintf(idx, sizeof(idx), "desc[%d]", 22923fe401a5SEd Maste i); 22933fe401a5SEd Maste PRT("\n %-9s", idx); 22943fe401a5SEd Maste } else if ((i & 0x3) == 0) 22953fe401a5SEd Maste PRT(" "); 22963fe401a5SEd Maste PRT(" %2.2x", src[i]); 22973fe401a5SEd Maste } 22983fe401a5SEd Maste PRT("\n"); 22993fe401a5SEd Maste } else { 23003fe401a5SEd Maste if (ed->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) 23013fe401a5SEd Maste desc = be32dec(src); 23023fe401a5SEd Maste else 23033fe401a5SEd Maste desc = le32dec(src); 23043fe401a5SEd Maste PRT("%d\n", desc); 23053fe401a5SEd Maste } 23063fe401a5SEd Maste src += roundup2(descsz, 4); 23073fe401a5SEd Maste count -= roundup2(descsz, 4); 23083fe401a5SEd Maste } 23093fe401a5SEd Maste } 23103fe401a5SEd Maste 23113fe401a5SEd Maste /* 23123fe401a5SEd Maste * Dump a hash table. 23133fe401a5SEd Maste */ 23143fe401a5SEd Maste static void 23153fe401a5SEd Maste elf_print_svr4_hash(struct elfdump *ed, struct section *s) 23163fe401a5SEd Maste { 23173fe401a5SEd Maste Elf_Data *data; 23183fe401a5SEd Maste uint32_t *buf; 23193fe401a5SEd Maste uint32_t *bucket, *chain; 23203fe401a5SEd Maste uint32_t nbucket, nchain; 23213fe401a5SEd Maste uint32_t *bl, *c, maxl, total; 23223fe401a5SEd Maste int i, j, first, elferr; 23233fe401a5SEd Maste char idx[10]; 23243fe401a5SEd Maste 23253fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 23263fe401a5SEd Maste PRT("\nHash Section: %s\n", s->name); 23273fe401a5SEd Maste else 23283fe401a5SEd Maste PRT("\nhash table (%s):\n", s->name); 23293fe401a5SEd Maste (void) elf_errno(); 23303fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 23313fe401a5SEd Maste elferr = elf_errno(); 23323fe401a5SEd Maste if (elferr != 0) 23333fe401a5SEd Maste warnx("elf_getdata failed: %s", 23343fe401a5SEd Maste elf_errmsg(elferr)); 23353fe401a5SEd Maste return; 23363fe401a5SEd Maste } 23373fe401a5SEd Maste if (data->d_size < 2 * sizeof(uint32_t)) { 23383fe401a5SEd Maste warnx(".hash section too small"); 23393fe401a5SEd Maste return; 23403fe401a5SEd Maste } 23413fe401a5SEd Maste buf = data->d_buf; 23423fe401a5SEd Maste nbucket = buf[0]; 23433fe401a5SEd Maste nchain = buf[1]; 23443fe401a5SEd Maste if (nbucket <= 0 || nchain <= 0) { 23453fe401a5SEd Maste warnx("Malformed .hash section"); 23463fe401a5SEd Maste return; 23473fe401a5SEd Maste } 23483fe401a5SEd Maste if (data->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) { 23493fe401a5SEd Maste warnx("Malformed .hash section"); 23503fe401a5SEd Maste return; 23513fe401a5SEd Maste } 23523fe401a5SEd Maste bucket = &buf[2]; 23533fe401a5SEd Maste chain = &buf[2 + nbucket]; 23543fe401a5SEd Maste 23553fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 23563fe401a5SEd Maste maxl = 0; 23573fe401a5SEd Maste if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 23583fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 23593fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 23603fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; 23613fe401a5SEd Maste j = chain[j]) 23623fe401a5SEd Maste if (++bl[i] > maxl) 23633fe401a5SEd Maste maxl = bl[i]; 23643fe401a5SEd Maste if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 23653fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 23663fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 23673fe401a5SEd Maste c[bl[i]]++; 23683fe401a5SEd Maste PRT(" bucket symndx name\n"); 23693fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) { 23703fe401a5SEd Maste first = 1; 23713fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; 23723fe401a5SEd Maste j = chain[j]) { 23733fe401a5SEd Maste if (first) { 23743fe401a5SEd Maste PRT("%10d ", i); 23753fe401a5SEd Maste first = 0; 23763fe401a5SEd Maste } else 23773fe401a5SEd Maste PRT(" "); 23783fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j); 23793fe401a5SEd Maste PRT("%-10s ", idx); 23803fe401a5SEd Maste PRT("%s\n", get_symbol_name(ed, s->link, j)); 23813fe401a5SEd Maste } 23823fe401a5SEd Maste } 23833fe401a5SEd Maste PRT("\n"); 23843fe401a5SEd Maste total = 0; 23853fe401a5SEd Maste for (i = 0; (uint32_t)i <= maxl; i++) { 23863fe401a5SEd Maste total += c[i] * i; 23873fe401a5SEd Maste PRT("%10u buckets contain %8d symbols\n", c[i], i); 23883fe401a5SEd Maste } 23893fe401a5SEd Maste PRT("%10u buckets %8u symbols (globals)\n", nbucket, 23903fe401a5SEd Maste total); 23913fe401a5SEd Maste } else { 23923fe401a5SEd Maste PRT("\nnbucket: %u\n", nbucket); 23933fe401a5SEd Maste PRT("nchain: %u\n\n", nchain); 23943fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 23953fe401a5SEd Maste PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 23963fe401a5SEd Maste for (i = 0; (uint32_t)i < nchain; i++) 23973fe401a5SEd Maste PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 23983fe401a5SEd Maste } 23993fe401a5SEd Maste } 24003fe401a5SEd Maste 24013fe401a5SEd Maste /* 24023fe401a5SEd Maste * Dump a 64bit hash table. 24033fe401a5SEd Maste */ 24043fe401a5SEd Maste static void 24053fe401a5SEd Maste elf_print_svr4_hash64(struct elfdump *ed, struct section *s) 24063fe401a5SEd Maste { 24073fe401a5SEd Maste Elf_Data *data, dst; 24083fe401a5SEd Maste uint64_t *buf; 24093fe401a5SEd Maste uint64_t *bucket, *chain; 24103fe401a5SEd Maste uint64_t nbucket, nchain; 24113fe401a5SEd Maste uint64_t *bl, *c, maxl, total; 24123fe401a5SEd Maste int i, j, elferr, first; 24133fe401a5SEd Maste char idx[10]; 24143fe401a5SEd Maste 24153fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 24163fe401a5SEd Maste PRT("\nHash Section: %s\n", s->name); 24173fe401a5SEd Maste else 24183fe401a5SEd Maste PRT("\nhash table (%s):\n", s->name); 24193fe401a5SEd Maste 24203fe401a5SEd Maste /* 24213fe401a5SEd Maste * ALPHA uses 64-bit hash entries. Since libelf assumes that 24223fe401a5SEd Maste * .hash section contains only 32-bit entry, an explicit 24233fe401a5SEd Maste * gelf_xlatetom is needed here. 24243fe401a5SEd Maste */ 24253fe401a5SEd Maste (void) elf_errno(); 24263fe401a5SEd Maste if ((data = elf_rawdata(s->scn, NULL)) == NULL) { 24273fe401a5SEd Maste elferr = elf_errno(); 24283fe401a5SEd Maste if (elferr != 0) 24293fe401a5SEd Maste warnx("elf_rawdata failed: %s", 24303fe401a5SEd Maste elf_errmsg(elferr)); 24313fe401a5SEd Maste return; 24323fe401a5SEd Maste } 24333fe401a5SEd Maste data->d_type = ELF_T_XWORD; 24343fe401a5SEd Maste memcpy(&dst, data, sizeof(Elf_Data)); 24353fe401a5SEd Maste if (gelf_xlatetom(ed->elf, &dst, data, 24363fe401a5SEd Maste ed->ehdr.e_ident[EI_DATA]) != &dst) { 24373fe401a5SEd Maste warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 24383fe401a5SEd Maste return; 24393fe401a5SEd Maste } 24403fe401a5SEd Maste if (dst.d_size < 2 * sizeof(uint64_t)) { 24413fe401a5SEd Maste warnx(".hash section too small"); 24423fe401a5SEd Maste return; 24433fe401a5SEd Maste } 24443fe401a5SEd Maste buf = dst.d_buf; 24453fe401a5SEd Maste nbucket = buf[0]; 24463fe401a5SEd Maste nchain = buf[1]; 24473fe401a5SEd Maste if (nbucket <= 0 || nchain <= 0) { 24483fe401a5SEd Maste warnx("Malformed .hash section"); 24493fe401a5SEd Maste return; 24503fe401a5SEd Maste } 24513fe401a5SEd Maste if (dst.d_size != (nbucket + nchain + 2) * sizeof(uint64_t)) { 24523fe401a5SEd Maste warnx("Malformed .hash section"); 24533fe401a5SEd Maste return; 24543fe401a5SEd Maste } 24553fe401a5SEd Maste bucket = &buf[2]; 24563fe401a5SEd Maste chain = &buf[2 + nbucket]; 24573fe401a5SEd Maste 24583fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 24593fe401a5SEd Maste maxl = 0; 24603fe401a5SEd Maste if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 24613fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 24623fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) 24633fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint64_t)j < nchain; 24643fe401a5SEd Maste j = chain[j]) 24653fe401a5SEd Maste if (++bl[i] > maxl) 24663fe401a5SEd Maste maxl = bl[i]; 24673fe401a5SEd Maste if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 24683fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 24693fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) 24703fe401a5SEd Maste c[bl[i]]++; 24713fe401a5SEd Maste PRT(" bucket symndx name\n"); 24723fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) { 24733fe401a5SEd Maste first = 1; 24743fe401a5SEd Maste for (j = bucket[i]; j > 0 && (uint64_t)j < nchain; 24753fe401a5SEd Maste j = chain[j]) { 24763fe401a5SEd Maste if (first) { 24773fe401a5SEd Maste PRT("%10d ", i); 24783fe401a5SEd Maste first = 0; 24793fe401a5SEd Maste } else 24803fe401a5SEd Maste PRT(" "); 24813fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j); 24823fe401a5SEd Maste PRT("%-10s ", idx); 24833fe401a5SEd Maste PRT("%s\n", get_symbol_name(ed, s->link, j)); 24843fe401a5SEd Maste } 24853fe401a5SEd Maste } 24863fe401a5SEd Maste PRT("\n"); 24873fe401a5SEd Maste total = 0; 24883fe401a5SEd Maste for (i = 0; (uint64_t)i <= maxl; i++) { 24893fe401a5SEd Maste total += c[i] * i; 24903fe401a5SEd Maste PRT("%10ju buckets contain %8d symbols\n", 24913fe401a5SEd Maste (uintmax_t)c[i], i); 24923fe401a5SEd Maste } 24933fe401a5SEd Maste PRT("%10ju buckets %8ju symbols (globals)\n", 24943fe401a5SEd Maste (uintmax_t)nbucket, (uintmax_t)total); 24953fe401a5SEd Maste } else { 24963fe401a5SEd Maste PRT("\nnbucket: %ju\n", (uintmax_t)nbucket); 24973fe401a5SEd Maste PRT("nchain: %ju\n\n", (uintmax_t)nchain); 24983fe401a5SEd Maste for (i = 0; (uint64_t)i < nbucket; i++) 24993fe401a5SEd Maste PRT("bucket[%d]:\n\t%ju\n\n", i, (uintmax_t)bucket[i]); 25003fe401a5SEd Maste for (i = 0; (uint64_t)i < nchain; i++) 25013fe401a5SEd Maste PRT("chain[%d]:\n\t%ju\n\n", i, (uintmax_t)chain[i]); 25023fe401a5SEd Maste } 25033fe401a5SEd Maste 25043fe401a5SEd Maste } 25053fe401a5SEd Maste 25063fe401a5SEd Maste /* 25073fe401a5SEd Maste * Dump a GNU hash table. 25083fe401a5SEd Maste */ 25093fe401a5SEd Maste static void 25103fe401a5SEd Maste elf_print_gnu_hash(struct elfdump *ed, struct section *s) 25113fe401a5SEd Maste { 25123fe401a5SEd Maste struct section *ds; 25133fe401a5SEd Maste Elf_Data *data; 25143fe401a5SEd Maste uint32_t *buf; 25153fe401a5SEd Maste uint32_t *bucket, *chain; 25163fe401a5SEd Maste uint32_t nbucket, nchain, symndx, maskwords, shift2; 25173fe401a5SEd Maste uint32_t *bl, *c, maxl, total; 25183fe401a5SEd Maste int i, j, first, elferr, dynsymcount; 25193fe401a5SEd Maste char idx[10]; 25203fe401a5SEd Maste 25213fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 25223fe401a5SEd Maste PRT("\nGNU Hash Section: %s\n", s->name); 25233fe401a5SEd Maste else 25243fe401a5SEd Maste PRT("\ngnu hash table (%s):\n", s->name); 25253fe401a5SEd Maste (void) elf_errno(); 25263fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 25273fe401a5SEd Maste elferr = elf_errno(); 25283fe401a5SEd Maste if (elferr != 0) 25293fe401a5SEd Maste warnx("elf_getdata failed: %s", 25303fe401a5SEd Maste elf_errmsg(elferr)); 25313fe401a5SEd Maste return; 25323fe401a5SEd Maste } 25333fe401a5SEd Maste if (data->d_size < 4 * sizeof(uint32_t)) { 25343fe401a5SEd Maste warnx(".gnu.hash section too small"); 25353fe401a5SEd Maste return; 25363fe401a5SEd Maste } 25373fe401a5SEd Maste buf = data->d_buf; 25383fe401a5SEd Maste nbucket = buf[0]; 25393fe401a5SEd Maste symndx = buf[1]; 25403fe401a5SEd Maste maskwords = buf[2]; 25413fe401a5SEd Maste shift2 = buf[3]; 25423fe401a5SEd Maste buf += 4; 25433fe401a5SEd Maste ds = &ed->sl[s->link]; 2544*656f49f8SEd Maste if (!get_ent_count(ds, &dynsymcount)) 2545*656f49f8SEd Maste return; 25463fe401a5SEd Maste nchain = dynsymcount - symndx; 25473fe401a5SEd Maste if (data->d_size != 4 * sizeof(uint32_t) + maskwords * 25483fe401a5SEd Maste (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + 25493fe401a5SEd Maste (nbucket + nchain) * sizeof(uint32_t)) { 25503fe401a5SEd Maste warnx("Malformed .gnu.hash section"); 25513fe401a5SEd Maste return; 25523fe401a5SEd Maste } 25533fe401a5SEd Maste bucket = buf + (ed->ec == ELFCLASS32 ? maskwords : maskwords * 2); 25543fe401a5SEd Maste chain = bucket + nbucket; 25553fe401a5SEd Maste 25563fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 25573fe401a5SEd Maste maxl = 0; 25583fe401a5SEd Maste if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 25593fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 25603fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 25613fe401a5SEd Maste for (j = bucket[i]; 25623fe401a5SEd Maste j > 0 && (uint32_t)j - symndx < nchain; 25633fe401a5SEd Maste j++) { 25643fe401a5SEd Maste if (++bl[i] > maxl) 25653fe401a5SEd Maste maxl = bl[i]; 25663fe401a5SEd Maste if (chain[j - symndx] & 1) 25673fe401a5SEd Maste break; 25683fe401a5SEd Maste } 25693fe401a5SEd Maste if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 25703fe401a5SEd Maste err(EXIT_FAILURE, "calloc failed"); 25713fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 25723fe401a5SEd Maste c[bl[i]]++; 25733fe401a5SEd Maste PRT(" bucket symndx name\n"); 25743fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) { 25753fe401a5SEd Maste first = 1; 25763fe401a5SEd Maste for (j = bucket[i]; 25773fe401a5SEd Maste j > 0 && (uint32_t)j - symndx < nchain; 25783fe401a5SEd Maste j++) { 25793fe401a5SEd Maste if (first) { 25803fe401a5SEd Maste PRT("%10d ", i); 25813fe401a5SEd Maste first = 0; 25823fe401a5SEd Maste } else 25833fe401a5SEd Maste PRT(" "); 25843fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", j ); 25853fe401a5SEd Maste PRT("%-10s ", idx); 25863fe401a5SEd Maste PRT("%s\n", get_symbol_name(ed, s->link, j)); 25873fe401a5SEd Maste if (chain[j - symndx] & 1) 25883fe401a5SEd Maste break; 25893fe401a5SEd Maste } 25903fe401a5SEd Maste } 25913fe401a5SEd Maste PRT("\n"); 25923fe401a5SEd Maste total = 0; 25933fe401a5SEd Maste for (i = 0; (uint32_t)i <= maxl; i++) { 25943fe401a5SEd Maste total += c[i] * i; 25953fe401a5SEd Maste PRT("%10u buckets contain %8d symbols\n", c[i], i); 25963fe401a5SEd Maste } 25973fe401a5SEd Maste PRT("%10u buckets %8u symbols (globals)\n", nbucket, 25983fe401a5SEd Maste total); 25993fe401a5SEd Maste } else { 26003fe401a5SEd Maste PRT("\nnbucket: %u\n", nbucket); 26013fe401a5SEd Maste PRT("symndx: %u\n", symndx); 26023fe401a5SEd Maste PRT("maskwords: %u\n", maskwords); 26033fe401a5SEd Maste PRT("shift2: %u\n", shift2); 26043fe401a5SEd Maste PRT("nchain: %u\n\n", nchain); 26053fe401a5SEd Maste for (i = 0; (uint32_t)i < nbucket; i++) 26063fe401a5SEd Maste PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 26073fe401a5SEd Maste for (i = 0; (uint32_t)i < nchain; i++) 26083fe401a5SEd Maste PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 26093fe401a5SEd Maste } 26103fe401a5SEd Maste } 26113fe401a5SEd Maste 26123fe401a5SEd Maste /* 26133fe401a5SEd Maste * Dump hash tables. 26143fe401a5SEd Maste */ 26153fe401a5SEd Maste static void 26163fe401a5SEd Maste elf_print_hash(struct elfdump *ed) 26173fe401a5SEd Maste { 26183fe401a5SEd Maste struct section *s; 26193fe401a5SEd Maste int i; 26203fe401a5SEd Maste 26213fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 26223fe401a5SEd Maste s = &ed->sl[i]; 26233fe401a5SEd Maste if ((s->type == SHT_HASH || s->type == SHT_GNU_HASH) && 26243fe401a5SEd Maste (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 26253fe401a5SEd Maste if (s->type == SHT_GNU_HASH) 26263fe401a5SEd Maste elf_print_gnu_hash(ed, s); 26273fe401a5SEd Maste else if (ed->ehdr.e_machine == EM_ALPHA && 26283fe401a5SEd Maste s->entsize == 8) 26293fe401a5SEd Maste elf_print_svr4_hash64(ed, s); 26303fe401a5SEd Maste else 26313fe401a5SEd Maste elf_print_svr4_hash(ed, s); 26323fe401a5SEd Maste } 26333fe401a5SEd Maste } 26343fe401a5SEd Maste } 26353fe401a5SEd Maste 26363fe401a5SEd Maste /* 26373fe401a5SEd Maste * Dump the content of a Version Definition(SHT_SUNW_Verdef) Section. 26383fe401a5SEd Maste */ 26393fe401a5SEd Maste static void 26403fe401a5SEd Maste elf_print_verdef(struct elfdump *ed, struct section *s) 26413fe401a5SEd Maste { 26423fe401a5SEd Maste Elf_Data *data; 26433fe401a5SEd Maste Elf32_Verdef *vd; 26443fe401a5SEd Maste Elf32_Verdaux *vda; 26453fe401a5SEd Maste const char *str; 26463fe401a5SEd Maste char idx[10]; 26473fe401a5SEd Maste uint8_t *buf, *end, *buf2; 26483fe401a5SEd Maste int i, j, elferr, count; 26493fe401a5SEd Maste 26503fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 26513fe401a5SEd Maste PRT("Version Definition Section: %s\n", s->name); 26523fe401a5SEd Maste else 26533fe401a5SEd Maste PRT("\nversion definition section (%s):\n", s->name); 26543fe401a5SEd Maste (void) elf_errno(); 26553fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 26563fe401a5SEd Maste elferr = elf_errno(); 26573fe401a5SEd Maste if (elferr != 0) 26583fe401a5SEd Maste warnx("elf_getdata failed: %s", 26593fe401a5SEd Maste elf_errmsg(elferr)); 26603fe401a5SEd Maste return; 26613fe401a5SEd Maste } 26623fe401a5SEd Maste buf = data->d_buf; 26633fe401a5SEd Maste end = buf + data->d_size; 26643fe401a5SEd Maste i = 0; 26653fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 26663fe401a5SEd Maste PRT(" index version dependency\n"); 26673fe401a5SEd Maste while (buf + sizeof(Elf32_Verdef) <= end) { 26683fe401a5SEd Maste vd = (Elf32_Verdef *) (uintptr_t) buf; 26693fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 26703fe401a5SEd Maste snprintf(idx, sizeof(idx), "[%d]", vd->vd_ndx); 26713fe401a5SEd Maste PRT("%10s ", idx); 26723fe401a5SEd Maste } else { 26733fe401a5SEd Maste PRT("\nentry: %d\n", i++); 26743fe401a5SEd Maste PRT("\tvd_version: %u\n", vd->vd_version); 26753fe401a5SEd Maste PRT("\tvd_flags: %u\n", vd->vd_flags); 26763fe401a5SEd Maste PRT("\tvd_ndx: %u\n", vd->vd_ndx); 26773fe401a5SEd Maste PRT("\tvd_cnt: %u\n", vd->vd_cnt); 26783fe401a5SEd Maste PRT("\tvd_hash: %u\n", vd->vd_hash); 26793fe401a5SEd Maste PRT("\tvd_aux: %u\n", vd->vd_aux); 26803fe401a5SEd Maste PRT("\tvd_next: %u\n\n", vd->vd_next); 26813fe401a5SEd Maste } 26823fe401a5SEd Maste buf2 = buf + vd->vd_aux; 26833fe401a5SEd Maste j = 0; 26843fe401a5SEd Maste count = 0; 26853fe401a5SEd Maste while (buf2 + sizeof(Elf32_Verdaux) <= end && j < vd->vd_cnt) { 26863fe401a5SEd Maste vda = (Elf32_Verdaux *) (uintptr_t) buf2; 26873fe401a5SEd Maste str = get_string(ed, s->link, vda->vda_name); 26883fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 26893fe401a5SEd Maste if (count == 0) 26903fe401a5SEd Maste PRT("%-26.26s", str); 26913fe401a5SEd Maste else if (count == 1) 26923fe401a5SEd Maste PRT(" %-20.20s", str); 26933fe401a5SEd Maste else { 26943fe401a5SEd Maste PRT("\n%40.40s", ""); 26953fe401a5SEd Maste PRT("%s", str); 26963fe401a5SEd Maste } 26973fe401a5SEd Maste } else { 26983fe401a5SEd Maste PRT("\t\tvda: %d\n", j++); 26993fe401a5SEd Maste PRT("\t\t\tvda_name: %s\n", str); 27003fe401a5SEd Maste PRT("\t\t\tvda_next: %u\n", vda->vda_next); 27013fe401a5SEd Maste } 27023fe401a5SEd Maste if (vda->vda_next == 0) { 27033fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 27043fe401a5SEd Maste if (vd->vd_flags & VER_FLG_BASE) { 27053fe401a5SEd Maste if (count == 0) 27063fe401a5SEd Maste PRT("%-20.20s", ""); 27073fe401a5SEd Maste PRT("%s", "[ BASE ]"); 27083fe401a5SEd Maste } 27093fe401a5SEd Maste PRT("\n"); 27103fe401a5SEd Maste } 27113fe401a5SEd Maste break; 27123fe401a5SEd Maste } 27133fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 27143fe401a5SEd Maste count++; 27153fe401a5SEd Maste buf2 += vda->vda_next; 27163fe401a5SEd Maste } 27173fe401a5SEd Maste if (vd->vd_next == 0) 27183fe401a5SEd Maste break; 27193fe401a5SEd Maste buf += vd->vd_next; 27203fe401a5SEd Maste } 27213fe401a5SEd Maste } 27223fe401a5SEd Maste 27233fe401a5SEd Maste /* 27243fe401a5SEd Maste * Dump the content of a Version Needed(SHT_SUNW_Verneed) Section. 27253fe401a5SEd Maste */ 27263fe401a5SEd Maste static void 27273fe401a5SEd Maste elf_print_verneed(struct elfdump *ed, struct section *s) 27283fe401a5SEd Maste { 27293fe401a5SEd Maste Elf_Data *data; 27303fe401a5SEd Maste Elf32_Verneed *vn; 27313fe401a5SEd Maste Elf32_Vernaux *vna; 27323fe401a5SEd Maste uint8_t *buf, *end, *buf2; 27333fe401a5SEd Maste int i, j, elferr, first; 27343fe401a5SEd Maste 27353fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 27363fe401a5SEd Maste PRT("\nVersion Needed Section: %s\n", s->name); 27373fe401a5SEd Maste else 27383fe401a5SEd Maste PRT("\nversion need section (%s):\n", s->name); 27393fe401a5SEd Maste (void) elf_errno(); 27403fe401a5SEd Maste if ((data = elf_getdata(s->scn, NULL)) == NULL) { 27413fe401a5SEd Maste elferr = elf_errno(); 27423fe401a5SEd Maste if (elferr != 0) 27433fe401a5SEd Maste warnx("elf_getdata failed: %s", 27443fe401a5SEd Maste elf_errmsg(elferr)); 27453fe401a5SEd Maste return; 27463fe401a5SEd Maste } 27473fe401a5SEd Maste buf = data->d_buf; 27483fe401a5SEd Maste end = buf + data->d_size; 27493fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 27503fe401a5SEd Maste PRT(" file version\n"); 27513fe401a5SEd Maste i = 0; 27523fe401a5SEd Maste while (buf + sizeof(Elf32_Verneed) <= end) { 27533fe401a5SEd Maste vn = (Elf32_Verneed *) (uintptr_t) buf; 27543fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) 27553fe401a5SEd Maste PRT(" %-26.26s ", 27563fe401a5SEd Maste get_string(ed, s->link, vn->vn_file)); 27573fe401a5SEd Maste else { 27583fe401a5SEd Maste PRT("\nentry: %d\n", i++); 27593fe401a5SEd Maste PRT("\tvn_version: %u\n", vn->vn_version); 27603fe401a5SEd Maste PRT("\tvn_cnt: %u\n", vn->vn_cnt); 27613fe401a5SEd Maste PRT("\tvn_file: %s\n", 27623fe401a5SEd Maste get_string(ed, s->link, vn->vn_file)); 27633fe401a5SEd Maste PRT("\tvn_aux: %u\n", vn->vn_aux); 27643fe401a5SEd Maste PRT("\tvn_next: %u\n\n", vn->vn_next); 27653fe401a5SEd Maste } 27663fe401a5SEd Maste buf2 = buf + vn->vn_aux; 27673fe401a5SEd Maste j = 0; 27683fe401a5SEd Maste first = 1; 27693fe401a5SEd Maste while (buf2 + sizeof(Elf32_Vernaux) <= end && j < vn->vn_cnt) { 27703fe401a5SEd Maste vna = (Elf32_Vernaux *) (uintptr_t) buf2; 27713fe401a5SEd Maste if (ed->flags & SOLARIS_FMT) { 27723fe401a5SEd Maste if (!first) 27733fe401a5SEd Maste PRT("%40.40s", ""); 27743fe401a5SEd Maste else 27753fe401a5SEd Maste first = 0; 27763fe401a5SEd Maste PRT("%s\n", get_string(ed, s->link, 27773fe401a5SEd Maste vna->vna_name)); 27783fe401a5SEd Maste } else { 27793fe401a5SEd Maste PRT("\t\tvna: %d\n", j++); 27803fe401a5SEd Maste PRT("\t\t\tvna_hash: %u\n", vna->vna_hash); 27813fe401a5SEd Maste PRT("\t\t\tvna_flags: %u\n", vna->vna_flags); 27823fe401a5SEd Maste PRT("\t\t\tvna_other: %u\n", vna->vna_other); 27833fe401a5SEd Maste PRT("\t\t\tvna_name: %s\n", 27843fe401a5SEd Maste get_string(ed, s->link, vna->vna_name)); 27853fe401a5SEd Maste PRT("\t\t\tvna_next: %u\n", vna->vna_next); 27863fe401a5SEd Maste } 27873fe401a5SEd Maste if (vna->vna_next == 0) 27883fe401a5SEd Maste break; 27893fe401a5SEd Maste buf2 += vna->vna_next; 27903fe401a5SEd Maste } 27913fe401a5SEd Maste if (vn->vn_next == 0) 27923fe401a5SEd Maste break; 27933fe401a5SEd Maste buf += vn->vn_next; 27943fe401a5SEd Maste } 27953fe401a5SEd Maste } 27963fe401a5SEd Maste 27973fe401a5SEd Maste /* 27983fe401a5SEd Maste * Dump the symbol-versioning sections. 27993fe401a5SEd Maste */ 28003fe401a5SEd Maste static void 28013fe401a5SEd Maste elf_print_symver(struct elfdump *ed) 28023fe401a5SEd Maste { 28033fe401a5SEd Maste struct section *s; 28043fe401a5SEd Maste int i; 28053fe401a5SEd Maste 28063fe401a5SEd Maste for (i = 0; (size_t)i < ed->shnum; i++) { 28073fe401a5SEd Maste s = &ed->sl[i]; 28083fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl) && !find_name(ed, s->name)) 28093fe401a5SEd Maste continue; 28103fe401a5SEd Maste if (s->type == SHT_SUNW_verdef) 28113fe401a5SEd Maste elf_print_verdef(ed, s); 28123fe401a5SEd Maste if (s->type == SHT_SUNW_verneed) 28133fe401a5SEd Maste elf_print_verneed(ed, s); 28143fe401a5SEd Maste } 28153fe401a5SEd Maste } 28163fe401a5SEd Maste 28173fe401a5SEd Maste /* 28183fe401a5SEd Maste * Dump the ELF checksum. See gelf_checksum(3) for details. 28193fe401a5SEd Maste */ 28203fe401a5SEd Maste static void 28213fe401a5SEd Maste elf_print_checksum(struct elfdump *ed) 28223fe401a5SEd Maste { 28233fe401a5SEd Maste 28243fe401a5SEd Maste if (!STAILQ_EMPTY(&ed->snl)) 28253fe401a5SEd Maste return; 28263fe401a5SEd Maste 28273fe401a5SEd Maste PRT("\nelf checksum: %#lx\n", gelf_checksum(ed->elf)); 28283fe401a5SEd Maste } 28293fe401a5SEd Maste 28303fe401a5SEd Maste #define USAGE_MESSAGE "\ 28313fe401a5SEd Maste Usage: %s [options] file...\n\ 28323fe401a5SEd Maste Display information about ELF objects and ar(1) archives.\n\n\ 28333fe401a5SEd Maste Options:\n\ 28343fe401a5SEd Maste -a Show all information.\n\ 28353fe401a5SEd Maste -c Show shared headers.\n\ 28363fe401a5SEd Maste -d Show dynamic symbols.\n\ 28373fe401a5SEd Maste -e Show the ELF header.\n\ 28383fe401a5SEd Maste -G Show the GOT.\n\ 28393fe401a5SEd Maste -H | --help Show a usage message and exit.\n\ 28403fe401a5SEd Maste -h Show hash values.\n\ 28413fe401a5SEd Maste -i Show the dynamic interpreter.\n\ 28423fe401a5SEd Maste -k Show the ELF checksum.\n\ 28433fe401a5SEd Maste -n Show the contents of note sections.\n\ 28443fe401a5SEd Maste -N NAME Show the section named \"NAME\".\n\ 28453fe401a5SEd Maste -p Show the program header.\n\ 28463fe401a5SEd Maste -r Show relocations.\n\ 28473fe401a5SEd Maste -s Show the symbol table.\n\ 28483fe401a5SEd Maste -S Use the Solaris elfdump format.\n\ 28493fe401a5SEd Maste -v Show symbol-versioning information.\n\ 28503fe401a5SEd Maste -V | --version Print a version identifier and exit.\n\ 28513fe401a5SEd Maste -w FILE Write output to \"FILE\".\n" 28523fe401a5SEd Maste 28533fe401a5SEd Maste static void 28543fe401a5SEd Maste usage(void) 28553fe401a5SEd Maste { 28563fe401a5SEd Maste fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 28573fe401a5SEd Maste exit(EXIT_FAILURE); 28583fe401a5SEd Maste } 2859