19ee7876kaiw/*- 29ee7876kaiw * Copyright (c) 2007-2012 Kai Wang 39ee7876kaiw * Copyright (c) 2003 David O'Brien. All rights reserved. 49ee7876kaiw * Copyright (c) 2001 Jake Burkholder 59ee7876kaiw * All rights reserved. 69ee7876kaiw * 79ee7876kaiw * Redistribution and use in source and binary forms, with or without 89ee7876kaiw * modification, are permitted provided that the following conditions 99ee7876kaiw * are met: 109ee7876kaiw * 1. Redistributions of source code must retain the above copyright 119ee7876kaiw * notice, this list of conditions and the following disclaimer. 129ee7876kaiw * 2. Redistributions in binary form must reproduce the above copyright 139ee7876kaiw * notice, this list of conditions and the following disclaimer in the 149ee7876kaiw * documentation and/or other materials provided with the distribution. 159ee7876kaiw * 169ee7876kaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 179ee7876kaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 189ee7876kaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 199ee7876kaiw * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 209ee7876kaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 219ee7876kaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 229ee7876kaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 239ee7876kaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 249ee7876kaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 259ee7876kaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 269ee7876kaiw * SUCH DAMAGE. 279ee7876kaiw */ 289ee7876kaiw 299ee7876kaiw#include <sys/param.h> 309ee7876kaiw#include <sys/queue.h> 319ee7876kaiw#include <sys/stat.h> 329ee7876kaiw 339ee7876kaiw#include <ar.h> 349ee7876kaiw#include <assert.h> 359ee7876kaiw#include <err.h> 369ee7876kaiw#include <fcntl.h> 379ee7876kaiw#include <gelf.h> 389ee7876kaiw#include <getopt.h> 399ee7876kaiw#include <libelftc.h> 409ee7876kaiw#include <inttypes.h> 419ee7876kaiw#include <stdio.h> 429ee7876kaiw#include <stdlib.h> 439ee7876kaiw#include <string.h> 449ee7876kaiw#include <unistd.h> 459ee7876kaiw 469ee7876kaiw#ifdef USE_LIBARCHIVE_AR 479ee7876kaiw#include <archive.h> 489ee7876kaiw#include <archive_entry.h> 499ee7876kaiw#endif 509ee7876kaiw 519ee7876kaiw#include "_elftc.h" 529ee7876kaiw 53061ef1femasteELFTC_VCSID("$Id: elfdump.c 3762 2019-06-28 21:06:24Z emaste $"); 549ee7876kaiw 559ee7876kaiw#if defined(ELFTC_NEED_ELF_NOTE_DEFINITION) 569ee7876kaiw#include "native-elf-format.h" 579ee7876kaiw#if ELFTC_CLASS == ELFCLASS32 589ee7876kaiwtypedef Elf32_Nhdr Elf_Note; 599ee7876kaiw#else 609ee7876kaiwtypedef Elf64_Nhdr Elf_Note; 619ee7876kaiw#endif 629ee7876kaiw#endif 639ee7876kaiw 649ee7876kaiw/* elfdump(1) options. */ 659ee7876kaiw#define ED_DYN (1<<0) 669ee7876kaiw#define ED_EHDR (1<<1) 679ee7876kaiw#define ED_GOT (1<<2) 689ee7876kaiw#define ED_HASH (1<<3) 699ee7876kaiw#define ED_INTERP (1<<4) 709ee7876kaiw#define ED_NOTE (1<<5) 719ee7876kaiw#define ED_PHDR (1<<6) 729ee7876kaiw#define ED_REL (1<<7) 739ee7876kaiw#define ED_SHDR (1<<8) 749ee7876kaiw#define ED_SYMTAB (1<<9) 759ee7876kaiw#define ED_SYMVER (1<<10) 769ee7876kaiw#define ED_CHECKSUM (1<<11) 779ee7876kaiw#define ED_ALL ((1<<12)-1) 789ee7876kaiw 799ee7876kaiw/* elfdump(1) run control flags. */ 809ee7876kaiw#define SOLARIS_FMT (1<<0) 819ee7876kaiw#define PRINT_FILENAME (1<<1) 829ee7876kaiw#define PRINT_ARSYM (1<<2) 839ee7876kaiw#define ONLY_ARSYM (1<<3) 849ee7876kaiw 859ee7876kaiw/* Convenient print macro. */ 869ee7876kaiw#define PRT(...) fprintf(ed->out, __VA_ARGS__) 879ee7876kaiw 889ee7876kaiw/* Internal data structure for sections. */ 899ee7876kaiwstruct section { 909ee7876kaiw const char *name; /* section name */ 919ee7876kaiw Elf_Scn *scn; /* section scn */ 929ee7876kaiw uint64_t off; /* section offset */ 939ee7876kaiw uint64_t sz; /* section size */ 949ee7876kaiw uint64_t entsize; /* section entsize */ 959ee7876kaiw uint64_t align; /* section alignment */ 969ee7876kaiw uint64_t type; /* section type */ 979ee7876kaiw uint64_t flags; /* section flags */ 989ee7876kaiw uint64_t addr; /* section virtual addr */ 999ee7876kaiw uint32_t link; /* section link ndx */ 1009ee7876kaiw uint32_t info; /* section info ndx */ 1019ee7876kaiw}; 1029ee7876kaiw 1039ee7876kaiwstruct spec_name { 1049ee7876kaiw const char *name; 1059ee7876kaiw STAILQ_ENTRY(spec_name) sn_list; 1069ee7876kaiw}; 1079ee7876kaiw 1089ee7876kaiw/* Structure encapsulates the global data for readelf(1). */ 1099ee7876kaiwstruct elfdump { 1109ee7876kaiw FILE *out; /* output redirection. */ 1119ee7876kaiw const char *filename; /* current processing file. */ 1129ee7876kaiw const char *archive; /* archive name */ 1139ee7876kaiw int options; /* command line options. */ 1149ee7876kaiw int flags; /* run control flags. */ 1159ee7876kaiw Elf *elf; /* underlying ELF descriptor. */ 1169ee7876kaiw#ifndef USE_LIBARCHIVE_AR 1179ee7876kaiw Elf *ar; /* ar(1) archive descriptor. */ 1189ee7876kaiw#endif 1199ee7876kaiw GElf_Ehdr ehdr; /* ELF header. */ 1209ee7876kaiw int ec; /* ELF class. */ 1219ee7876kaiw size_t shnum; /* #sections. */ 1229ee7876kaiw struct section *sl; /* list of sections. */ 1239ee7876kaiw STAILQ_HEAD(, spec_name) snl; /* list of names specified by -N. */ 1249ee7876kaiw}; 1259ee7876kaiw 1269ee7876kaiw/* Relocation entry. */ 1279ee7876kaiwstruct rel_entry { 1289ee7876kaiw union { 1299ee7876kaiw GElf_Rel rel; 1309ee7876kaiw GElf_Rela rela; 1319ee7876kaiw } u_r; 1329ee7876kaiw const char *symn; 1339ee7876kaiw uint32_t type; 1349ee7876kaiw}; 1359ee7876kaiw 1369ee7876kaiw#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS) 1379ee7876kaiwstatic __inline uint32_t 1389ee7876kaiwbe32dec(const void *pp) 1399ee7876kaiw{ 1409ee7876kaiw unsigned char const *p = (unsigned char const *)pp; 1419ee7876kaiw 1429ee7876kaiw return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); 1439ee7876kaiw} 1449ee7876kaiw 1459ee7876kaiwstatic __inline uint32_t 1469ee7876kaiwle32dec(const void *pp) 1479ee7876kaiw{ 1489ee7876kaiw unsigned char const *p = (unsigned char const *)pp; 1499ee7876kaiw 1509ee7876kaiw return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); 1519ee7876kaiw} 1529ee7876kaiw#endif 1539ee7876kaiw 1549ee7876kaiw/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 1559ee7876kaiwstatic const char * 1569ee7876kaiwd_tags(uint64_t tag) 1579ee7876kaiw{ 15885217deemaste static char unknown_buf[64]; 15985217deemaste 1609ee7876kaiw switch (tag) { 16185217deemaste case DT_NULL: return "DT_NULL"; 16285217deemaste case DT_NEEDED: return "DT_NEEDED"; 16385217deemaste case DT_PLTRELSZ: return "DT_PLTRELSZ"; 16485217deemaste case DT_PLTGOT: return "DT_PLTGOT"; 16585217deemaste case DT_HASH: return "DT_HASH"; 16685217deemaste case DT_STRTAB: return "DT_STRTAB"; 16785217deemaste case DT_SYMTAB: return "DT_SYMTAB"; 16885217deemaste case DT_RELA: return "DT_RELA"; 16985217deemaste case DT_RELASZ: return "DT_RELASZ"; 17085217deemaste case DT_RELAENT: return "DT_RELAENT"; 17185217deemaste case DT_STRSZ: return "DT_STRSZ"; 17285217deemaste case DT_SYMENT: return "DT_SYMENT"; 17385217deemaste case DT_INIT: return "DT_INIT"; 17485217deemaste case DT_FINI: return "DT_FINI"; 17585217deemaste case DT_SONAME: return "DT_SONAME"; 17685217deemaste case DT_RPATH: return "DT_RPATH"; 17785217deemaste case DT_SYMBOLIC: return "DT_SYMBOLIC"; 17885217deemaste case DT_REL: return "DT_REL"; 17985217deemaste case DT_RELSZ: return "DT_RELSZ"; 18085217deemaste case DT_RELENT: return "DT_RELENT"; 18185217deemaste case DT_PLTREL: return "DT_PLTREL"; 18285217deemaste case DT_DEBUG: return "DT_DEBUG"; 18385217deemaste case DT_TEXTREL: return "DT_TEXTREL"; 18485217deemaste case DT_JMPREL: return "DT_JMPREL"; 18585217deemaste case DT_BIND_NOW: return "DT_BIND_NOW"; 18685217deemaste case DT_INIT_ARRAY: return "DT_INIT_ARRAY"; 18785217deemaste case DT_FINI_ARRAY: return "DT_FINI_ARRAY"; 18885217deemaste case DT_INIT_ARRAYSZ: return "DT_INIT_ARRAYSZ"; 18985217deemaste case DT_FINI_ARRAYSZ: return "DT_FINI_ARRAYSZ"; 19085217deemaste case DT_RUNPATH: return "DT_RUNPATH"; 19185217deemaste case DT_FLAGS: return "DT_FLAGS"; 19285217deemaste case DT_PREINIT_ARRAY: return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */ 19385217deemaste case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ"; 1949ee7876kaiw /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 19585217deemaste case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 19685217deemaste case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 19785217deemaste case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 19885217deemaste case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 19985217deemaste case DT_PLTPADSZ: return "DT_PLTPADSZ"; 20085217deemaste case DT_MOVEENT: return "DT_MOVEENT"; 20185217deemaste case DT_MOVESZ: return "DT_MOVESZ"; 20285217deemaste case 0x6ffffdfc: return "DT_FEATURE"; 20385217deemaste case DT_POSFLAG_1: return "DT_POSFLAG_1"; 20485217deemaste case DT_SYMINSZ: return "DT_SYMINSZ"; 20585217deemaste case DT_SYMINENT: return "DT_SYMINENT (DT_VALRNGHI)"; 20685217deemaste case DT_ADDRRNGLO: return "DT_ADDRRNGLO"; 20785217deemaste case DT_GNU_HASH: return "DT_GNU_HASH"; 20885217deemaste case 0x6ffffef8: return "DT_GNU_CONFLICT"; 20985217deemaste case 0x6ffffef9: return "DT_GNU_LIBLIST"; 21085217deemaste case 0x6ffffefa: return "DT_CONFIG"; 21185217deemaste case 0x6ffffefb: return "DT_DEPAUDIT"; 21285217deemaste case 0x6ffffefc: return "DT_AUDIT"; 21385217deemaste case 0x6ffffefd: return "DT_PLTPAD"; 21485217deemaste case 0x6ffffefe: return "DT_MOVETAB"; 21585217deemaste case DT_SYMINFO: return "DT_SYMINFO (DT_ADDRRNGHI)"; 21685217deemaste case DT_RELACOUNT: return "DT_RELACOUNT"; 21785217deemaste case DT_RELCOUNT: return "DT_RELCOUNT"; 21885217deemaste case DT_FLAGS_1: return "DT_FLAGS_1"; 21985217deemaste case DT_VERDEF: return "DT_VERDEF"; 22085217deemaste case DT_VERDEFNUM: return "DT_VERDEFNUM"; 22185217deemaste case DT_VERNEED: return "DT_VERNEED"; 22285217deemaste case DT_VERNEEDNUM: return "DT_VERNEEDNUM"; 22385217deemaste case 0x6ffffff0: return "DT_GNU_VERSYM"; 2249ee7876kaiw /* 0x70000000 - 0x7fffffff processor-specific semantics */ 22585217deemaste case 0x70000000: return "DT_IA_64_PLT_RESERVE"; 226c90b1e5emaste case DT_AUXILIARY: return "DT_AUXILIARY"; 227c90b1e5emaste case DT_USED: return "DT_USED"; 228c90b1e5emaste case DT_FILTER: return "DT_FILTER"; 2299ee7876kaiw } 23085217deemaste 23185217deemaste snprintf(unknown_buf, sizeof(unknown_buf), 23285217deemaste "<unknown: %#llx>", (unsigned long long)tag); 23385217deemaste return (unknown_buf); 2349ee7876kaiw} 2359ee7876kaiw 2369ee7876kaiwstatic const char * 2379ee7876kaiwe_machines(unsigned int mach) 2389ee7876kaiw{ 2399ee7876kaiw static char machdesc[64]; 2409ee7876kaiw 2419ee7876kaiw switch (mach) { 2429ee7876kaiw case EM_NONE: return "EM_NONE"; 2439ee7876kaiw case EM_M32: return "EM_M32"; 2449ee7876kaiw case EM_SPARC: return "EM_SPARC"; 2459ee7876kaiw case EM_386: return "EM_386"; 2469ee7876kaiw case EM_68K: return "EM_68K"; 2479ee7876kaiw case EM_88K: return "EM_88K"; 248b532da5emaste case EM_IAMCU: return "EM_IAMCU"; 2499ee7876kaiw case EM_860: return "EM_860"; 2509ee7876kaiw case EM_MIPS: return "EM_MIPS"; 2519ee7876kaiw case EM_PPC: return "EM_PPC"; 252f776db0emaste case EM_PPC64: return "EM_PPC64"; 2539ee7876kaiw case EM_ARM: return "EM_ARM"; 2549ee7876kaiw case EM_ALPHA: return "EM_ALPHA (legacy)"; 2559ee7876kaiw case EM_SPARCV9:return "EM_SPARCV9"; 2569ee7876kaiw case EM_IA_64: return "EM_IA_64"; 2579ee7876kaiw case EM_X86_64: return "EM_X86_64"; 258f776db0emaste case EM_AARCH64:return "EM_AARCH64"; 259f776db0emaste case EM_RISCV: return "EM_RISCV"; 2609ee7876kaiw } 2619ee7876kaiw snprintf(machdesc, sizeof(machdesc), 2629ee7876kaiw "(unknown machine) -- type 0x%x", mach); 2639ee7876kaiw return (machdesc); 2649ee7876kaiw} 2659ee7876kaiw 266db27a04emastestatic const char * 267db27a04emasteelf_type_str(unsigned int type) 268db27a04emaste{ 269db27a04emaste static char s_type[32]; 2709ee7876kaiw 271db27a04emaste switch (type) 272db27a04emaste { 273db27a04emaste case ET_NONE: return "ET_NONE"; 274db27a04emaste case ET_REL: return "ET_REL"; 275db27a04emaste case ET_EXEC: return "ET_EXEC"; 276db27a04emaste case ET_DYN: return "ET_DYN"; 277db27a04emaste case ET_CORE: return "ET_CORE"; 278db27a04emaste } 279db27a04emaste if (type >= ET_LOPROC) 280db27a04emaste snprintf(s_type, sizeof(s_type), "<proc: %#x>", type); 281db27a04emaste else if (type >= ET_LOOS && type <= ET_HIOS) 282db27a04emaste snprintf(s_type, sizeof(s_type), "<os: %#x>", type); 283db27a04emaste else 284db27a04emaste snprintf(s_type, sizeof(s_type), "<unknown: %#x", type); 285db27a04emaste return (s_type); 286db27a04emaste} 2879ee7876kaiw 288db27a04emastestatic const char * 289db27a04emasteelf_version_str(unsigned int ver) 290db27a04emaste{ 291db27a04emaste static char s_ver[32]; 2929ee7876kaiw 293db27a04emaste switch (ver) { 294db27a04emaste case EV_NONE: return "EV_NONE"; 295db27a04emaste case EV_CURRENT: return "EV_CURRENT"; 296db27a04emaste } 297db27a04emaste snprintf(s_ver, sizeof(s_ver), "<unknown: %#x>", ver); 298db27a04emaste return (s_ver); 299db27a04emaste} 300db27a04emaste 301db27a04emastestatic const char * 302db27a04emasteelf_class_str(unsigned int class) 303db27a04emaste{ 304db27a04emaste static char s_class[32]; 305db27a04emaste 306db27a04emaste switch (class) { 307db27a04emaste case ELFCLASSNONE: return "ELFCLASSNONE"; 308db27a04emaste case ELFCLASS32: return "ELFCLASS32"; 309db27a04emaste case ELFCLASS64: return "ELFCLASS64"; 310db27a04emaste } 311db27a04emaste snprintf(s_class, sizeof(s_class), "<unknown: %#x>", class); 312db27a04emaste return (s_class); 313db27a04emaste} 314db27a04emaste 315db27a04emastestatic const char * 316db27a04emasteelf_data_str(unsigned int data) 317db27a04emaste{ 318db27a04emaste static char s_data[32]; 319db27a04emaste 320db27a04emaste switch (data) { 321db27a04emaste case ELFDATANONE: return "ELFDATANONE"; 322db27a04emaste case ELFDATA2LSB: return "ELFDATA2LSB"; 323db27a04emaste case ELFDATA2MSB: return "ELFDATA2MSB"; 324db27a04emaste } 325db27a04emaste snprintf(s_data, sizeof(s_data), "<unknown: %#x>", data); 326db27a04emaste return (s_data); 327db27a04emaste} 3289ee7876kaiw 329f776db0emastestatic const char *ei_abis[256] = { 330f776db0emaste "ELFOSABI_NONE", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 331f776db0emaste "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX", 332f776db0emaste "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64", 333f776db0emaste "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD", 334db27a04emaste [17] = "ELFOSABI_CLOUDABI", 3358c25ed7emaste [64] = "ELFOSABI_ARM_AEABI", 3368c25ed7emaste [97] = "ELFOSABI_ARM", 337f776db0emaste [255] = "ELFOSABI_STANDALONE" 3389ee7876kaiw}; 3399ee7876kaiw 340db27a04emastestatic const char * 341db27a04emasteelf_phdr_type_str(unsigned int type) 342db27a04emaste{ 343db27a04emaste static char s_type[32]; 344db27a04emaste 345db27a04emaste switch (type) { 346061ef1femaste case PT_NULL: return "PT_NULL"; 347061ef1femaste case PT_LOAD: return "PT_LOAD"; 348061ef1femaste case PT_DYNAMIC: return "PT_DYNAMIC"; 349061ef1femaste case PT_INTERP: return "PT_INTERP"; 350061ef1femaste case PT_NOTE: return "PT_NOTE"; 351061ef1femaste case PT_SHLIB: return "PT_SHLIB"; 352061ef1femaste case PT_PHDR: return "PT_PHDR"; 353061ef1femaste case PT_TLS: return "PT_TLS"; 354061ef1femaste case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME"; 355061ef1femaste case PT_GNU_STACK: return "PT_GNU_STACK"; 356061ef1femaste case PT_GNU_RELRO: return "PT_GNU_RELRO"; 357061ef1femaste case PT_OPENBSD_RANDOMIZE: return "PT_OPENBSD_RANDOMIZE"; 358061ef1femaste case PT_OPENBSD_WXNEEDED: return "PT_OPENBSD_WXNEEDED"; 359061ef1femaste case PT_OPENBSD_BOOTDATA: return "PT_OPENBSD_BOOTDATA"; 360db27a04emaste } 361db27a04emaste snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type); 362db27a04emaste return (s_type); 363db27a04emaste} 3649ee7876kaiw 3659ee7876kaiwstatic const char *p_flags[] = { 3669ee7876kaiw "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 3679ee7876kaiw "PF_X|PF_W|PF_R" 3689ee7876kaiw}; 3699ee7876kaiw 3709ee7876kaiwstatic const char * 3719ee7876kaiwsh_name(struct elfdump *ed, int ndx) 3729ee7876kaiw{ 3739ee7876kaiw static char num[10]; 3749ee7876kaiw 3759ee7876kaiw switch (ndx) { 3769ee7876kaiw case SHN_UNDEF: return "UNDEF"; 3779ee7876kaiw case SHN_ABS: return "ABS"; 3789ee7876kaiw case SHN_COMMON: return "COMMON"; 3799ee7876kaiw default: 3809ee7876kaiw if ((uint64_t)ndx < ed->shnum) 3819ee7876kaiw return (ed->sl[ndx].name); 3829ee7876kaiw else { 3839ee7876kaiw snprintf(num, sizeof(num), "%d", ndx); 3849ee7876kaiw return (num); 3859ee7876kaiw } 3869ee7876kaiw } 3879ee7876kaiw} 3889ee7876kaiw 3899ee7876kaiw/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 3909ee7876kaiwstatic const char * 39185217deemastesh_types(uint64_t mach, uint64_t sht) { 39285217deemaste static char unknown_buf[64]; 39385217deemaste 39485217deemaste if (sht < 0x60000000) { 39585217deemaste switch (sht) { 39685217deemaste case SHT_NULL: return "SHT_NULL"; 39785217deemaste case SHT_PROGBITS: return "SHT_PROGBITS"; 39885217deemaste case SHT_SYMTAB: return "SHT_SYMTAB"; 39985217deemaste case SHT_STRTAB: return "SHT_STRTAB"; 40085217deemaste case SHT_RELA: return "SHT_RELA"; 40185217deemaste case SHT_HASH: return "SHT_HASH"; 40285217deemaste case SHT_DYNAMIC: return "SHT_DYNAMIC"; 40385217deemaste case SHT_NOTE: return "SHT_NOTE"; 40485217deemaste case SHT_NOBITS: return "SHT_NOBITS"; 40585217deemaste case SHT_REL: return "SHT_REL"; 40685217deemaste case SHT_SHLIB: return "SHT_SHLIB"; 40785217deemaste case SHT_DYNSYM: return "SHT_DYNSYM"; 40885217deemaste case SHT_INIT_ARRAY: return "SHT_INIT_ARRAY"; 40985217deemaste case SHT_FINI_ARRAY: return "SHT_FINI_ARRAY"; 41085217deemaste case SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY"; 41185217deemaste case SHT_GROUP: return "SHT_GROUP"; 41285217deemaste case SHT_SYMTAB_SHNDX: return "SHT_SYMTAB_SHNDX"; 41385217deemaste } 41485217deemaste } else if (sht < 0x70000000) { 41585217deemaste /* 0x60000000-0x6fffffff operating system-specific semantics */ 41685217deemaste switch (sht) { 41785217deemaste case 0x6ffffff0: return "XXX:VERSYM"; 41885217deemaste case SHT_SUNW_dof: return "SHT_SUNW_dof"; 41985217deemaste case SHT_GNU_HASH: return "SHT_GNU_HASH"; 42085217deemaste case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 42185217deemaste case 0x6ffffffc: return "XXX:VERDEF"; 42285217deemaste case SHT_SUNW_verdef: return "SHT_SUNW(GNU)_verdef"; 42385217deemaste case SHT_SUNW_verneed: return "SHT_SUNW(GNU)_verneed"; 42485217deemaste case SHT_SUNW_versym: return "SHT_SUNW(GNU)_versym"; 42585217deemaste } 42685217deemaste } else if (sht < 0x80000000) { 42785217deemaste /* 0x70000000 - 0x7fffffff processor-specific semantics */ 42885217deemaste switch (mach) { 42985217deemaste case EM_ARM: 43085217deemaste switch (sht) { 43185217deemaste case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX"; 43285217deemaste case SHT_ARM_PREEMPTMAP: return "SHT_ARM_PREEMPTMAP"; 43385217deemaste case SHT_ARM_ATTRIBUTES: return "SHT_ARM_ATTRIBUTES"; 43485217deemaste case SHT_ARM_DEBUGOVERLAY: 43585217deemaste return "SHT_ARM_DEBUGOVERLAY"; 43685217deemaste case SHT_ARM_OVERLAYSECTION: 43785217deemaste return "SHT_ARM_OVERLAYSECTION"; 43885217deemaste } 43985217deemaste break; 44085217deemaste case EM_IA_64: 44185217deemaste switch (sht) { 44285217deemaste case 0x70000000: return "SHT_IA_64_EXT"; 44385217deemaste case 0x70000001: return "SHT_IA_64_UNWIND"; 44485217deemaste } 44585217deemaste break; 44685217deemaste case EM_MIPS: 44785217deemaste switch (sht) { 44885217deemaste case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO"; 44985217deemaste case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS"; 45085217deemaste case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS"; 45185217deemaste } 45285217deemaste break; 45385217deemaste } 45485217deemaste switch (sht) { 45585217deemaste case 0x7ffffffd: return "XXX:AUXILIARY"; 45685217deemaste case 0x7fffffff: return "XXX:FILTER"; 45785217deemaste } 4589ee7876kaiw } 45985217deemaste /* 0x80000000 - 0xffffffff application programs */ 46085217deemaste 46185217deemaste snprintf(unknown_buf, sizeof(unknown_buf), 46285217deemaste "<unknown: %#llx>", (unsigned long long)sht); 46385217deemaste return (unknown_buf); 4649ee7876kaiw} 4659ee7876kaiw 4669ee7876kaiw/* 4679ee7876kaiw * Define known section flags. These flags are defined in the order 4689ee7876kaiw * they are to be printed out. 4699ee7876kaiw */ 4709ee7876kaiw#define DEFINE_SHFLAGS() \ 4719ee7876kaiw DEFINE_SHF(WRITE) \ 4729ee7876kaiw DEFINE_SHF(ALLOC) \ 4739ee7876kaiw DEFINE_SHF(EXECINSTR) \ 4749ee7876kaiw DEFINE_SHF(MERGE) \ 4759ee7876kaiw DEFINE_SHF(STRINGS) \ 4769ee7876kaiw DEFINE_SHF(INFO_LINK) \ 4779ee7876kaiw DEFINE_SHF(LINK_ORDER) \ 4789ee7876kaiw DEFINE_SHF(OS_NONCONFORMING) \ 4799ee7876kaiw DEFINE_SHF(GROUP) \ 480db27a04emaste DEFINE_SHF(TLS) \ 481db27a04emaste DEFINE_SHF(COMPRESSED) 4829ee7876kaiw 4839ee7876kaiw#undef DEFINE_SHF 4849ee7876kaiw#define DEFINE_SHF(F) "SHF_" #F "|" 4859ee7876kaiw#define ALLSHFLAGS DEFINE_SHFLAGS() 4869ee7876kaiw 4879ee7876kaiwstatic const char * 4889ee7876kaiwsh_flags(uint64_t shf) 4899ee7876kaiw{ 4909ee7876kaiw static char flg[sizeof(ALLSHFLAGS)+1]; 4919ee7876kaiw 4929ee7876kaiw flg[0] = '\0'; 4939ee7876kaiw 4949ee7876kaiw#undef DEFINE_SHF 4959ee7876kaiw#define DEFINE_SHF(N) \ 4969ee7876kaiw if (shf & SHF_##N) \ 4979ee7876kaiw strcat(flg, "SHF_" #N "|"); \ 4989ee7876kaiw 4999ee7876kaiw DEFINE_SHFLAGS() 5009ee7876kaiw 5019ee7876kaiw flg[strlen(flg) - 1] = '\0'; /* Remove the trailing "|". */ 5029ee7876kaiw 5039ee7876kaiw return (flg); 5049ee7876kaiw} 5059ee7876kaiw 50685217deemastestatic const char * 50785217deemastest_type(unsigned int mach, unsigned int type) 50885217deemaste{ 50985217deemaste static char s_type[32]; 51085217deemaste 51185217deemaste switch (type) { 51285217deemaste case STT_NOTYPE: return "STT_NOTYPE"; 51385217deemaste case STT_OBJECT: return "STT_OBJECT"; 51485217deemaste case STT_FUNC: return "STT_FUNC"; 51585217deemaste case STT_SECTION: return "STT_SECTION"; 51685217deemaste case STT_FILE: return "STT_FILE"; 51785217deemaste case STT_COMMON: return "STT_COMMON"; 51885217deemaste case STT_TLS: return "STT_TLS"; 51985217deemaste case 13: 52085217deemaste if (mach == EM_SPARCV9) 52185217deemaste return "STT_SPARC_REGISTER"; 52285217deemaste break; 52385217deemaste } 52485217deemaste snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type); 52585217deemaste return (s_type); 52685217deemaste} 5279ee7876kaiw 52885217deemastestatic const char * 52985217deemastest_type_S(unsigned int type) 53085217deemaste{ 53185217deemaste static char s_type[32]; 53285217deemaste 53385217deemaste switch (type) { 53485217deemaste case STT_NOTYPE: return "NOTY"; 53585217deemaste case STT_OBJECT: return "OBJT"; 53685217deemaste case STT_FUNC: return "FUNC"; 53785217deemaste case STT_SECTION: return "SECT"; 53885217deemaste case STT_FILE: return "FILE"; 53985217deemaste } 54085217deemaste snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type); 54185217deemaste return (s_type); 54285217deemaste} 5439ee7876kaiw 54485217deemastestatic const char * 54585217deemastest_bindings(unsigned int sbind) 54685217deemaste{ 54785217deemaste static char s_sbind[32]; 5489ee7876kaiw 54985217deemaste switch (sbind) { 55085217deemaste case STB_LOCAL: return "STB_LOCAL"; 55185217deemaste case STB_GLOBAL: return "STB_GLOBAL"; 55285217deemaste case STB_WEAK: return "STB_WEAK"; 55385217deemaste case STB_GNU_UNIQUE: return "STB_GNU_UNIQUE"; 55485217deemaste default: 55585217deemaste if (sbind >= STB_LOOS && sbind <= STB_HIOS) 55685217deemaste return "OS"; 55785217deemaste else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC) 55885217deemaste return "PROC"; 55985217deemaste else 56085217deemaste snprintf(s_sbind, sizeof(s_sbind), "<unknown: %#x>", 56185217deemaste sbind); 56285217deemaste return (s_sbind); 56385217deemaste } 56485217deemaste} 56585217deemaste 56685217deemastestatic const char * 56785217deemastest_bindings_S(unsigned int sbind) 56885217deemaste{ 56985217deemaste static char s_sbind[32]; 57085217deemaste 57185217deemaste switch (sbind) { 57285217deemaste case STB_LOCAL: return "LOCL"; 57385217deemaste case STB_GLOBAL: return "GLOB"; 57485217deemaste case STB_WEAK: return "WEAK"; 57585217deemaste case STB_GNU_UNIQUE: return "UNIQ"; 57685217deemaste default: 57785217deemaste if (sbind >= STB_LOOS && sbind <= STB_HIOS) 57885217deemaste return "OS"; 57985217deemaste else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC) 58085217deemaste return "PROC"; 58185217deemaste else 58285217deemaste snprintf(s_sbind, sizeof(s_sbind), "<%#x>", 58385217deemaste sbind); 58485217deemaste return (s_sbind); 58585217deemaste } 58685217deemaste} 5879ee7876kaiw 5889ee7876kaiwstatic unsigned char st_others[] = { 5899ee7876kaiw 'D', 'I', 'H', 'P' 5909ee7876kaiw}; 5919ee7876kaiw 5929ee7876kaiwstatic void add_name(struct elfdump *ed, const char *name); 5939ee7876kaiwstatic void elf_print_object(struct elfdump *ed); 5949ee7876kaiwstatic void elf_print_elf(struct elfdump *ed); 5959ee7876kaiwstatic void elf_print_ehdr(struct elfdump *ed); 5969ee7876kaiwstatic void elf_print_phdr(struct elfdump *ed); 5979ee7876kaiwstatic void elf_print_shdr(struct elfdump *ed); 5989ee7876kaiwstatic void elf_print_symtab(struct elfdump *ed, int i); 5999ee7876kaiwstatic void elf_print_symtabs(struct elfdump *ed); 6009ee7876kaiwstatic void elf_print_symver(struct elfdump *ed); 6019ee7876kaiwstatic void elf_print_verdef(struct elfdump *ed, struct section *s); 6029ee7876kaiwstatic void elf_print_verneed(struct elfdump *ed, struct section *s); 6039ee7876kaiwstatic void elf_print_interp(struct elfdump *ed); 6049ee7876kaiwstatic void elf_print_dynamic(struct elfdump *ed); 6059ee7876kaiwstatic void elf_print_rel_entry(struct elfdump *ed, struct section *s, 6069ee7876kaiw int j, struct rel_entry *r); 6079ee7876kaiwstatic void elf_print_rela(struct elfdump *ed, struct section *s, 6089ee7876kaiw Elf_Data *data); 6099ee7876kaiwstatic void elf_print_rel(struct elfdump *ed, struct section *s, 6109ee7876kaiw Elf_Data *data); 6119ee7876kaiwstatic void elf_print_reloc(struct elfdump *ed); 6129ee7876kaiwstatic void elf_print_got(struct elfdump *ed); 6139ee7876kaiwstatic void elf_print_got_section(struct elfdump *ed, struct section *s); 6149ee7876kaiwstatic void elf_print_note(struct elfdump *ed); 6159ee7876kaiwstatic void elf_print_svr4_hash(struct elfdump *ed, struct section *s); 6169ee7876kaiwstatic void elf_print_svr4_hash64(struct elfdump *ed, struct section *s); 6179ee7876kaiwstatic void elf_print_gnu_hash(struct elfdump *ed, struct section *s); 6189ee7876kaiwstatic void elf_print_hash(struct elfdump *ed); 6199ee7876kaiwstatic void elf_print_checksum(struct elfdump *ed); 6209ee7876kaiwstatic void find_gotrel(struct elfdump *ed, struct section *gs, 6219ee7876kaiw struct rel_entry *got); 6229ee7876kaiwstatic struct spec_name *find_name(struct elfdump *ed, const char *name); 623f776db0emastestatic int get_ent_count(const struct section *s, int *ent_count); 624db27a04emastestatic const char *get_symbol_name(struct elfdump *ed, uint32_t symtab, int i); 6259ee7876kaiwstatic const char *get_string(struct elfdump *ed, int strtab, size_t off); 6269ee7876kaiwstatic void get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs); 6279ee7876kaiwstatic void load_sections(struct elfdump *ed); 6289ee7876kaiwstatic void unload_sections(struct elfdump *ed); 6299ee7876kaiwstatic void usage(void); 6309ee7876kaiw#ifdef USE_LIBARCHIVE_AR 6319ee7876kaiwstatic int ac_detect_ar(int fd); 6329ee7876kaiwstatic void ac_print_ar(struct elfdump *ed, int fd); 6339ee7876kaiw#else 6349ee7876kaiwstatic void elf_print_ar(struct elfdump *ed, int fd); 6359ee7876kaiw#endif /* USE_LIBARCHIVE_AR */ 6369ee7876kaiw 6379ee7876kaiwstatic struct option elfdump_longopts[] = 6389ee7876kaiw{ 6399ee7876kaiw { "help", no_argument, NULL, 'H' }, 6409ee7876kaiw { "version", no_argument, NULL, 'V' }, 6419ee7876kaiw { NULL, 0, NULL, 0 } 6429ee7876kaiw}; 6439ee7876kaiw 6449ee7876kaiwint 6459ee7876kaiwmain(int ac, char **av) 6469ee7876kaiw{ 6479ee7876kaiw struct elfdump *ed, ed_storage; 6489ee7876kaiw struct spec_name *sn; 6499ee7876kaiw int ch, i; 6509ee7876kaiw 6519ee7876kaiw ed = &ed_storage; 6529ee7876kaiw memset(ed, 0, sizeof(*ed)); 6539ee7876kaiw STAILQ_INIT(&ed->snl); 6549ee7876kaiw ed->out = stdout; 6559ee7876kaiw while ((ch = getopt_long(ac, av, "acdeiGHhknN:prsSvVw:", 6569ee7876kaiw elfdump_longopts, NULL)) != -1) 6579ee7876kaiw switch (ch) { 6589ee7876kaiw case 'a': 6599ee7876kaiw ed->options = ED_ALL; 6609ee7876kaiw break; 6619ee7876kaiw case 'c': 6629ee7876kaiw ed->options |= ED_SHDR; 6639ee7876kaiw break; 6649ee7876kaiw case 'd': 6659ee7876kaiw ed->options |= ED_DYN; 6669ee7876kaiw break; 6679ee7876kaiw case 'e': 6689ee7876kaiw ed->options |= ED_EHDR; 6699ee7876kaiw break; 6709ee7876kaiw case 'i': 6719ee7876kaiw ed->options |= ED_INTERP; 6729ee7876kaiw break; 6739ee7876kaiw case 'G': 6749ee7876kaiw ed->options |= ED_GOT; 6759ee7876kaiw break; 6769ee7876kaiw case 'h': 6779ee7876kaiw ed->options |= ED_HASH; 6789ee7876kaiw break; 6799ee7876kaiw case 'k': 6809ee7876kaiw ed->options |= ED_CHECKSUM; 6819ee7876kaiw break; 6829ee7876kaiw case 'n': 6839ee7876kaiw ed->options |= ED_NOTE; 6849ee7876kaiw break; 6859ee7876kaiw case 'N': 6869ee7876kaiw add_name(ed, optarg); 6879ee7876kaiw break; 6889ee7876kaiw case 'p': 6899ee7876kaiw ed->options |= ED_PHDR; 6909ee7876kaiw break; 6919ee7876kaiw case 'r': 6929ee7876kaiw ed->options |= ED_REL; 6939ee7876kaiw break; 6949ee7876kaiw case 's': 6959ee7876kaiw ed->options |= ED_SYMTAB; 6969ee7876kaiw break; 6979ee7876kaiw case 'S': 6989ee7876kaiw ed->flags |= SOLARIS_FMT; 6999ee7876kaiw break; 7009ee7876kaiw case 'v': 7019ee7876kaiw ed->options |= ED_SYMVER; 7029ee7876kaiw break; 7039ee7876kaiw case 'V': 7049ee7876kaiw (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), 7059ee7876kaiw elftc_version()); 7069ee7876kaiw exit(EXIT_SUCCESS); 7079ee7876kaiw break; 7089ee7876kaiw case 'w': 7099ee7876kaiw if ((ed->out = fopen(optarg, "w")) == NULL) 7109ee7876kaiw err(EXIT_FAILURE, "%s", optarg); 7119ee7876kaiw break; 7129ee7876kaiw case '?': 7139ee7876kaiw case 'H': 7149ee7876kaiw default: 7159ee7876kaiw usage(); 7169ee7876kaiw } 7179ee7876kaiw 7189ee7876kaiw ac -= optind; 7199ee7876kaiw av += optind; 7209ee7876kaiw 7219ee7876kaiw if (ed->options == 0) 7229ee7876kaiw ed->options = ED_ALL; 7239ee7876kaiw sn = NULL; 7249ee7876kaiw if (ed->options & ED_SYMTAB && 7259ee7876kaiw (STAILQ_EMPTY(&ed->snl) || (sn = find_name(ed, "ARSYM")) != NULL)) { 7269ee7876kaiw ed->flags |= PRINT_ARSYM; 7279ee7876kaiw if (sn != NULL) { 7289ee7876kaiw STAILQ_REMOVE(&ed->snl, sn, spec_name, sn_list); 7299ee7876kaiw if (STAILQ_EMPTY(&ed->snl)) 7309ee7876kaiw ed->flags |= ONLY_ARSYM; 7319ee7876kaiw } 7329ee7876kaiw } 7339ee7876kaiw if (ac == 0) 7349ee7876kaiw usage(); 7359ee7876kaiw if (ac > 1) 7369ee7876kaiw ed->flags |= PRINT_FILENAME; 7379ee7876kaiw if (elf_version(EV_CURRENT) == EV_NONE) 7389ee7876kaiw errx(EXIT_FAILURE, "ELF library initialization failed: %s", 7399ee7876kaiw elf_errmsg(-1)); 7409ee7876kaiw 741eb5d1f5emaste for (i = 0; i < ac; i++) { 742eb5d1f5emaste ed->filename = av[i]; 743eb5d1f5emaste ed->archive = NULL; 744eb5d1f5emaste elf_print_object(ed); 745eb5d1f5emaste } 7469ee7876kaiw 7479ee7876kaiw exit(EXIT_SUCCESS); 7489ee7876kaiw} 7499ee7876kaiw 7509ee7876kaiw#ifdef USE_LIBARCHIVE_AR 7519ee7876kaiw 7529ee7876kaiw/* Archive symbol table entry. */ 7539ee7876kaiwstruct arsym_entry { 7549ee7876kaiw char *sym_name; 7559ee7876kaiw size_t off; 7569ee7876kaiw}; 7579ee7876kaiw 7589ee7876kaiw/* 7599ee7876kaiw * Convenient wrapper for general libarchive error handling. 7609ee7876kaiw */ 7619ee7876kaiw#define AC(CALL) do { \ 7629ee7876kaiw if ((CALL)) { \ 7639ee7876kaiw warnx("%s", archive_error_string(a)); \ 7649ee7876kaiw return; \ 7659ee7876kaiw } \ 7669ee7876kaiw} while (0) 7679ee7876kaiw 7689ee7876kaiw/* 7699ee7876kaiw * Detect an ar(1) archive using libarchive(3). 7709ee7876kaiw */ 7719ee7876kaiwstatic int 7729ee7876kaiwac_detect_ar(int fd) 7739ee7876kaiw{ 7749ee7876kaiw struct archive *a; 7759ee7876kaiw struct archive_entry *entry; 7769ee7876kaiw int r; 7779ee7876kaiw 7789ee7876kaiw r = -1; 7799ee7876kaiw if ((a = archive_read_new()) == NULL) 7809ee7876kaiw return (0); 7819ee7876kaiw archive_read_support_format_ar(a); 7829ee7876kaiw if (archive_read_open_fd(a, fd, 10240) == ARCHIVE_OK) 7839ee7876kaiw r = archive_read_next_header(a, &entry); 7849ee7876kaiw archive_read_close(a); 7856f703c4emaste archive_read_free(a); 7869ee7876kaiw 7879ee7876kaiw return (r == ARCHIVE_OK); 7889ee7876kaiw} 7899ee7876kaiw 7909ee7876kaiw/* 7919ee7876kaiw * Dump an ar(1) archive using libarchive(3). 7929ee7876kaiw */ 7939ee7876kaiwstatic void 7949ee7876kaiwac_print_ar(struct elfdump *ed, int fd) 7959ee7876kaiw{ 7969ee7876kaiw struct archive *a; 7979ee7876kaiw struct archive_entry *entry; 7989ee7876kaiw struct arsym_entry *arsym; 7999ee7876kaiw const char *name; 8009ee7876kaiw char idx[10], *b; 8019ee7876kaiw void *buff; 8029ee7876kaiw size_t size; 803db27a04emaste uint32_t cnt, i; 804db27a04emaste int r; 8059ee7876kaiw 8069ee7876kaiw if (lseek(fd, 0, SEEK_SET) == -1) 8079ee7876kaiw err(EXIT_FAILURE, "lseek failed"); 8089ee7876kaiw if ((a = archive_read_new()) == NULL) 8099ee7876kaiw errx(EXIT_FAILURE, "%s", archive_error_string(a)); 8109ee7876kaiw archive_read_support_format_ar(a); 8119ee7876kaiw AC(archive_read_open_fd(a, fd, 10240)); 8129ee7876kaiw for(;;) { 8139ee7876kaiw r = archive_read_next_header(a, &entry); 8149ee7876kaiw if (r == ARCHIVE_FATAL) 8159ee7876kaiw errx(EXIT_FAILURE, "%s", archive_error_string(a)); 8169ee7876kaiw if (r == ARCHIVE_EOF) 8179ee7876kaiw break; 8189ee7876kaiw if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY) 8199ee7876kaiw warnx("%s", archive_error_string(a)); 8209ee7876kaiw if (r == ARCHIVE_RETRY) 8219ee7876kaiw continue; 8229ee7876kaiw name = archive_entry_pathname(entry); 8239ee7876kaiw size = archive_entry_size(entry); 8249ee7876kaiw if (size == 0) 8259ee7876kaiw continue; 8269ee7876kaiw if ((buff = malloc(size)) == NULL) { 8279ee7876kaiw warn("malloc failed"); 8289ee7876kaiw continue; 8299ee7876kaiw } 8309ee7876kaiw if (archive_read_data(a, buff, size) != (ssize_t)size) { 8319ee7876kaiw warnx("%s", archive_error_string(a)); 8329ee7876kaiw free(buff); 8339ee7876kaiw continue; 8349ee7876kaiw } 8359ee7876kaiw 8369ee7876kaiw /* 8379ee7876kaiw * Note that when processing arsym via libarchive, there is 8389ee7876kaiw * no way to tell which member a certain symbol belongs to, 8399ee7876kaiw * since we can not just "lseek" to a member offset and read 8409ee7876kaiw * the member header. 8419ee7876kaiw */ 8429ee7876kaiw if (!strcmp(name, "/") && ed->flags & PRINT_ARSYM) { 8439ee7876kaiw b = buff; 8449ee7876kaiw cnt = be32dec(b); 8459ee7876kaiw if (cnt == 0) { 8469ee7876kaiw free(buff); 8479ee7876kaiw continue; 8489ee7876kaiw } 8499ee7876kaiw arsym = calloc(cnt, sizeof(*arsym)); 8509ee7876kaiw if (arsym == NULL) 8519ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 8529ee7876kaiw b += sizeof(uint32_t); 853db27a04emaste for (i = 0; i < cnt; i++) { 8549ee7876kaiw arsym[i].off = be32dec(b); 8559ee7876kaiw b += sizeof(uint32_t); 8569ee7876kaiw } 857db27a04emaste for (i = 0; i < cnt; i++) { 8589ee7876kaiw arsym[i].sym_name = b; 8599ee7876kaiw b += strlen(b) + 1; 8609ee7876kaiw } 8619ee7876kaiw if (ed->flags & SOLARIS_FMT) { 8629ee7876kaiw PRT("\nSymbol Table: (archive)\n"); 8639ee7876kaiw PRT(" index offset symbol\n"); 8649ee7876kaiw } else 8659ee7876kaiw PRT("\nsymbol table (archive):\n"); 866db27a04emaste for (i = 0; i < cnt; i++) { 8679ee7876kaiw if (ed->flags & SOLARIS_FMT) { 8689ee7876kaiw snprintf(idx, sizeof(idx), "[%d]", i); 8699ee7876kaiw PRT("%10s ", idx); 8709ee7876kaiw PRT("0x%8.8jx ", 8719ee7876kaiw (uintmax_t)arsym[i].off); 8729ee7876kaiw PRT("%s\n", arsym[i].sym_name); 8739ee7876kaiw } else { 8749ee7876kaiw PRT("\nentry: %d\n", i); 8759ee7876kaiw PRT("\toffset: %#jx\n", 8769ee7876kaiw (uintmax_t)arsym[i].off); 8779ee7876kaiw PRT("\tsymbol: %s\n", 8789ee7876kaiw arsym[i].sym_name); 8799ee7876kaiw } 8809ee7876kaiw } 8819ee7876kaiw free(arsym); 8829ee7876kaiw free(buff); 8839ee7876kaiw /* No need to continue if we only dump ARSYM. */ 8849ee7876kaiw if (ed->flags & ONLY_ARSYM) { 8859ee7876kaiw AC(archive_read_close(a)); 8866f703c4emaste AC(archive_read_free(a)); 8879ee7876kaiw return; 8889ee7876kaiw } 8899ee7876kaiw continue; 8909ee7876kaiw } 8919ee7876kaiw if ((ed->elf = elf_memory(buff, size)) == NULL) { 8929ee7876kaiw warnx("elf_memroy() failed: %s", 8939ee7876kaiw elf_errmsg(-1)); 8949ee7876kaiw free(buff); 8959ee7876kaiw continue; 8969ee7876kaiw } 8979ee7876kaiw /* Skip non-ELF member. */ 8989ee7876kaiw if (elf_kind(ed->elf) == ELF_K_ELF) { 8999ee7876kaiw printf("\n%s(%s):\n", ed->archive, name); 9009ee7876kaiw elf_print_elf(ed); 9019ee7876kaiw } 9029ee7876kaiw elf_end(ed->elf); 9039ee7876kaiw free(buff); 9049ee7876kaiw } 9059ee7876kaiw AC(archive_read_close(a)); 9066f703c4emaste AC(archive_read_free(a)); 9079ee7876kaiw} 9089ee7876kaiw 9099ee7876kaiw#else /* USE_LIBARCHIVE_AR */ 9109ee7876kaiw 9119ee7876kaiw/* 9129ee7876kaiw * Dump an ar(1) archive. 9139ee7876kaiw */ 9149ee7876kaiwstatic void 9159ee7876kaiwelf_print_ar(struct elfdump *ed, int fd) 9169ee7876kaiw{ 9179ee7876kaiw Elf *e; 9189ee7876kaiw Elf_Arhdr *arh; 9199ee7876kaiw Elf_Arsym *arsym; 9209ee7876kaiw Elf_Cmd cmd; 921b4985c2emaste char idx[21]; 922db27a04emaste size_t cnt, i; 9239ee7876kaiw 9249ee7876kaiw ed->ar = ed->elf; 9259ee7876kaiw 9269ee7876kaiw if (ed->flags & PRINT_ARSYM) { 9279ee7876kaiw cnt = 0; 9289ee7876kaiw if ((arsym = elf_getarsym(ed->ar, &cnt)) == NULL) { 9299ee7876kaiw warnx("elf_getarsym failed: %s", elf_errmsg(-1)); 9309ee7876kaiw goto print_members; 9319ee7876kaiw } 9329ee7876kaiw if (cnt == 0) 9339ee7876kaiw goto print_members; 9349ee7876kaiw if (ed->flags & SOLARIS_FMT) { 9359ee7876kaiw PRT("\nSymbol Table: (archive)\n"); 9369ee7876kaiw PRT(" index offset member name and symbol\n"); 9379ee7876kaiw } else 9389ee7876kaiw PRT("\nsymbol table (archive):\n"); 939db27a04emaste for (i = 0; i < cnt - 1; i++) { 9409ee7876kaiw if (elf_rand(ed->ar, arsym[i].as_off) != 9419ee7876kaiw arsym[i].as_off) { 9429ee7876kaiw warnx("elf_rand failed: %s", elf_errmsg(-1)); 9439ee7876kaiw break; 9449ee7876kaiw } 9459ee7876kaiw if ((e = elf_begin(fd, ELF_C_READ, ed->ar)) == NULL) { 9469ee7876kaiw warnx("elf_begin failed: %s", elf_errmsg(-1)); 9479ee7876kaiw break; 9489ee7876kaiw } 9499ee7876kaiw if ((arh = elf_getarhdr(e)) == NULL) { 9509ee7876kaiw warnx("elf_getarhdr failed: %s", 9519ee7876kaiw elf_errmsg(-1)); 9529ee7876kaiw break; 9539ee7876kaiw } 9549ee7876kaiw if (ed->flags & SOLARIS_FMT) { 955db27a04emaste snprintf(idx, sizeof(idx), "[%zu]", i); 9569ee7876kaiw PRT("%10s ", idx); 9579ee7876kaiw PRT("0x%8.8jx ", 9589ee7876kaiw (uintmax_t)arsym[i].as_off); 9599ee7876kaiw PRT("(%s):%s\n", arh->ar_name, 9609ee7876kaiw arsym[i].as_name); 9619ee7876kaiw } else { 962db27a04emaste PRT("\nentry: %zu\n", i); 9639ee7876kaiw PRT("\toffset: %#jx\n", 9649ee7876kaiw (uintmax_t)arsym[i].as_off); 9659ee7876kaiw PRT("\tmember: %s\n", arh->ar_name); 9669ee7876kaiw PRT("\tsymbol: %s\n", arsym[i].as_name); 9679ee7876kaiw } 9689ee7876kaiw elf_end(e); 9699ee7876kaiw } 9709ee7876kaiw 9719ee7876kaiw /* No need to continue if we only dump ARSYM. */ 9729ee7876kaiw if (ed->flags & ONLY_ARSYM) 9739ee7876kaiw return; 9749ee7876kaiw } 9759ee7876kaiw 9769ee7876kaiwprint_members: 9779ee7876kaiw 9789ee7876kaiw /* Rewind the archive. */ 9799ee7876kaiw if (elf_rand(ed->ar, SARMAG) != SARMAG) { 9809ee7876kaiw warnx("elf_rand failed: %s", elf_errmsg(-1)); 9819ee7876kaiw return; 9829ee7876kaiw } 9839ee7876kaiw 9849ee7876kaiw /* Dump each member of the archive. */ 9859ee7876kaiw cmd = ELF_C_READ; 9869ee7876kaiw while ((ed->elf = elf_begin(fd, cmd, ed->ar)) != NULL) { 9879ee7876kaiw /* Skip non-ELF member. */ 9889ee7876kaiw if (elf_kind(ed->elf) == ELF_K_ELF) { 9899ee7876kaiw if ((arh = elf_getarhdr(ed->elf)) == NULL) { 9909ee7876kaiw warnx("elf_getarhdr failed: %s", 9919ee7876kaiw elf_errmsg(-1)); 9929ee7876kaiw break; 9939ee7876kaiw } 9949ee7876kaiw printf("\n%s(%s):\n", ed->archive, arh->ar_name); 9959ee7876kaiw elf_print_elf(ed); 9969ee7876kaiw } 9979ee7876kaiw cmd = elf_next(ed->elf); 9989ee7876kaiw elf_end(ed->elf); 9999ee7876kaiw } 10009ee7876kaiw} 10019ee7876kaiw 10029ee7876kaiw#endif /* USE_LIBARCHIVE_AR */ 10039ee7876kaiw 10049ee7876kaiw/* 10059ee7876kaiw * Dump an object. (ELF object or ar(1) archive) 10069ee7876kaiw */ 10079ee7876kaiwstatic void 10089ee7876kaiwelf_print_object(struct elfdump *ed) 10099ee7876kaiw{ 10109ee7876kaiw int fd; 10119ee7876kaiw 10129ee7876kaiw if ((fd = open(ed->filename, O_RDONLY)) == -1) { 10139ee7876kaiw warn("open %s failed", ed->filename); 10149ee7876kaiw return; 10159ee7876kaiw } 10169ee7876kaiw 10179ee7876kaiw#ifdef USE_LIBARCHIVE_AR 10189ee7876kaiw if (ac_detect_ar(fd)) { 10199ee7876kaiw ed->archive = ed->filename; 10209ee7876kaiw ac_print_ar(ed, fd); 10219ee7876kaiw return; 10229ee7876kaiw } 10239ee7876kaiw#endif /* USE_LIBARCHIVE_AR */ 10249ee7876kaiw 10259ee7876kaiw if ((ed->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 10269ee7876kaiw warnx("elf_begin() failed: %s", elf_errmsg(-1)); 10279ee7876kaiw return; 10289ee7876kaiw } 10299ee7876kaiw 10309ee7876kaiw switch (elf_kind(ed->elf)) { 10319ee7876kaiw case ELF_K_NONE: 10329ee7876kaiw warnx("Not an ELF file."); 10339ee7876kaiw return; 10349ee7876kaiw case ELF_K_ELF: 10359ee7876kaiw if (ed->flags & PRINT_FILENAME) 10369ee7876kaiw printf("\n%s:\n", ed->filename); 10379ee7876kaiw elf_print_elf(ed); 10389ee7876kaiw break; 10399ee7876kaiw case ELF_K_AR: 10409ee7876kaiw#ifndef USE_LIBARCHIVE_AR 10419ee7876kaiw ed->archive = ed->filename; 10429ee7876kaiw elf_print_ar(ed, fd); 10439ee7876kaiw#endif 10449ee7876kaiw break; 10459ee7876kaiw default: 10469ee7876kaiw warnx("Internal: libelf returned unknown elf kind."); 10479ee7876kaiw return; 10489ee7876kaiw } 10499ee7876kaiw 10509ee7876kaiw elf_end(ed->elf); 10519ee7876kaiw} 10529ee7876kaiw 10539ee7876kaiw/* 10549ee7876kaiw * Dump an ELF object. 10559ee7876kaiw */ 10569ee7876kaiwstatic void 10579ee7876kaiwelf_print_elf(struct elfdump *ed) 10589ee7876kaiw{ 10599ee7876kaiw 10609ee7876kaiw if (gelf_getehdr(ed->elf, &ed->ehdr) == NULL) { 10619ee7876kaiw warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 10629ee7876kaiw return; 10639ee7876kaiw } 10649ee7876kaiw if ((ed->ec = gelf_getclass(ed->elf)) == ELFCLASSNONE) { 10659ee7876kaiw warnx("gelf_getclass failed: %s", elf_errmsg(-1)); 10669ee7876kaiw return; 10679ee7876kaiw } 10689ee7876kaiw 10699ee7876kaiw if (ed->options & (ED_SHDR | ED_DYN | ED_REL | ED_GOT | ED_SYMTAB | 10709ee7876kaiw ED_SYMVER | ED_NOTE | ED_HASH)) 10719ee7876kaiw load_sections(ed); 10729ee7876kaiw 10739ee7876kaiw if (ed->options & ED_EHDR) 10749ee7876kaiw elf_print_ehdr(ed); 10759ee7876kaiw if (ed->options & ED_PHDR) 10769ee7876kaiw elf_print_phdr(ed); 10779ee7876kaiw if (ed->options & ED_INTERP) 10789ee7876kaiw elf_print_interp(ed); 10799ee7876kaiw if (ed->options & ED_SHDR) 10809ee7876kaiw elf_print_shdr(ed); 10819ee7876kaiw if (ed->options & ED_DYN) 10829ee7876kaiw elf_print_dynamic(ed); 10839ee7876kaiw if (ed->options & ED_REL) 10849ee7876kaiw elf_print_reloc(ed); 10859ee7876kaiw if (ed->options & ED_GOT) 10869ee7876kaiw elf_print_got(ed); 10879ee7876kaiw if (ed->options & ED_SYMTAB) 10889ee7876kaiw elf_print_symtabs(ed); 10899ee7876kaiw if (ed->options & ED_SYMVER) 10909ee7876kaiw elf_print_symver(ed); 10919ee7876kaiw if (ed->options & ED_NOTE) 10929ee7876kaiw elf_print_note(ed); 10939ee7876kaiw if (ed->options & ED_HASH) 10949ee7876kaiw elf_print_hash(ed); 10959ee7876kaiw if (ed->options & ED_CHECKSUM) 10969ee7876kaiw elf_print_checksum(ed); 10979ee7876kaiw 10989ee7876kaiw unload_sections(ed); 10999ee7876kaiw} 11009ee7876kaiw 11019ee7876kaiw/* 11029ee7876kaiw * Read the section headers from ELF object and store them in the 11039ee7876kaiw * internal cache. 11049ee7876kaiw */ 11059ee7876kaiwstatic void 11069ee7876kaiwload_sections(struct elfdump *ed) 11079ee7876kaiw{ 11089ee7876kaiw struct section *s; 11099ee7876kaiw const char *name; 11109ee7876kaiw Elf_Scn *scn; 11119ee7876kaiw GElf_Shdr sh; 11129ee7876kaiw size_t shstrndx, ndx; 11139ee7876kaiw int elferr; 11149ee7876kaiw 11159ee7876kaiw assert(ed->sl == NULL); 11169ee7876kaiw 11179ee7876kaiw if (!elf_getshnum(ed->elf, &ed->shnum)) { 11189ee7876kaiw warnx("elf_getshnum failed: %s", elf_errmsg(-1)); 11199ee7876kaiw return; 11209ee7876kaiw } 11219ee7876kaiw if (ed->shnum == 0) 11229ee7876kaiw return; 11239ee7876kaiw if ((ed->sl = calloc(ed->shnum, sizeof(*ed->sl))) == NULL) 11249ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 11259ee7876kaiw if (!elf_getshstrndx(ed->elf, &shstrndx)) { 11269ee7876kaiw warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 11279ee7876kaiw return; 11289ee7876kaiw } 11299ee7876kaiw if ((scn = elf_getscn(ed->elf, 0)) == NULL) { 11309ee7876kaiw warnx("elf_getscn failed: %s", elf_errmsg(-1)); 11319ee7876kaiw return; 11329ee7876kaiw } 11339ee7876kaiw (void) elf_errno(); 11349ee7876kaiw do { 11359ee7876kaiw if (gelf_getshdr(scn, &sh) == NULL) { 11369ee7876kaiw warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 11379ee7876kaiw (void) elf_errno(); 11389ee7876kaiw continue; 11399ee7876kaiw } 11409ee7876kaiw if ((name = elf_strptr(ed->elf, shstrndx, sh.sh_name)) == NULL) { 11419ee7876kaiw (void) elf_errno(); 11429ee7876kaiw name = "ERROR"; 11439ee7876kaiw } 11449ee7876kaiw if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) 11459ee7876kaiw if ((elferr = elf_errno()) != 0) { 11469ee7876kaiw warnx("elf_ndxscn failed: %s", 11479ee7876kaiw elf_errmsg(elferr)); 11489ee7876kaiw continue; 11499ee7876kaiw } 11509ee7876kaiw if (ndx >= ed->shnum) { 11519ee7876kaiw warnx("section index of '%s' out of range", name); 11529ee7876kaiw continue; 11539ee7876kaiw } 11549ee7876kaiw s = &ed->sl[ndx]; 11559ee7876kaiw s->name = name; 11569ee7876kaiw s->scn = scn; 11579ee7876kaiw s->off = sh.sh_offset; 11589ee7876kaiw s->sz = sh.sh_size; 11599ee7876kaiw s->entsize = sh.sh_entsize; 11609ee7876kaiw s->align = sh.sh_addralign; 11619ee7876kaiw s->type = sh.sh_type; 11629ee7876kaiw s->flags = sh.sh_flags; 11639ee7876kaiw s->addr = sh.sh_addr; 11649ee7876kaiw s->link = sh.sh_link; 11659ee7876kaiw s->info = sh.sh_info; 11669ee7876kaiw } while ((scn = elf_nextscn(ed->elf, scn)) != NULL); 11679ee7876kaiw elferr = elf_errno(); 11689ee7876kaiw if (elferr != 0) 11699ee7876kaiw warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 11709ee7876kaiw} 11719ee7876kaiw 11729ee7876kaiw/* 11739ee7876kaiw * Release section related resources. 11749ee7876kaiw */ 11759ee7876kaiwstatic void 11769ee7876kaiwunload_sections(struct elfdump *ed) 11779ee7876kaiw{ 11789ee7876kaiw if (ed->sl != NULL) { 11799ee7876kaiw free(ed->sl); 11809ee7876kaiw ed->sl = NULL; 11819ee7876kaiw } 11829ee7876kaiw} 11839ee7876kaiw 11849ee7876kaiw/* 11859ee7876kaiw * Add a name to the '-N' name list. 11869ee7876kaiw */ 11879ee7876kaiwstatic void 11889ee7876kaiwadd_name(struct elfdump *ed, const char *name) 11899ee7876kaiw{ 11909ee7876kaiw struct spec_name *sn; 11919ee7876kaiw 11929ee7876kaiw if (find_name(ed, name)) 11939ee7876kaiw return; 11949ee7876kaiw if ((sn = malloc(sizeof(*sn))) == NULL) { 11959ee7876kaiw warn("malloc failed"); 11969ee7876kaiw return; 11979ee7876kaiw } 11989ee7876kaiw sn->name = name; 11999ee7876kaiw STAILQ_INSERT_TAIL(&ed->snl, sn, sn_list); 12009ee7876kaiw} 12019ee7876kaiw 12029ee7876kaiw/* 12039ee7876kaiw * Lookup a name in the '-N' name list. 12049ee7876kaiw */ 12059ee7876kaiwstatic struct spec_name * 12069ee7876kaiwfind_name(struct elfdump *ed, const char *name) 12079ee7876kaiw{ 12089ee7876kaiw struct spec_name *sn; 12099ee7876kaiw 12109ee7876kaiw STAILQ_FOREACH(sn, &ed->snl, sn_list) { 12119ee7876kaiw if (!strcmp(sn->name, name)) 12129ee7876kaiw return (sn); 12139ee7876kaiw } 12149ee7876kaiw 12159ee7876kaiw return (NULL); 12169ee7876kaiw} 12179ee7876kaiw 12189ee7876kaiw/* 12199ee7876kaiw * Retrieve the name of a symbol using the section index of the symbol 12209ee7876kaiw * table and the index of the symbol within that table. 12219ee7876kaiw */ 12229ee7876kaiwstatic const char * 1223db27a04emasteget_symbol_name(struct elfdump *ed, uint32_t symtab, int i) 12249ee7876kaiw{ 12259ee7876kaiw static char sname[64]; 12269ee7876kaiw struct section *s; 12279ee7876kaiw const char *name; 12289ee7876kaiw GElf_Sym sym; 12299ee7876kaiw Elf_Data *data; 12309ee7876kaiw int elferr; 12319ee7876kaiw 1232db27a04emaste if (symtab >= ed->shnum) 1233db27a04emaste return (""); 12349ee7876kaiw s = &ed->sl[symtab]; 12359ee7876kaiw if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) 12369ee7876kaiw return (""); 12379ee7876kaiw (void) elf_errno(); 12389ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 12399ee7876kaiw elferr = elf_errno(); 12409ee7876kaiw if (elferr != 0) 12419ee7876kaiw warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 12429ee7876kaiw return (""); 12439ee7876kaiw } 12449ee7876kaiw if (gelf_getsym(data, i, &sym) != &sym) 12459ee7876kaiw return (""); 12469ee7876kaiw if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) { 12479ee7876kaiw if (sym.st_shndx < ed->shnum) { 12489ee7876kaiw snprintf(sname, sizeof(sname), "%s (section)", 12499ee7876kaiw ed->sl[sym.st_shndx].name); 12509ee7876kaiw return (sname); 12519ee7876kaiw } else 12529ee7876kaiw return (""); 12539ee7876kaiw } 12549ee7876kaiw if ((name = elf_strptr(ed->elf, s->link, sym.st_name)) == NULL) 12559ee7876kaiw return (""); 12569ee7876kaiw 12579ee7876kaiw return (name); 12589ee7876kaiw} 12599ee7876kaiw 12609ee7876kaiw/* 12619ee7876kaiw * Retrieve a string using string table section index and the string offset. 12629ee7876kaiw */ 12639ee7876kaiwstatic const char* 12649ee7876kaiwget_string(struct elfdump *ed, int strtab, size_t off) 12659ee7876kaiw{ 12669ee7876kaiw const char *name; 12679ee7876kaiw 12689ee7876kaiw if ((name = elf_strptr(ed->elf, strtab, off)) == NULL) 12699ee7876kaiw return (""); 12709ee7876kaiw 12719ee7876kaiw return (name); 12729ee7876kaiw} 12739ee7876kaiw 12749ee7876kaiw/* 12759ee7876kaiw * Dump the ELF Executable Header. 12769ee7876kaiw */ 12779ee7876kaiwstatic void 12789ee7876kaiwelf_print_ehdr(struct elfdump *ed) 12799ee7876kaiw{ 12809ee7876kaiw 12819ee7876kaiw if (!STAILQ_EMPTY(&ed->snl)) 12829ee7876kaiw return; 12839ee7876kaiw 12849ee7876kaiw if (ed->flags & SOLARIS_FMT) { 12859ee7876kaiw PRT("\nELF Header\n"); 12869ee7876kaiw PRT(" ei_magic: { %#x, %c, %c, %c }\n", 12879ee7876kaiw ed->ehdr.e_ident[0], ed->ehdr.e_ident[1], 12889ee7876kaiw ed->ehdr.e_ident[2], ed->ehdr.e_ident[3]); 12899ee7876kaiw PRT(" ei_class: %-18s", 1290db27a04emaste elf_class_str(ed->ehdr.e_ident[EI_CLASS])); 1291db27a04emaste PRT(" ei_data: %s\n", 1292db27a04emaste elf_data_str(ed->ehdr.e_ident[EI_DATA])); 12939ee7876kaiw PRT(" e_machine: %-18s", e_machines(ed->ehdr.e_machine)); 1294db27a04emaste PRT(" e_version: %s\n", 1295db27a04emaste elf_version_str(ed->ehdr.e_version)); 1296db27a04emaste PRT(" e_type: %s\n", elf_type_str(ed->ehdr.e_type)); 12979ee7876kaiw PRT(" e_flags: %18d\n", ed->ehdr.e_flags); 12989ee7876kaiw PRT(" e_entry: %#18jx", (uintmax_t)ed->ehdr.e_entry); 12999ee7876kaiw PRT(" e_ehsize: %6d", ed->ehdr.e_ehsize); 13009ee7876kaiw PRT(" e_shstrndx:%5d\n", ed->ehdr.e_shstrndx); 13019ee7876kaiw PRT(" e_shoff: %#18jx", (uintmax_t)ed->ehdr.e_shoff); 13029ee7876kaiw PRT(" e_shentsize: %3d", ed->ehdr.e_shentsize); 13039ee7876kaiw PRT(" e_shnum: %5d\n", ed->ehdr.e_shnum); 13049ee7876kaiw PRT(" e_phoff: %#18jx", (uintmax_t)ed->ehdr.e_phoff); 13059ee7876kaiw PRT(" e_phentsize: %3d", ed->ehdr.e_phentsize); 13069ee7876kaiw PRT(" e_phnum: %5d\n", ed->ehdr.e_phnum); 13079ee7876kaiw } else { 13089ee7876kaiw PRT("\nelf header:\n"); 13099ee7876kaiw PRT("\n"); 13109ee7876kaiw PRT("\te_ident: %s %s %s\n", 1311db27a04emaste elf_class_str(ed->ehdr.e_ident[EI_CLASS]), 1312db27a04emaste elf_data_str(ed->ehdr.e_ident[EI_DATA]), 13139ee7876kaiw ei_abis[ed->ehdr.e_ident[EI_OSABI]]); 1314db27a04emaste PRT("\te_type: %s\n", elf_type_str(ed->ehdr.e_type)); 13159ee7876kaiw PRT("\te_machine: %s\n", e_machines(ed->ehdr.e_machine)); 1316db27a04emaste PRT("\te_version: %s\n", elf_version_str(ed->ehdr.e_version)); 13179ee7876kaiw PRT("\te_entry: %#jx\n", (uintmax_t)ed->ehdr.e_entry); 13189ee7876kaiw PRT("\te_phoff: %ju\n", (uintmax_t)ed->ehdr.e_phoff); 13199ee7876kaiw PRT("\te_shoff: %ju\n", (uintmax_t) ed->ehdr.e_shoff); 13209ee7876kaiw PRT("\te_flags: %u\n", ed->ehdr.e_flags); 13219ee7876kaiw PRT("\te_ehsize: %u\n", ed->ehdr.e_ehsize); 13229ee7876kaiw PRT("\te_phentsize: %u\n", ed->ehdr.e_phentsize); 13239ee7876kaiw PRT("\te_phnum: %u\n", ed->ehdr.e_phnum); 13249ee7876kaiw PRT("\te_shentsize: %u\n", ed->ehdr.e_shentsize); 13259ee7876kaiw PRT("\te_shnum: %u\n", ed->ehdr.e_shnum); 13269ee7876kaiw PRT("\te_shstrndx: %u\n", ed->ehdr.e_shstrndx); 13279ee7876kaiw } 13289ee7876kaiw} 13299ee7876kaiw 13309ee7876kaiw/* 13319ee7876kaiw * Dump the ELF Program Header Table. 13329ee7876kaiw */ 13339ee7876kaiwstatic void 13349ee7876kaiwelf_print_phdr(struct elfdump *ed) 13359ee7876kaiw{ 13369ee7876kaiw GElf_Phdr ph; 1337db27a04emaste size_t phnum, i; 1338db27a04emaste int header; 13399ee7876kaiw 13409ee7876kaiw if (elf_getphnum(ed->elf, &phnum) == 0) { 13419ee7876kaiw warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 13429ee7876kaiw return; 13439ee7876kaiw } 13449ee7876kaiw header = 0; 1345db27a04emaste for (i = 0; i < phnum; i++) { 13469ee7876kaiw if (gelf_getphdr(ed->elf, i, &ph) != &ph) { 13479ee7876kaiw warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 13489ee7876kaiw continue; 13499ee7876kaiw } 13509ee7876kaiw if (!STAILQ_EMPTY(&ed->snl) && 1351db27a04emaste find_name(ed, elf_phdr_type_str(ph.p_type)) == NULL) 13529ee7876kaiw continue; 13539ee7876kaiw if (ed->flags & SOLARIS_FMT) { 1354db27a04emaste PRT("\nProgram Header[%zu]:\n", i); 13559ee7876kaiw PRT(" p_vaddr: %#-14jx", (uintmax_t)ph.p_vaddr); 1356db27a04emaste PRT(" p_flags: [ %s ]\n", 1357db27a04emaste p_flags[ph.p_flags & 0x7]); 13589ee7876kaiw PRT(" p_paddr: %#-14jx", (uintmax_t)ph.p_paddr); 1359db27a04emaste PRT(" p_type: [ %s ]\n", 1360db27a04emaste elf_phdr_type_str(ph.p_type)); 13619ee7876kaiw PRT(" p_filesz: %#-14jx", 13629ee7876kaiw (uintmax_t)ph.p_filesz); 13639ee7876kaiw PRT(" p_memsz: %#jx\n", (uintmax_t)ph.p_memsz); 13649ee7876kaiw PRT(" p_offset: %#-14jx", 13659ee7876kaiw (uintmax_t)ph.p_offset); 13669ee7876kaiw PRT(" p_align: %#jx\n", (uintmax_t)ph.p_align); 13679ee7876kaiw } else { 13689ee7876kaiw if (!header) { 13699ee7876kaiw PRT("\nprogram header:\n"); 13709ee7876kaiw header = 1; 13719ee7876kaiw } 13729ee7876kaiw PRT("\n"); 1373db27a04emaste PRT("entry: %zu\n", i); 1374db27a04emaste PRT("\tp_type: %s\n", elf_phdr_type_str(ph.p_type)); 13759ee7876kaiw PRT("\tp_offset: %ju\n", (uintmax_t)ph.p_offset); 13769ee7876kaiw PRT("\tp_vaddr: %#jx\n", (uintmax_t)ph.p_vaddr); 13779ee7876kaiw PRT("\tp_paddr: %#jx\n", (uintmax_t)ph.p_paddr); 13789ee7876kaiw PRT("\tp_filesz: %ju\n", (uintmax_t)ph.p_filesz); 13799ee7876kaiw PRT("\tp_memsz: %ju\n", (uintmax_t)ph.p_memsz); 1380db27a04emaste PRT("\tp_flags: %s\n", p_flags[ph.p_flags & 0x7]); 13819ee7876kaiw PRT("\tp_align: %ju\n", (uintmax_t)ph.p_align); 13829ee7876kaiw } 13839ee7876kaiw } 13849ee7876kaiw} 13859ee7876kaiw 13869ee7876kaiw/* 13879ee7876kaiw * Dump the ELF Section Header Table. 13889ee7876kaiw */ 13899ee7876kaiwstatic void 13909ee7876kaiwelf_print_shdr(struct elfdump *ed) 13919ee7876kaiw{ 13929ee7876kaiw struct section *s; 1393db27a04emaste size_t i; 13949ee7876kaiw 13959ee7876kaiw if (!STAILQ_EMPTY(&ed->snl)) 13969ee7876kaiw return; 13979ee7876kaiw 13989ee7876kaiw if ((ed->flags & SOLARIS_FMT) == 0) 13999ee7876kaiw PRT("\nsection header:\n"); 1400db27a04emaste for (i = 0; i < ed->shnum; i++) { 14019ee7876kaiw s = &ed->sl[i]; 14029ee7876kaiw if (ed->flags & SOLARIS_FMT) { 14039ee7876kaiw if (i == 0) 14049ee7876kaiw continue; 1405db27a04emaste PRT("\nSection Header[%zu]:", i); 14069ee7876kaiw PRT(" sh_name: %s\n", s->name); 14079ee7876kaiw PRT(" sh_addr: %#-14jx", (uintmax_t)s->addr); 14089ee7876kaiw if (s->flags != 0) 14099ee7876kaiw PRT(" sh_flags: [ %s ]\n", sh_flags(s->flags)); 14109ee7876kaiw else 14119ee7876kaiw PRT(" sh_flags: 0\n"); 14129ee7876kaiw PRT(" sh_size: %#-14jx", (uintmax_t)s->sz); 141385217deemaste PRT(" sh_type: [ %s ]\n", 141485217deemaste sh_types(ed->ehdr.e_machine, s->type)); 14159ee7876kaiw PRT(" sh_offset: %#-14jx", (uintmax_t)s->off); 14169ee7876kaiw PRT(" sh_entsize: %#jx\n", (uintmax_t)s->entsize); 14179ee7876kaiw PRT(" sh_link: %-14u", s->link); 14189ee7876kaiw PRT(" sh_info: %u\n", s->info); 14199ee7876kaiw PRT(" sh_addralign: %#jx\n", (uintmax_t)s->align); 14209ee7876kaiw } else { 14219ee7876kaiw PRT("\n"); 14229ee7876kaiw PRT("entry: %ju\n", (uintmax_t)i); 14239ee7876kaiw PRT("\tsh_name: %s\n", s->name); 142485217deemaste PRT("\tsh_type: %s\n", 142585217deemaste sh_types(ed->ehdr.e_machine, s->type)); 14269ee7876kaiw PRT("\tsh_flags: %s\n", sh_flags(s->flags)); 14279ee7876kaiw PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr); 14289ee7876kaiw PRT("\tsh_offset: %ju\n", (uintmax_t)s->off); 14299ee7876kaiw PRT("\tsh_size: %ju\n", (uintmax_t)s->sz); 14309ee7876kaiw PRT("\tsh_link: %u\n", s->link); 14319ee7876kaiw PRT("\tsh_info: %u\n", s->info); 14329ee7876kaiw PRT("\tsh_addralign: %ju\n", (uintmax_t)s->align); 14339ee7876kaiw PRT("\tsh_entsize: %ju\n", (uintmax_t)s->entsize); 14349ee7876kaiw } 14359ee7876kaiw } 14369ee7876kaiw} 14379ee7876kaiw 14389ee7876kaiw/* 1439f776db0emaste * Return number of entries in the given section. We'd prefer ent_count be a 1440f776db0emaste * size_t, but libelf APIs already use int for section indices. 1441f776db0emaste */ 1442f776db0emastestatic int 1443f776db0emasteget_ent_count(const struct section *s, int *ent_count) 1444f776db0emaste{ 1445f776db0emaste if (s->entsize == 0) { 1446f776db0emaste warnx("section %s has entry size 0", s->name); 1447f776db0emaste return (0); 1448f776db0emaste } else if (s->sz / s->entsize > INT_MAX) { 1449f776db0emaste warnx("section %s has invalid section count", s->name); 1450f776db0emaste return (0); 1451f776db0emaste } 1452f776db0emaste *ent_count = (int)(s->sz / s->entsize); 1453f776db0emaste return (1); 1454f776db0emaste} 1455f776db0emaste 1456f776db0emaste/* 14579ee7876kaiw * Retrieve the content of the corresponding SHT_SUNW_versym section for 14589ee7876kaiw * a symbol table section. 14599ee7876kaiw */ 14609ee7876kaiwstatic void 14619ee7876kaiwget_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs) 14629ee7876kaiw{ 14639ee7876kaiw struct section *s; 14649ee7876kaiw Elf_Data *data; 1465db27a04emaste size_t j; 1466db27a04emaste int elferr; 14679ee7876kaiw 14689ee7876kaiw s = NULL; 1469db27a04emaste for (j = 0; j < ed->shnum; j++) { 14709ee7876kaiw s = &ed->sl[j]; 14719ee7876kaiw if (s->type == SHT_SUNW_versym && s->link == (uint32_t)i) 14729ee7876kaiw break; 14739ee7876kaiw } 1474db27a04emaste if (j >= ed->shnum) { 14759ee7876kaiw *vs = NULL; 14769ee7876kaiw return; 14779ee7876kaiw } 14789ee7876kaiw (void) elf_errno(); 14799ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 14809ee7876kaiw elferr = elf_errno(); 14819ee7876kaiw if (elferr != 0) 14829ee7876kaiw warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 14839ee7876kaiw *vs = NULL; 14849ee7876kaiw return; 14859ee7876kaiw } 14869ee7876kaiw 14879ee7876kaiw *vs = data->d_buf; 1488f776db0emaste assert(data->d_size == s->sz); 1489f776db0emaste if (!get_ent_count(s, nvs)) 1490f776db0emaste *nvs = 0; 14919ee7876kaiw} 14929ee7876kaiw 14939ee7876kaiw/* 14949ee7876kaiw * Dump the symbol table section. 14959ee7876kaiw */ 14969ee7876kaiwstatic void 14979ee7876kaiwelf_print_symtab(struct elfdump *ed, int i) 14989ee7876kaiw{ 14999ee7876kaiw struct section *s; 15009ee7876kaiw const char *name; 15019ee7876kaiw uint16_t *vs; 1502b4985c2emaste char idx[13]; 15039ee7876kaiw Elf_Data *data; 15049ee7876kaiw GElf_Sym sym; 15059ee7876kaiw int len, j, elferr, nvs; 15069ee7876kaiw 15079ee7876kaiw s = &ed->sl[i]; 15089ee7876kaiw if (ed->flags & SOLARIS_FMT) 15099ee7876kaiw PRT("\nSymbol Table Section: %s\n", s->name); 15109ee7876kaiw else 15119ee7876kaiw PRT("\nsymbol table (%s):\n", s->name); 15129ee7876kaiw (void) elf_errno(); 15139ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 15149ee7876kaiw elferr = elf_errno(); 15159ee7876kaiw if (elferr != 0) 15169ee7876kaiw warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 15179ee7876kaiw return; 15189ee7876kaiw } 15199ee7876kaiw vs = NULL; 15209ee7876kaiw nvs = 0; 1521f776db0emaste assert(data->d_size == s->sz); 1522f776db0emaste if (!get_ent_count(s, &len)) 1523f776db0emaste return; 15249ee7876kaiw if (ed->flags & SOLARIS_FMT) { 15259ee7876kaiw if (ed->ec == ELFCLASS32) 15269ee7876kaiw PRT(" index value "); 15279ee7876kaiw else 15289ee7876kaiw PRT(" index value "); 15299ee7876kaiw PRT("size type bind oth ver shndx name\n"); 15309ee7876kaiw get_versym(ed, i, &vs, &nvs); 15319ee7876kaiw if (vs != NULL && nvs != len) { 15329ee7876kaiw warnx("#symbol not equal to #versym"); 15339ee7876kaiw vs = NULL; 15349ee7876kaiw } 15359ee7876kaiw } 15369ee7876kaiw for (j = 0; j < len; j++) { 15379ee7876kaiw if (gelf_getsym(data, j, &sym) != &sym) { 15389ee7876kaiw warnx("gelf_getsym failed: %s", elf_errmsg(-1)); 15399ee7876kaiw continue; 15409ee7876kaiw } 15419ee7876kaiw name = get_string(ed, s->link, sym.st_name); 15429ee7876kaiw if (ed->flags & SOLARIS_FMT) { 15439ee7876kaiw snprintf(idx, sizeof(idx), "[%d]", j); 15449ee7876kaiw if (ed->ec == ELFCLASS32) 15459ee7876kaiw PRT("%10s ", idx); 15469ee7876kaiw else 15479ee7876kaiw PRT("%10s ", idx); 15489ee7876kaiw PRT("0x%8.8jx ", (uintmax_t)sym.st_value); 15499ee7876kaiw if (ed->ec == ELFCLASS32) 15509ee7876kaiw PRT("0x%8.8jx ", (uintmax_t)sym.st_size); 15519ee7876kaiw else 15529ee7876kaiw PRT("0x%12.12jx ", (uintmax_t)sym.st_size); 155385217deemaste PRT("%s ", st_type_S(GELF_ST_TYPE(sym.st_info))); 155485217deemaste PRT("%s ", st_bindings_S(GELF_ST_BIND(sym.st_info))); 15559ee7876kaiw PRT("%c ", st_others[sym.st_other]); 15569ee7876kaiw PRT("%3u ", (vs == NULL ? 0 : vs[j])); 15579ee7876kaiw PRT("%-11.11s ", sh_name(ed, sym.st_shndx)); 15589ee7876kaiw PRT("%s\n", name); 15599ee7876kaiw } else { 15609ee7876kaiw PRT("\nentry: %d\n", j); 15619ee7876kaiw PRT("\tst_name: %s\n", name); 15629ee7876kaiw PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value); 15639ee7876kaiw PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size); 15649ee7876kaiw PRT("\tst_info: %s %s\n", 156585217deemaste st_type(ed->ehdr.e_machine, 156685217deemaste GELF_ST_TYPE(sym.st_info)), 156785217deemaste st_bindings(GELF_ST_BIND(sym.st_info))); 15689ee7876kaiw PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx); 15699ee7876kaiw } 15709ee7876kaiw } 15719ee7876kaiw} 15729ee7876kaiw 15739ee7876kaiw/* 15749ee7876kaiw * Dump the symbol tables. (.dynsym and .symtab) 15759ee7876kaiw */ 15769ee7876kaiwstatic void 15779ee7876kaiwelf_print_symtabs(struct elfdump *ed) 15789ee7876kaiw{ 1579db27a04emaste size_t i; 15809ee7876kaiw 1581db27a04emaste for (i = 0; i < ed->shnum; i++) 15829ee7876kaiw if ((ed->sl[i].type == SHT_SYMTAB || 15839ee7876kaiw ed->sl[i].type == SHT_DYNSYM) && 15849ee7876kaiw (STAILQ_EMPTY(&ed->snl) || find_name(ed, ed->sl[i].name))) 15859ee7876kaiw elf_print_symtab(ed, i); 15869ee7876kaiw} 15879ee7876kaiw 15889ee7876kaiw/* 15899ee7876kaiw * Dump the content of .dynamic section. 15909ee7876kaiw */ 15919ee7876kaiwstatic void 15929ee7876kaiwelf_print_dynamic(struct elfdump *ed) 15939ee7876kaiw{ 15949ee7876kaiw struct section *s; 15959ee7876kaiw const char *name; 1596b4985c2emaste char idx[13]; 15979ee7876kaiw Elf_Data *data; 15989ee7876kaiw GElf_Dyn dyn; 15999ee7876kaiw int elferr, i, len; 16009ee7876kaiw 16019ee7876kaiw s = NULL; 16029ee7876kaiw for (i = 0; (size_t)i < ed->shnum; i++) { 16039ee7876kaiw s = &ed->sl[i]; 16049ee7876kaiw if (s->type == SHT_DYNAMIC && 16059ee7876kaiw (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 16069ee7876kaiw break; 16079ee7876kaiw } 16089ee7876kaiw if ((size_t)i >= ed->shnum) 16099ee7876kaiw return; 16109ee7876kaiw 16119ee7876kaiw if (ed->flags & SOLARIS_FMT) { 16129ee7876kaiw PRT("Dynamic Section: %s\n", s->name); 16139ee7876kaiw PRT(" index tag value\n"); 16149ee7876kaiw } else 16159ee7876kaiw PRT("\ndynamic:\n"); 16169ee7876kaiw (void) elf_errno(); 16179ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 16189ee7876kaiw elferr = elf_errno(); 16199ee7876kaiw if (elferr != 0) 16209ee7876kaiw warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 16219ee7876kaiw return; 16229ee7876kaiw } 1623f776db0emaste assert(data->d_size == s->sz); 1624f776db0emaste if (!get_ent_count(s, &len)) 1625f776db0emaste return; 16269ee7876kaiw for (i = 0; i < len; i++) { 16279ee7876kaiw if (gelf_getdyn(data, i, &dyn) != &dyn) { 16289ee7876kaiw warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); 16299ee7876kaiw continue; 16309ee7876kaiw } 16319ee7876kaiw 16329ee7876kaiw if (ed->flags & SOLARIS_FMT) { 16339ee7876kaiw snprintf(idx, sizeof(idx), "[%d]", i); 16349ee7876kaiw PRT("%10s %-16s ", idx, d_tags(dyn.d_tag)); 16359ee7876kaiw } else { 16369ee7876kaiw PRT("\n"); 16379ee7876kaiw PRT("entry: %d\n", i); 16389ee7876kaiw PRT("\td_tag: %s\n", d_tags(dyn.d_tag)); 16399ee7876kaiw } 16409ee7876kaiw switch(dyn.d_tag) { 16419ee7876kaiw case DT_NEEDED: 16429ee7876kaiw case DT_SONAME: 16439ee7876kaiw case DT_RPATH: 1644db27a04emaste case DT_RUNPATH: 16459ee7876kaiw if ((name = elf_strptr(ed->elf, s->link, 16469ee7876kaiw dyn.d_un.d_val)) == NULL) 16479ee7876kaiw name = ""; 16489ee7876kaiw if (ed->flags & SOLARIS_FMT) 16499ee7876kaiw PRT("%#-16jx %s\n", (uintmax_t)dyn.d_un.d_val, 16509ee7876kaiw name); 16519ee7876kaiw else 16529ee7876kaiw PRT("\td_val: %s\n", name); 16539ee7876kaiw break; 16549ee7876kaiw case DT_PLTRELSZ: 16559ee7876kaiw case DT_RELA: 16569ee7876kaiw case DT_RELASZ: 16579ee7876kaiw case DT_RELAENT: 16589ee7876kaiw case DT_RELACOUNT: 16599ee7876kaiw case DT_STRSZ: 16609ee7876kaiw case DT_SYMENT: 16619ee7876kaiw case DT_RELSZ: 16629ee7876kaiw case DT_RELENT: 16639ee7876kaiw case DT_PLTREL: 16649ee7876kaiw case DT_VERDEF: 16659ee7876kaiw case DT_VERDEFNUM: 16669ee7876kaiw case DT_VERNEED: 16679ee7876kaiw case DT_VERNEEDNUM: 16689ee7876kaiw case DT_VERSYM: 16699ee7876kaiw if (ed->flags & SOLARIS_FMT) 16709ee7876kaiw PRT("%#jx\n", (uintmax_t)dyn.d_un.d_val); 16719ee7876kaiw else 16729ee7876kaiw PRT("\td_val: %ju\n", 16739ee7876kaiw (uintmax_t)dyn.d_un.d_val); 16749ee7876kaiw break; 16759ee7876kaiw case DT_PLTGOT: 16769ee7876kaiw case DT_HASH: 16779ee7876kaiw case DT_GNU_HASH: 16789ee7876kaiw case DT_STRTAB: 16799ee7876kaiw case DT_SYMTAB: 16809ee7876kaiw case DT_INIT: 16819ee7876kaiw case DT_FINI: 16829ee7876kaiw case DT_REL: 16839ee7876kaiw case DT_JMPREL: 16849ee7876kaiw case DT_DEBUG: 16859ee7876kaiw if (ed->flags & SOLARIS_FMT) 16869ee7876kaiw PRT("%#jx\n", (uintmax_t)dyn.d_un.d_ptr); 16879ee7876kaiw else 16889ee7876kaiw PRT("\td_ptr: %#jx\n", 16899ee7876kaiw (uintmax_t)dyn.d_un.d_ptr); 16909ee7876kaiw break; 16919ee7876kaiw case DT_NULL: 16929ee7876kaiw case DT_SYMBOLIC: 16939ee7876kaiw case DT_TEXTREL: 16949ee7876kaiw default: 16959ee7876kaiw if (ed->flags & SOLARIS_FMT) 16969ee7876kaiw PRT("\n"); 16979ee7876kaiw break; 16989ee7876kaiw } 16999ee7876kaiw } 17009ee7876kaiw} 17019ee7876kaiw 17029ee7876kaiw/* 17039ee7876kaiw * Dump a .rel/.rela section entry. 17049ee7876kaiw */ 17059ee7876kaiwstatic void 17069ee7876kaiwelf_print_rel_entry(struct elfdump *ed, struct section *s, int j, 17079ee7876kaiw struct rel_entry *r) 17089ee7876kaiw{ 17099ee7876kaiw 17109ee7876kaiw if (ed->flags & SOLARIS_FMT) { 1711db27a04emaste PRT(" %-23s ", elftc_reloc_type_str(ed->ehdr.e_machine, 17129ee7876kaiw GELF_R_TYPE(r->u_r.rel.r_info))); 17139ee7876kaiw PRT("%#12jx ", (uintmax_t)r->u_r.rel.r_offset); 17149ee7876kaiw if (r->type == SHT_RELA) 17159ee7876kaiw PRT("%10jd ", (intmax_t)r->u_r.rela.r_addend); 17169ee7876kaiw else 17179ee7876kaiw PRT(" "); 17189ee7876kaiw PRT("%-14s ", s->name); 17199ee7876kaiw PRT("%s\n", r->symn); 17209ee7876kaiw } else { 17219ee7876kaiw PRT("\n"); 17229ee7876kaiw PRT("entry: %d\n", j); 17239ee7876kaiw PRT("\tr_offset: %#jx\n", (uintmax_t)r->u_r.rel.r_offset); 17249ee7876kaiw if (ed->ec == ELFCLASS32) 17259ee7876kaiw PRT("\tr_info: %#jx\n", (uintmax_t) 17269ee7876kaiw ELF32_R_INFO(ELF64_R_SYM(r->u_r.rel.r_info), 17279ee7876kaiw ELF64_R_TYPE(r->u_r.rel.r_info))); 17289ee7876kaiw else 17299ee7876kaiw PRT("\tr_info: %#jx\n", (uintmax_t)r->u_r.rel.r_info); 17309ee7876kaiw if (r->type == SHT_RELA) 17319ee7876kaiw PRT("\tr_addend: %jd\n", 17329ee7876kaiw (intmax_t)r->u_r.rela.r_addend); 17339ee7876kaiw } 17349ee7876kaiw} 17359ee7876kaiw 17369ee7876kaiw/* 17379ee7876kaiw * Dump a relocation section of type SHT_RELA. 17389ee7876kaiw */ 17399ee7876kaiwstatic void 17409ee7876kaiwelf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data) 17419ee7876kaiw{ 17429ee7876kaiw struct rel_entry r; 17439ee7876kaiw int j, len; 17449ee7876kaiw 17459ee7876kaiw if (ed->flags & SOLARIS_FMT) { 17469ee7876kaiw PRT("\nRelocation Section: %s\n", s->name); 17479ee7876kaiw PRT(" type offset " 17489ee7876kaiw "addend section with respect to\n"); 17499ee7876kaiw } else 17509ee7876kaiw PRT("\nrelocation with addend (%s):\n", s->name); 17519ee7876kaiw r.type = SHT_RELA; 1752f776db0emaste assert(data->d_size == s->sz); 1753f776db0emaste if (!get_ent_count(s, &len)) 1754f776db0emaste return; 17559ee7876kaiw for (j = 0; j < len; j++) { 17569ee7876kaiw if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) { 17579ee7876kaiw warnx("gelf_getrela failed: %s", 17589ee7876kaiw elf_errmsg(-1)); 17599ee7876kaiw continue; 17609ee7876kaiw } 17619ee7876kaiw r.symn = get_symbol_name(ed, s->link, 17629ee7876kaiw GELF_R_SYM(r.u_r.rela.r_info)); 17639ee7876kaiw elf_print_rel_entry(ed, s, j, &r); 17649ee7876kaiw } 17659ee7876kaiw} 17669ee7876kaiw 17679ee7876kaiw/* 17689ee7876kaiw * Dump a relocation section of type SHT_REL. 17699ee7876kaiw */ 17709ee7876kaiwstatic void 17719ee7876kaiwelf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data) 17729ee7876kaiw{ 17739ee7876kaiw struct rel_entry r; 17749ee7876kaiw int j, len; 17759ee7876kaiw 17769ee7876kaiw if (ed->flags & SOLARIS_FMT) { 17779ee7876kaiw PRT("\nRelocation Section: %s\n", s->name); 17789ee7876kaiw PRT(" type offset " 17799ee7876kaiw "section with respect to\n"); 17809ee7876kaiw } else 17819ee7876kaiw PRT("\nrelocation (%s):\n", s->name); 17829ee7876kaiw r.type = SHT_REL; 1783f776db0emaste assert(data->d_size == s->sz); 1784f776db0emaste if (!get_ent_count(s, &len)) 1785f776db0emaste return; 17869ee7876kaiw for (j = 0; j < len; j++) { 17879ee7876kaiw if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) { 17889ee7876kaiw warnx("gelf_getrel failed: %s", elf_errmsg(-1)); 17899ee7876kaiw continue; 17909ee7876kaiw } 17919ee7876kaiw r.symn = get_symbol_name(ed, s->link, 17929ee7876kaiw GELF_R_SYM(r.u_r.rel.r_info)); 17939ee7876kaiw elf_print_rel_entry(ed, s, j, &r); 17949ee7876kaiw } 17959ee7876kaiw} 17969ee7876kaiw 17979ee7876kaiw/* 17989ee7876kaiw * Dump relocation sections. 17999ee7876kaiw */ 18009ee7876kaiwstatic void 18019ee7876kaiwelf_print_reloc(struct elfdump *ed) 18029ee7876kaiw{ 18039ee7876kaiw struct section *s; 18049ee7876kaiw Elf_Data *data; 1805db27a04emaste size_t i; 1806db27a04emaste int elferr; 18079ee7876kaiw 1808db27a04emaste for (i = 0; i < ed->shnum; i++) { 18099ee7876kaiw s = &ed->sl[i]; 18109ee7876kaiw if ((s->type == SHT_REL || s->type == SHT_RELA) && 18119ee7876kaiw (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 18129ee7876kaiw (void) elf_errno(); 18139ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 18149ee7876kaiw elferr = elf_errno(); 18159ee7876kaiw if (elferr != 0) 18169ee7876kaiw warnx("elf_getdata failed: %s", 18179ee7876kaiw elf_errmsg(elferr)); 18189ee7876kaiw continue; 18199ee7876kaiw } 18209ee7876kaiw if (s->type == SHT_REL) 18219ee7876kaiw elf_print_rel(ed, s, data); 18229ee7876kaiw else 18239ee7876kaiw elf_print_rela(ed, s, data); 18249ee7876kaiw } 18259ee7876kaiw } 18269ee7876kaiw} 18279ee7876kaiw 18289ee7876kaiw/* 18299ee7876kaiw * Dump the content of PT_INTERP segment. 18309ee7876kaiw */ 18319ee7876kaiwstatic void 18329ee7876kaiwelf_print_interp(struct elfdump *ed) 18339ee7876kaiw{ 18349ee7876kaiw const char *s; 18359ee7876kaiw GElf_Phdr phdr; 1836db27a04emaste size_t filesize, i, phnum; 18379ee7876kaiw 18389ee7876kaiw if (!STAILQ_EMPTY(&ed->snl) && find_name(ed, "PT_INTERP") == NULL) 18399ee7876kaiw return; 18409ee7876kaiw 1841db27a04emaste if ((s = elf_rawfile(ed->elf, &filesize)) == NULL) { 18429ee7876kaiw warnx("elf_rawfile failed: %s", elf_errmsg(-1)); 18439ee7876kaiw return; 18449ee7876kaiw } 18459ee7876kaiw if (!elf_getphnum(ed->elf, &phnum)) { 18469ee7876kaiw warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 18479ee7876kaiw return; 18489ee7876kaiw } 1849db27a04emaste for (i = 0; i < phnum; i++) { 18509ee7876kaiw if (gelf_getphdr(ed->elf, i, &phdr) != &phdr) { 18519ee7876kaiw warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 18529ee7876kaiw continue; 18539ee7876kaiw } 18549ee7876kaiw if (phdr.p_type == PT_INTERP) { 1855db27a04emaste if (phdr.p_offset >= filesize) { 1856db27a04emaste warnx("invalid phdr offset"); 1857db27a04emaste continue; 1858db27a04emaste } 18599ee7876kaiw PRT("\ninterp:\n"); 18609ee7876kaiw PRT("\t%s\n", s + phdr.p_offset); 18619ee7876kaiw } 18629ee7876kaiw } 18639ee7876kaiw} 18649ee7876kaiw 18659ee7876kaiw/* 1866db27a04emaste * Search the relocation sections for entries referring to the .got section. 18679ee7876kaiw */ 18689ee7876kaiwstatic void 18699ee7876kaiwfind_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got) 18709ee7876kaiw{ 18719ee7876kaiw struct section *s; 18729ee7876kaiw struct rel_entry r; 18739ee7876kaiw Elf_Data *data; 1874db27a04emaste size_t i; 1875db27a04emaste int elferr, j, k, len; 18769ee7876kaiw 1877db27a04emaste for(i = 0; i < ed->shnum; i++) { 18789ee7876kaiw s = &ed->sl[i]; 18799ee7876kaiw if (s->type != SHT_REL && s->type != SHT_RELA) 18809ee7876kaiw continue; 18819ee7876kaiw (void) elf_errno(); 18829ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 18839ee7876kaiw elferr = elf_errno(); 18849ee7876kaiw if (elferr != 0) 18859ee7876kaiw warnx("elf_getdata failed: %s", 18869ee7876kaiw elf_errmsg(elferr)); 18879ee7876kaiw return; 18889ee7876kaiw } 18899ee7876kaiw memset(&r, 0, sizeof(struct rel_entry)); 18909ee7876kaiw r.type = s->type; 1891f776db0emaste assert(data->d_size == s->sz); 1892f776db0emaste if (!get_ent_count(s, &len)) 1893f776db0emaste return; 18949ee7876kaiw for (j = 0; j < len; j++) { 18959ee7876kaiw if (s->type == SHT_REL) { 18969ee7876kaiw if (gelf_getrel(data, j, &r.u_r.rel) != 18979ee7876kaiw &r.u_r.rel) { 18989ee7876kaiw warnx("gelf_getrel failed: %s", 18999ee7876kaiw elf_errmsg(-1)); 19009ee7876kaiw continue; 19019ee7876kaiw } 19029ee7876kaiw } else { 19039ee7876kaiw if (gelf_getrela(data, j, &r.u_r.rela) != 19049ee7876kaiw &r.u_r.rela) { 19059ee7876kaiw warnx("gelf_getrel failed: %s", 19069ee7876kaiw elf_errmsg(-1)); 19079ee7876kaiw continue; 19089ee7876kaiw } 19099ee7876kaiw } 19109ee7876kaiw if (r.u_r.rel.r_offset >= gs->addr && 19119ee7876kaiw r.u_r.rel.r_offset < gs->addr + gs->sz) { 19129ee7876kaiw r.symn = get_symbol_name(ed, s->link, 19139ee7876kaiw GELF_R_SYM(r.u_r.rel.r_info)); 19149ee7876kaiw k = (r.u_r.rel.r_offset - gs->addr) / 19159ee7876kaiw gs->entsize; 19169ee7876kaiw memcpy(&got[k], &r, sizeof(struct rel_entry)); 19179ee7876kaiw } 19189ee7876kaiw } 19199ee7876kaiw } 19209ee7876kaiw} 19219ee7876kaiw 19229ee7876kaiwstatic void 19239ee7876kaiwelf_print_got_section(struct elfdump *ed, struct section *s) 19249ee7876kaiw{ 19259ee7876kaiw struct rel_entry *got; 19269ee7876kaiw Elf_Data *data, dst; 19279ee7876kaiw int elferr, i, len; 19289ee7876kaiw 19299ee7876kaiw if (s->entsize == 0) { 19309ee7876kaiw /* XXX IA64 GOT section generated by gcc has entry size 0. */ 19319ee7876kaiw if (s->align != 0) 19329ee7876kaiw s->entsize = s->align; 19339ee7876kaiw else 19349ee7876kaiw return; 19359ee7876kaiw } 19369ee7876kaiw 1937f776db0emaste if (!get_ent_count(s, &len)) 1938f776db0emaste return; 19399ee7876kaiw if (ed->flags & SOLARIS_FMT) 1940f776db0emaste PRT("\nGlobal Offset Table Section: %s (%d entries)\n", 1941f776db0emaste s->name, len); 19429ee7876kaiw else 19439ee7876kaiw PRT("\nglobal offset table: %s\n", s->name); 19449ee7876kaiw (void) elf_errno(); 19459ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 19469ee7876kaiw elferr = elf_errno(); 19479ee7876kaiw if (elferr != 0) 19489ee7876kaiw warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 19499ee7876kaiw return; 19509ee7876kaiw } 19519ee7876kaiw 19529ee7876kaiw /* 19539ee7876kaiw * GOT section has section type SHT_PROGBITS, thus libelf treats it as 1954db27a04emaste * byte stream and will not perform any translation on it. As a result, 19559ee7876kaiw * an exlicit call to gelf_xlatetom is needed here. Depends on arch, 19569ee7876kaiw * GOT section should be translated to either WORD or XWORD. 19579ee7876kaiw */ 19589ee7876kaiw if (ed->ec == ELFCLASS32) 19599ee7876kaiw data->d_type = ELF_T_WORD; 19609ee7876kaiw else 19619ee7876kaiw data->d_type = ELF_T_XWORD; 19629ee7876kaiw memcpy(&dst, data, sizeof(Elf_Data)); 19639ee7876kaiw if (gelf_xlatetom(ed->elf, &dst, data, ed->ehdr.e_ident[EI_DATA]) != 19649ee7876kaiw &dst) { 19659ee7876kaiw warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 19669ee7876kaiw return; 19679ee7876kaiw } 1968f776db0emaste assert(dst.d_size == s->sz); 19699ee7876kaiw if (ed->flags & SOLARIS_FMT) { 19709ee7876kaiw /* 19719ee7876kaiw * In verbose/Solaris mode, we search the relocation sections 19729ee7876kaiw * and try to find the corresponding reloc entry for each GOT 19739ee7876kaiw * section entry. 19749ee7876kaiw */ 19759ee7876kaiw if ((got = calloc(len, sizeof(struct rel_entry))) == NULL) 19769ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 19779ee7876kaiw find_gotrel(ed, s, got); 19789ee7876kaiw if (ed->ec == ELFCLASS32) { 19799ee7876kaiw PRT(" ndx addr value reloc "); 19809ee7876kaiw PRT("addend symbol\n"); 19819ee7876kaiw } else { 19829ee7876kaiw PRT(" ndx addr value "); 19839ee7876kaiw PRT("reloc addend symbol\n"); 19849ee7876kaiw } 19859ee7876kaiw for(i = 0; i < len; i++) { 19869ee7876kaiw PRT("[%5.5d] ", i); 19879ee7876kaiw if (ed->ec == ELFCLASS32) { 198885217deemaste PRT("%-8.8jx ", 198985217deemaste (uintmax_t) (s->addr + i * s->entsize)); 19909ee7876kaiw PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i)); 19919ee7876kaiw } else { 199285217deemaste PRT("%-16.16jx ", 199385217deemaste (uintmax_t) (s->addr + i * s->entsize)); 199485217deemaste PRT("%-16.16jx ", 199585217deemaste (uintmax_t) *((uint64_t *)dst.d_buf + i)); 19969ee7876kaiw } 1997db27a04emaste PRT("%-18s ", elftc_reloc_type_str(ed->ehdr.e_machine, 19989ee7876kaiw GELF_R_TYPE(got[i].u_r.rel.r_info))); 19999ee7876kaiw if (ed->ec == ELFCLASS32) 20009ee7876kaiw PRT("%-8.8jd ", 20019ee7876kaiw (intmax_t)got[i].u_r.rela.r_addend); 20029ee7876kaiw else 20039ee7876kaiw PRT("%-12.12jd ", 20049ee7876kaiw (intmax_t)got[i].u_r.rela.r_addend); 20059ee7876kaiw if (got[i].symn == NULL) 20069ee7876kaiw got[i].symn = ""; 20079ee7876kaiw PRT("%s\n", got[i].symn); 20089ee7876kaiw } 20099ee7876kaiw free(got); 20109ee7876kaiw } else { 20119ee7876kaiw for(i = 0; i < len; i++) { 20129ee7876kaiw PRT("\nentry: %d\n", i); 20139ee7876kaiw if (ed->ec == ELFCLASS32) 20149ee7876kaiw PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i)); 20159ee7876kaiw else 201685217deemaste PRT("\t%#jx\n", 201785217deemaste (uintmax_t) *((uint64_t *)dst.d_buf + i)); 20189ee7876kaiw } 20199ee7876kaiw } 20209ee7876kaiw} 20219ee7876kaiw 20229ee7876kaiw/* 20239ee7876kaiw * Dump the content of Global Offset Table section. 20249ee7876kaiw */ 20259ee7876kaiwstatic void 20269ee7876kaiwelf_print_got(struct elfdump *ed) 20279ee7876kaiw{ 20289ee7876kaiw struct section *s; 2029db27a04emaste size_t i; 20309ee7876kaiw 20319ee7876kaiw if (!STAILQ_EMPTY(&ed->snl)) 20329ee7876kaiw return; 20339ee7876kaiw 20349ee7876kaiw s = NULL; 2035db27a04emaste for (i = 0; i < ed->shnum; i++) { 20369ee7876kaiw s = &ed->sl[i]; 20379ee7876kaiw if (s->name && !strncmp(s->name, ".got", 4) && 20389ee7876kaiw (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 20399ee7876kaiw elf_print_got_section(ed, s); 20409ee7876kaiw } 20419ee7876kaiw} 20429ee7876kaiw 20439ee7876kaiw/* 20449ee7876kaiw * Dump the content of .note.ABI-tag section. 20459ee7876kaiw */ 20469ee7876kaiwstatic void 20479ee7876kaiwelf_print_note(struct elfdump *ed) 20489ee7876kaiw{ 20499ee7876kaiw struct section *s; 20509ee7876kaiw Elf_Data *data; 20519ee7876kaiw Elf_Note *en; 20529ee7876kaiw uint32_t namesz; 20539ee7876kaiw uint32_t descsz; 20549ee7876kaiw uint32_t desc; 20559ee7876kaiw size_t count; 20569ee7876kaiw int elferr, i; 2057db27a04emaste uint8_t *src; 2058b4985c2emaste char idx[17]; 20599ee7876kaiw 20609ee7876kaiw s = NULL; 20619ee7876kaiw for (i = 0; (size_t)i < ed->shnum; i++) { 20629ee7876kaiw s = &ed->sl[i]; 20639ee7876kaiw if (s->type == SHT_NOTE && s->name && 20649ee7876kaiw !strcmp(s->name, ".note.ABI-tag") && 20659ee7876kaiw (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 20669ee7876kaiw break; 20679ee7876kaiw } 20689ee7876kaiw if ((size_t)i >= ed->shnum) 20699ee7876kaiw return; 20709ee7876kaiw if (ed->flags & SOLARIS_FMT) 20719ee7876kaiw PRT("\nNote Section: %s\n", s->name); 20729ee7876kaiw else 20739ee7876kaiw PRT("\nnote (%s):\n", s->name); 20749ee7876kaiw (void) elf_errno(); 20759ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 20769ee7876kaiw elferr = elf_errno(); 20779ee7876kaiw if (elferr != 0) 20789ee7876kaiw warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 20799ee7876kaiw return; 20809ee7876kaiw } 20819ee7876kaiw src = data->d_buf; 20829ee7876kaiw count = data->d_size; 20839ee7876kaiw while (count > sizeof(Elf_Note)) { 20849ee7876kaiw en = (Elf_Note *) (uintptr_t) src; 20859ee7876kaiw namesz = en->n_namesz; 20869ee7876kaiw descsz = en->n_descsz; 20879ee7876kaiw src += sizeof(Elf_Note); 20889ee7876kaiw count -= sizeof(Elf_Note); 2089db27a04emaste if (roundup2(namesz, 4) + roundup2(descsz, 4) > count) { 2090db27a04emaste warnx("truncated note section"); 2091db27a04emaste return; 2092db27a04emaste } 20939ee7876kaiw if (ed->flags & SOLARIS_FMT) { 20949ee7876kaiw PRT("\n type %#x\n", en->n_type); 20959ee7876kaiw PRT(" namesz %#x:\n", en->n_namesz); 20969ee7876kaiw PRT("%s\n", src); 20979ee7876kaiw } else 20989ee7876kaiw PRT("\t%s ", src); 20999ee7876kaiw src += roundup2(namesz, 4); 21009ee7876kaiw count -= roundup2(namesz, 4); 21019ee7876kaiw 21029ee7876kaiw /* 21039ee7876kaiw * Note that we dump the whole desc part if we're in 21049ee7876kaiw * "Solaris mode", while in the normal mode, we only look 21059ee7876kaiw * at the first 4 bytes (a 32bit word) of the desc, i.e, 21069ee7876kaiw * we assume that it's always a FreeBSD version number. 21079ee7876kaiw */ 21089ee7876kaiw if (ed->flags & SOLARIS_FMT) { 21099ee7876kaiw PRT(" descsz %#x:", en->n_descsz); 21109ee7876kaiw for (i = 0; (uint32_t)i < descsz; i++) { 21119ee7876kaiw if ((i & 0xF) == 0) { 21129ee7876kaiw snprintf(idx, sizeof(idx), "desc[%d]", 21139ee7876kaiw i); 21149ee7876kaiw PRT("\n %-9s", idx); 21159ee7876kaiw } else if ((i & 0x3) == 0) 21169ee7876kaiw PRT(" "); 21179ee7876kaiw PRT(" %2.2x", src[i]); 21189ee7876kaiw } 21199ee7876kaiw PRT("\n"); 21209ee7876kaiw } else { 21219ee7876kaiw if (ed->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) 21229ee7876kaiw desc = be32dec(src); 21239ee7876kaiw else 21249ee7876kaiw desc = le32dec(src); 21259ee7876kaiw PRT("%d\n", desc); 21269ee7876kaiw } 21279ee7876kaiw src += roundup2(descsz, 4); 21289ee7876kaiw count -= roundup2(descsz, 4); 21299ee7876kaiw } 21309ee7876kaiw} 21319ee7876kaiw 21329ee7876kaiw/* 21339ee7876kaiw * Dump a hash table. 21349ee7876kaiw */ 21359ee7876kaiwstatic void 21369ee7876kaiwelf_print_svr4_hash(struct elfdump *ed, struct section *s) 21379ee7876kaiw{ 21389ee7876kaiw Elf_Data *data; 21399ee7876kaiw uint32_t *buf; 21409ee7876kaiw uint32_t *bucket, *chain; 21419ee7876kaiw uint32_t nbucket, nchain; 21429ee7876kaiw uint32_t *bl, *c, maxl, total; 2143db27a04emaste uint32_t i, j; 2144db27a04emaste int first, elferr; 21459ee7876kaiw char idx[10]; 21469ee7876kaiw 21479ee7876kaiw if (ed->flags & SOLARIS_FMT) 21489ee7876kaiw PRT("\nHash Section: %s\n", s->name); 21499ee7876kaiw else 21509ee7876kaiw PRT("\nhash table (%s):\n", s->name); 21519ee7876kaiw (void) elf_errno(); 21529ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 21539ee7876kaiw elferr = elf_errno(); 21549ee7876kaiw if (elferr != 0) 21559ee7876kaiw warnx("elf_getdata failed: %s", 21569ee7876kaiw elf_errmsg(elferr)); 21579ee7876kaiw return; 21589ee7876kaiw } 21599ee7876kaiw if (data->d_size < 2 * sizeof(uint32_t)) { 21609ee7876kaiw warnx(".hash section too small"); 21619ee7876kaiw return; 21629ee7876kaiw } 21639ee7876kaiw buf = data->d_buf; 21649ee7876kaiw nbucket = buf[0]; 21659ee7876kaiw nchain = buf[1]; 21669ee7876kaiw if (nbucket <= 0 || nchain <= 0) { 21679ee7876kaiw warnx("Malformed .hash section"); 21689ee7876kaiw return; 21699ee7876kaiw } 2170db27a04emaste if (data->d_size != 2171db27a04emaste ((uint64_t)nbucket + (uint64_t)nchain + 2) * sizeof(uint32_t)) { 21729ee7876kaiw warnx("Malformed .hash section"); 21739ee7876kaiw return; 21749ee7876kaiw } 21759ee7876kaiw bucket = &buf[2]; 21769ee7876kaiw chain = &buf[2 + nbucket]; 21779ee7876kaiw 21789ee7876kaiw if (ed->flags & SOLARIS_FMT) { 21799ee7876kaiw maxl = 0; 21809ee7876kaiw if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 21819ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 2182db27a04emaste for (i = 0; i < nbucket; i++) 2183db27a04emaste for (j = bucket[i]; j > 0 && j < nchain; j = chain[j]) 21849ee7876kaiw if (++bl[i] > maxl) 21859ee7876kaiw maxl = bl[i]; 21869ee7876kaiw if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 21879ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 2188db27a04emaste for (i = 0; i < nbucket; i++) 21899ee7876kaiw c[bl[i]]++; 21909ee7876kaiw PRT(" bucket symndx name\n"); 2191db27a04emaste for (i = 0; i < nbucket; i++) { 21929ee7876kaiw first = 1; 2193db27a04emaste for (j = bucket[i]; j > 0 && j < nchain; j = chain[j]) { 21949ee7876kaiw if (first) { 21959ee7876kaiw PRT("%10d ", i); 21969ee7876kaiw first = 0; 21979ee7876kaiw } else 21989ee7876kaiw PRT(" "); 21999ee7876kaiw snprintf(idx, sizeof(idx), "[%d]", j); 22009ee7876kaiw PRT("%-10s ", idx); 22019ee7876kaiw PRT("%s\n", get_symbol_name(ed, s->link, j)); 22029ee7876kaiw } 22039ee7876kaiw } 22049ee7876kaiw PRT("\n"); 22059ee7876kaiw total = 0; 2206db27a04emaste for (i = 0; i <= maxl; i++) { 22079ee7876kaiw total += c[i] * i; 22089ee7876kaiw PRT("%10u buckets contain %8d symbols\n", c[i], i); 22099ee7876kaiw } 22109ee7876kaiw PRT("%10u buckets %8u symbols (globals)\n", nbucket, 22119ee7876kaiw total); 22129ee7876kaiw } else { 22139ee7876kaiw PRT("\nnbucket: %u\n", nbucket); 22149ee7876kaiw PRT("nchain: %u\n\n", nchain); 2215db27a04emaste for (i = 0; i < nbucket; i++) 22169ee7876kaiw PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 2217db27a04emaste for (i = 0; i < nchain; i++) 22189ee7876kaiw PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 22199ee7876kaiw } 22209ee7876kaiw} 22219ee7876kaiw 22229ee7876kaiw/* 22239ee7876kaiw * Dump a 64bit hash table. 22249ee7876kaiw */ 22259ee7876kaiwstatic void 22269ee7876kaiwelf_print_svr4_hash64(struct elfdump *ed, struct section *s) 22279ee7876kaiw{ 22289ee7876kaiw Elf_Data *data, dst; 22299ee7876kaiw uint64_t *buf; 22309ee7876kaiw uint64_t *bucket, *chain; 22319ee7876kaiw uint64_t nbucket, nchain; 22323e5b0e3emaste uint64_t *bl, *c, j, maxl, total; 22333e5b0e3emaste size_t i; 2234db27a04emaste int elferr, first; 22359ee7876kaiw char idx[10]; 22369ee7876kaiw 22379ee7876kaiw if (ed->flags & SOLARIS_FMT) 22389ee7876kaiw PRT("\nHash Section: %s\n", s->name); 22399ee7876kaiw else 22409ee7876kaiw PRT("\nhash table (%s):\n", s->name); 22419ee7876kaiw 22429ee7876kaiw /* 22439ee7876kaiw * ALPHA uses 64-bit hash entries. Since libelf assumes that 22449ee7876kaiw * .hash section contains only 32-bit entry, an explicit 22459ee7876kaiw * gelf_xlatetom is needed here. 22469ee7876kaiw */ 22479ee7876kaiw (void) elf_errno(); 22489ee7876kaiw if ((data = elf_rawdata(s->scn, NULL)) == NULL) { 22499ee7876kaiw elferr = elf_errno(); 22509ee7876kaiw if (elferr != 0) 22519ee7876kaiw warnx("elf_rawdata failed: %s", 22529ee7876kaiw elf_errmsg(elferr)); 22539ee7876kaiw return; 22549ee7876kaiw } 22559ee7876kaiw data->d_type = ELF_T_XWORD; 22569ee7876kaiw memcpy(&dst, data, sizeof(Elf_Data)); 22579ee7876kaiw if (gelf_xlatetom(ed->elf, &dst, data, 22589ee7876kaiw ed->ehdr.e_ident[EI_DATA]) != &dst) { 22599ee7876kaiw warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 22609ee7876kaiw return; 22619ee7876kaiw } 22629ee7876kaiw if (dst.d_size < 2 * sizeof(uint64_t)) { 22639ee7876kaiw warnx(".hash section too small"); 22649ee7876kaiw return; 22659ee7876kaiw } 22669ee7876kaiw buf = dst.d_buf; 22679ee7876kaiw nbucket = buf[0]; 22689ee7876kaiw nchain = buf[1]; 22699ee7876kaiw if (nbucket <= 0 || nchain <= 0) { 22709ee7876kaiw warnx("Malformed .hash section"); 22719ee7876kaiw return; 22729ee7876kaiw } 22739ee7876kaiw if (dst.d_size != (nbucket + nchain + 2) * sizeof(uint64_t)) { 22749ee7876kaiw warnx("Malformed .hash section"); 22759ee7876kaiw return; 22769ee7876kaiw } 22779ee7876kaiw bucket = &buf[2]; 22789ee7876kaiw chain = &buf[2 + nbucket]; 22799ee7876kaiw 22809ee7876kaiw if (ed->flags & SOLARIS_FMT) { 22819ee7876kaiw maxl = 0; 22829ee7876kaiw if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 22839ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 2284db27a04emaste for (i = 0; i < nbucket; i++) 2285db27a04emaste for (j = bucket[i]; j > 0 && j < nchain; j = chain[j]) 22869ee7876kaiw if (++bl[i] > maxl) 22879ee7876kaiw maxl = bl[i]; 22889ee7876kaiw if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 22899ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 2290db27a04emaste for (i = 0; i < nbucket; i++) 22919ee7876kaiw c[bl[i]]++; 22929ee7876kaiw PRT(" bucket symndx name\n"); 2293db27a04emaste for (i = 0; i < nbucket; i++) { 22949ee7876kaiw first = 1; 2295db27a04emaste for (j = bucket[i]; j > 0 && j < nchain; j = chain[j]) { 22969ee7876kaiw if (first) { 2297db27a04emaste PRT("%10zu ", i); 22989ee7876kaiw first = 0; 22999ee7876kaiw } else 23009ee7876kaiw PRT(" "); 2301db27a04emaste snprintf(idx, sizeof(idx), "[%zu]", (size_t)j); 23029ee7876kaiw PRT("%-10s ", idx); 23039ee7876kaiw PRT("%s\n", get_symbol_name(ed, s->link, j)); 23049ee7876kaiw } 23059ee7876kaiw } 23069ee7876kaiw PRT("\n"); 23079ee7876kaiw total = 0; 2308db27a04emaste for (i = 0; i <= maxl; i++) { 23099ee7876kaiw total += c[i] * i; 2310db27a04emaste PRT("%10ju buckets contain %8zu symbols\n", 23119ee7876kaiw (uintmax_t)c[i], i); 23129ee7876kaiw } 23139ee7876kaiw PRT("%10ju buckets %8ju symbols (globals)\n", 23149ee7876kaiw (uintmax_t)nbucket, (uintmax_t)total); 23159ee7876kaiw } else { 23169ee7876kaiw PRT("\nnbucket: %ju\n", (uintmax_t)nbucket); 23179ee7876kaiw PRT("nchain: %ju\n\n", (uintmax_t)nchain); 2318db27a04emaste for (i = 0; i < nbucket; i++) 2319db27a04emaste PRT("bucket[%zu]:\n\t%ju\n\n", i, (uintmax_t)bucket[i]); 2320db27a04emaste for (i = 0; i < nchain; i++) 2321db27a04emaste PRT("chain[%zu]:\n\t%ju\n\n", i, (uintmax_t)chain[i]); 23229ee7876kaiw } 23239ee7876kaiw 23249ee7876kaiw} 23259ee7876kaiw 23269ee7876kaiw/* 23279ee7876kaiw * Dump a GNU hash table. 23289ee7876kaiw */ 23299ee7876kaiwstatic void 23309ee7876kaiwelf_print_gnu_hash(struct elfdump *ed, struct section *s) 23319ee7876kaiw{ 23329ee7876kaiw struct section *ds; 23339ee7876kaiw Elf_Data *data; 23349ee7876kaiw uint32_t *buf; 23359ee7876kaiw uint32_t *bucket, *chain; 23369ee7876kaiw uint32_t nbucket, nchain, symndx, maskwords, shift2; 23379ee7876kaiw uint32_t *bl, *c, maxl, total; 2338db27a04emaste uint32_t i, j; 2339db27a04emaste int first, elferr, dynsymcount; 23409ee7876kaiw char idx[10]; 23419ee7876kaiw 23429ee7876kaiw if (ed->flags & SOLARIS_FMT) 23439ee7876kaiw PRT("\nGNU Hash Section: %s\n", s->name); 23449ee7876kaiw else 23459ee7876kaiw PRT("\ngnu hash table (%s):\n", s->name); 23469ee7876kaiw (void) elf_errno(); 23479ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 23489ee7876kaiw elferr = elf_errno(); 23499ee7876kaiw if (elferr != 0) 23509ee7876kaiw warnx("elf_getdata failed: %s", 23519ee7876kaiw elf_errmsg(elferr)); 23529ee7876kaiw return; 23539ee7876kaiw } 23549ee7876kaiw if (data->d_size < 4 * sizeof(uint32_t)) { 23559ee7876kaiw warnx(".gnu.hash section too small"); 23569ee7876kaiw return; 23579ee7876kaiw } 23589ee7876kaiw buf = data->d_buf; 23599ee7876kaiw nbucket = buf[0]; 23609ee7876kaiw symndx = buf[1]; 23619ee7876kaiw maskwords = buf[2]; 23629ee7876kaiw shift2 = buf[3]; 23639ee7876kaiw buf += 4; 2364db27a04emaste if (s->link >= ed->shnum) { 2365db27a04emaste warnx("Malformed .gnu.hash section"); 2366db27a04emaste return; 2367db27a04emaste } 23689ee7876kaiw ds = &ed->sl[s->link]; 2369f776db0emaste if (!get_ent_count(ds, &dynsymcount)) 2370f776db0emaste return; 2371db27a04emaste if (symndx >= (uint32_t)dynsymcount) { 2372db27a04emaste warnx("Malformed .gnu.hash section"); 2373db27a04emaste return; 2374db27a04emaste } 23759ee7876kaiw nchain = dynsymcount - symndx; 23769ee7876kaiw if (data->d_size != 4 * sizeof(uint32_t) + maskwords * 23779ee7876kaiw (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + 2378db27a04emaste ((uint64_t)nbucket + (uint64_t)nchain) * sizeof(uint32_t)) { 23799ee7876kaiw warnx("Malformed .gnu.hash section"); 23809ee7876kaiw return; 23819ee7876kaiw } 23829ee7876kaiw bucket = buf + (ed->ec == ELFCLASS32 ? maskwords : maskwords * 2); 23839ee7876kaiw chain = bucket + nbucket; 23849ee7876kaiw 23859ee7876kaiw if (ed->flags & SOLARIS_FMT) { 23869ee7876kaiw maxl = 0; 23879ee7876kaiw if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 23889ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 2389db27a04emaste for (i = 0; i < nbucket; i++) 2390db27a04emaste for (j = bucket[i]; j > 0 && j - symndx < nchain; j++) { 23919ee7876kaiw if (++bl[i] > maxl) 23929ee7876kaiw maxl = bl[i]; 23939ee7876kaiw if (chain[j - symndx] & 1) 23949ee7876kaiw break; 23959ee7876kaiw } 23969ee7876kaiw if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 23979ee7876kaiw err(EXIT_FAILURE, "calloc failed"); 2398db27a04emaste for (i = 0; i < nbucket; i++) 23999ee7876kaiw c[bl[i]]++; 24009ee7876kaiw PRT(" bucket symndx name\n"); 2401db27a04emaste for (i = 0; i < nbucket; i++) { 24029ee7876kaiw first = 1; 2403db27a04emaste for (j = bucket[i]; j > 0 && j - symndx < nchain; j++) { 24049ee7876kaiw if (first) { 24059ee7876kaiw PRT("%10d ", i); 24069ee7876kaiw first = 0; 24079ee7876kaiw } else 24089ee7876kaiw PRT(" "); 24099ee7876kaiw snprintf(idx, sizeof(idx), "[%d]", j ); 24109ee7876kaiw PRT("%-10s ", idx); 24119ee7876kaiw PRT("%s\n", get_symbol_name(ed, s->link, j)); 24129ee7876kaiw if (chain[j - symndx] & 1) 24139ee7876kaiw break; 24149ee7876kaiw } 24159ee7876kaiw } 24169ee7876kaiw PRT("\n"); 24179ee7876kaiw total = 0; 2418db27a04emaste for (i = 0; i <= maxl; i++) { 24199ee7876kaiw total += c[i] * i; 24209ee7876kaiw PRT("%10u buckets contain %8d symbols\n", c[i], i); 24219ee7876kaiw } 24229ee7876kaiw PRT("%10u buckets %8u symbols (globals)\n", nbucket, 24239ee7876kaiw total); 24249ee7876kaiw } else { 24259ee7876kaiw PRT("\nnbucket: %u\n", nbucket); 24269ee7876kaiw PRT("symndx: %u\n", symndx); 24279ee7876kaiw PRT("maskwords: %u\n", maskwords); 24289ee7876kaiw PRT("shift2: %u\n", shift2); 24299ee7876kaiw PRT("nchain: %u\n\n", nchain); 2430db27a04emaste for (i = 0; i < nbucket; i++) 24319ee7876kaiw PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 2432db27a04emaste for (i = 0; i < nchain; i++) 24339ee7876kaiw PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 24349ee7876kaiw } 24359ee7876kaiw} 24369ee7876kaiw 24379ee7876kaiw/* 24389ee7876kaiw * Dump hash tables. 24399ee7876kaiw */ 24409ee7876kaiwstatic void 24419ee7876kaiwelf_print_hash(struct elfdump *ed) 24429ee7876kaiw{ 24439ee7876kaiw struct section *s; 2444db27a04emaste size_t i; 24459ee7876kaiw 2446db27a04emaste for (i = 0; i < ed->shnum; i++) { 24479ee7876kaiw s = &ed->sl[i]; 24489ee7876kaiw if ((s->type == SHT_HASH || s->type == SHT_GNU_HASH) && 24499ee7876kaiw (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 24509ee7876kaiw if (s->type == SHT_GNU_HASH) 24519ee7876kaiw elf_print_gnu_hash(ed, s); 24529ee7876kaiw else if (ed->ehdr.e_machine == EM_ALPHA && 24539ee7876kaiw s->entsize == 8) 24549ee7876kaiw elf_print_svr4_hash64(ed, s); 24559ee7876kaiw else 24569ee7876kaiw elf_print_svr4_hash(ed, s); 24579ee7876kaiw } 24589ee7876kaiw } 24599ee7876kaiw} 24609ee7876kaiw 24619ee7876kaiw/* 24629ee7876kaiw * Dump the content of a Version Definition(SHT_SUNW_Verdef) Section. 24639ee7876kaiw */ 24649ee7876kaiwstatic void 24659ee7876kaiwelf_print_verdef(struct elfdump *ed, struct section *s) 24669ee7876kaiw{ 24679ee7876kaiw Elf_Data *data; 24689ee7876kaiw Elf32_Verdef *vd; 24699ee7876kaiw Elf32_Verdaux *vda; 24709ee7876kaiw const char *str; 24719ee7876kaiw char idx[10]; 24729ee7876kaiw uint8_t *buf, *end, *buf2; 24739ee7876kaiw int i, j, elferr, count; 24749ee7876kaiw 24759ee7876kaiw if (ed->flags & SOLARIS_FMT) 24769ee7876kaiw PRT("Version Definition Section: %s\n", s->name); 24779ee7876kaiw else 24789ee7876kaiw PRT("\nversion definition section (%s):\n", s->name); 24799ee7876kaiw (void) elf_errno(); 24809ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 24819ee7876kaiw elferr = elf_errno(); 24829ee7876kaiw if (elferr != 0) 24839ee7876kaiw warnx("elf_getdata failed: %s", 24849ee7876kaiw elf_errmsg(elferr)); 24859ee7876kaiw return; 24869ee7876kaiw } 24879ee7876kaiw buf = data->d_buf; 24889ee7876kaiw end = buf + data->d_size; 24899ee7876kaiw i = 0; 24909ee7876kaiw if (ed->flags & SOLARIS_FMT) 24919ee7876kaiw PRT(" index version dependency\n"); 24929ee7876kaiw while (buf + sizeof(Elf32_Verdef) <= end) { 24939ee7876kaiw vd = (Elf32_Verdef *) (uintptr_t) buf; 24949ee7876kaiw if (ed->flags & SOLARIS_FMT) { 24959ee7876kaiw snprintf(idx, sizeof(idx), "[%d]", vd->vd_ndx); 24969ee7876kaiw PRT("%10s ", idx); 24979ee7876kaiw } else { 24989ee7876kaiw PRT("\nentry: %d\n", i++); 24999ee7876kaiw PRT("\tvd_version: %u\n", vd->vd_version); 25009ee7876kaiw PRT("\tvd_flags: %u\n", vd->vd_flags); 25019ee7876kaiw PRT("\tvd_ndx: %u\n", vd->vd_ndx); 25029ee7876kaiw PRT("\tvd_cnt: %u\n", vd->vd_cnt); 25039ee7876kaiw PRT("\tvd_hash: %u\n", vd->vd_hash); 25049ee7876kaiw PRT("\tvd_aux: %u\n", vd->vd_aux); 25059ee7876kaiw PRT("\tvd_next: %u\n\n", vd->vd_next); 25069ee7876kaiw } 25079ee7876kaiw buf2 = buf + vd->vd_aux; 25089ee7876kaiw j = 0; 25099ee7876kaiw count = 0; 25109ee7876kaiw while (buf2 + sizeof(Elf32_Verdaux) <= end && j < vd->vd_cnt) { 25119ee7876kaiw vda = (Elf32_Verdaux *) (uintptr_t) buf2; 25129ee7876kaiw str = get_string(ed, s->link, vda->vda_name); 25139ee7876kaiw if (ed->flags & SOLARIS_FMT) { 25149ee7876kaiw if (count == 0) 25159ee7876kaiw PRT("%-26.26s", str); 25169ee7876kaiw else if (count == 1) 25179ee7876kaiw PRT(" %-20.20s", str); 25189ee7876kaiw else { 25199ee7876kaiw PRT("\n%40.40s", ""); 25209ee7876kaiw PRT("%s", str); 25219ee7876kaiw } 25229ee7876kaiw } else { 25239ee7876kaiw PRT("\t\tvda: %d\n", j++); 25249ee7876kaiw PRT("\t\t\tvda_name: %s\n", str); 25259ee7876kaiw PRT("\t\t\tvda_next: %u\n", vda->vda_next); 25269ee7876kaiw } 25279ee7876kaiw if (vda->vda_next == 0) { 25289ee7876kaiw if (ed->flags & SOLARIS_FMT) { 25299ee7876kaiw if (vd->vd_flags & VER_FLG_BASE) { 25309ee7876kaiw if (count == 0) 25319ee7876kaiw PRT("%-20.20s", ""); 25329ee7876kaiw PRT("%s", "[ BASE ]"); 25339ee7876kaiw } 25349ee7876kaiw PRT("\n"); 25359ee7876kaiw } 25369ee7876kaiw break; 25379ee7876kaiw } 25389ee7876kaiw if (ed->flags & SOLARIS_FMT) 25399ee7876kaiw count++; 25409ee7876kaiw buf2 += vda->vda_next; 25419ee7876kaiw } 25429ee7876kaiw if (vd->vd_next == 0) 25439ee7876kaiw break; 25449ee7876kaiw buf += vd->vd_next; 25459ee7876kaiw } 25469ee7876kaiw} 25479ee7876kaiw 25489ee7876kaiw/* 25499ee7876kaiw * Dump the content of a Version Needed(SHT_SUNW_Verneed) Section. 25509ee7876kaiw */ 25519ee7876kaiwstatic void 25529ee7876kaiwelf_print_verneed(struct elfdump *ed, struct section *s) 25539ee7876kaiw{ 25549ee7876kaiw Elf_Data *data; 25559ee7876kaiw Elf32_Verneed *vn; 25569ee7876kaiw Elf32_Vernaux *vna; 25579ee7876kaiw uint8_t *buf, *end, *buf2; 25589ee7876kaiw int i, j, elferr, first; 25599ee7876kaiw 25609ee7876kaiw if (ed->flags & SOLARIS_FMT) 25619ee7876kaiw PRT("\nVersion Needed Section: %s\n", s->name); 25629ee7876kaiw else 25639ee7876kaiw PRT("\nversion need section (%s):\n", s->name); 25649ee7876kaiw (void) elf_errno(); 25659ee7876kaiw if ((data = elf_getdata(s->scn, NULL)) == NULL) { 25669ee7876kaiw elferr = elf_errno(); 25679ee7876kaiw if (elferr != 0) 25689ee7876kaiw warnx("elf_getdata failed: %s", 25699ee7876kaiw elf_errmsg(elferr)); 25709ee7876kaiw return; 25719ee7876kaiw } 25729ee7876kaiw buf = data->d_buf; 25739ee7876kaiw end = buf + data->d_size; 25749ee7876kaiw if (ed->flags & SOLARIS_FMT) 25759ee7876kaiw PRT(" file version\n"); 25769ee7876kaiw i = 0; 25779ee7876kaiw while (buf + sizeof(Elf32_Verneed) <= end) { 25789ee7876kaiw vn = (Elf32_Verneed *) (uintptr_t) buf; 25799ee7876kaiw if (ed->flags & SOLARIS_FMT) 25809ee7876kaiw PRT(" %-26.26s ", 25819ee7876kaiw get_string(ed, s->link, vn->vn_file)); 25829ee7876kaiw else { 25839ee7876kaiw PRT("\nentry: %d\n", i++); 25849ee7876kaiw PRT("\tvn_version: %u\n", vn->vn_version); 25859ee7876kaiw PRT("\tvn_cnt: %u\n", vn->vn_cnt); 25869ee7876kaiw PRT("\tvn_file: %s\n", 25879ee7876kaiw get_string(ed, s->link, vn->vn_file)); 25889ee7876kaiw PRT("\tvn_aux: %u\n", vn->vn_aux); 25899ee7876kaiw PRT("\tvn_next: %u\n\n", vn->vn_next); 25909ee7876kaiw } 25919ee7876kaiw buf2 = buf + vn->vn_aux; 25929ee7876kaiw j = 0; 25939ee7876kaiw first = 1; 25949ee7876kaiw while (buf2 + sizeof(Elf32_Vernaux) <= end && j < vn->vn_cnt) { 25959ee7876kaiw vna = (Elf32_Vernaux *) (uintptr_t) buf2; 25969ee7876kaiw if (ed->flags & SOLARIS_FMT) { 25979ee7876kaiw if (!first) 25989ee7876kaiw PRT("%40.40s", ""); 25999ee7876kaiw else 26009ee7876kaiw first = 0; 26019ee7876kaiw PRT("%s\n", get_string(ed, s->link, 26029ee7876kaiw vna->vna_name)); 26039ee7876kaiw } else { 26049ee7876kaiw PRT("\t\tvna: %d\n", j++); 26059ee7876kaiw PRT("\t\t\tvna_hash: %u\n", vna->vna_hash); 26069ee7876kaiw PRT("\t\t\tvna_flags: %u\n", vna->vna_flags); 26079ee7876kaiw PRT("\t\t\tvna_other: %u\n", vna->vna_other); 26089ee7876kaiw PRT("\t\t\tvna_name: %s\n", 26099ee7876kaiw get_string(ed, s->link, vna->vna_name)); 26109ee7876kaiw PRT("\t\t\tvna_next: %u\n", vna->vna_next); 26119ee7876kaiw } 26129ee7876kaiw if (vna->vna_next == 0) 26139ee7876kaiw break; 26149ee7876kaiw buf2 += vna->vna_next; 26159ee7876kaiw } 26169ee7876kaiw if (vn->vn_next == 0) 26179ee7876kaiw break; 26189ee7876kaiw buf += vn->vn_next; 26199ee7876kaiw } 26209ee7876kaiw} 26219ee7876kaiw 26229ee7876kaiw/* 26239ee7876kaiw * Dump the symbol-versioning sections. 26249ee7876kaiw */ 26259ee7876kaiwstatic void 26269ee7876kaiwelf_print_symver(struct elfdump *ed) 26279ee7876kaiw{ 26289ee7876kaiw struct section *s; 2629db27a04emaste size_t i; 26309ee7876kaiw 2631db27a04emaste for (i = 0; i < ed->shnum; i++) { 26329ee7876kaiw s = &ed->sl[i]; 26339ee7876kaiw if (!STAILQ_EMPTY(&ed->snl) && !find_name(ed, s->name)) 26349ee7876kaiw continue; 26359ee7876kaiw if (s->type == SHT_SUNW_verdef) 26369ee7876kaiw elf_print_verdef(ed, s); 26379ee7876kaiw if (s->type == SHT_SUNW_verneed) 26389ee7876kaiw elf_print_verneed(ed, s); 26399ee7876kaiw } 26409ee7876kaiw} 26419ee7876kaiw 26429ee7876kaiw/* 26439ee7876kaiw * Dump the ELF checksum. See gelf_checksum(3) for details. 26449ee7876kaiw */ 26459ee7876kaiwstatic void 26469ee7876kaiwelf_print_checksum(struct elfdump *ed) 26479ee7876kaiw{ 26489ee7876kaiw 26499ee7876kaiw if (!STAILQ_EMPTY(&ed->snl)) 26509ee7876kaiw return; 26519ee7876kaiw 26529ee7876kaiw PRT("\nelf checksum: %#lx\n", gelf_checksum(ed->elf)); 26539ee7876kaiw} 26549ee7876kaiw 26559ee7876kaiw#define USAGE_MESSAGE "\ 26569ee7876kaiwUsage: %s [options] file...\n\ 26579ee7876kaiw Display information about ELF objects and ar(1) archives.\n\n\ 26589ee7876kaiw Options:\n\ 26599ee7876kaiw -a Show all information.\n\ 26609ee7876kaiw -c Show shared headers.\n\ 26619ee7876kaiw -d Show dynamic symbols.\n\ 26629ee7876kaiw -e Show the ELF header.\n\ 26639ee7876kaiw -G Show the GOT.\n\ 26649ee7876kaiw -H | --help Show a usage message and exit.\n\ 26659ee7876kaiw -h Show hash values.\n\ 26669ee7876kaiw -i Show the dynamic interpreter.\n\ 26679ee7876kaiw -k Show the ELF checksum.\n\ 26689ee7876kaiw -n Show the contents of note sections.\n\ 26699ee7876kaiw -N NAME Show the section named \"NAME\".\n\ 26709ee7876kaiw -p Show the program header.\n\ 26719ee7876kaiw -r Show relocations.\n\ 26729ee7876kaiw -s Show the symbol table.\n\ 26739ee7876kaiw -S Use the Solaris elfdump format.\n\ 26749ee7876kaiw -v Show symbol-versioning information.\n\ 26759ee7876kaiw -V | --version Print a version identifier and exit.\n\ 26769ee7876kaiw -w FILE Write output to \"FILE\".\n" 26779ee7876kaiw 26789ee7876kaiwstatic void 26799ee7876kaiwusage(void) 26809ee7876kaiw{ 26819ee7876kaiw fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 26829ee7876kaiw exit(EXIT_FAILURE); 26839ee7876kaiw} 2684