11556Srgrimes/*- 21556Srgrimes * Copyright (c) 2003 David O'Brien. All rights reserved. 31556Srgrimes * Copyright (c) 2001 Jake Burkholder 41556Srgrimes * All rights reserved. 51556Srgrimes * 61556Srgrimes * Redistribution and use in source and binary forms, with or without 71556Srgrimes * modification, are permitted provided that the following conditions 81556Srgrimes * are met: 91556Srgrimes * 1. Redistributions of source code must retain the above copyright 101556Srgrimes * notice, this list of conditions and the following disclaimer. 111556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer in the 131556Srgrimes * documentation and/or other materials provided with the distribution. 141556Srgrimes * 151556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 161556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 171556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 191556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 201556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 211556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 221556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 231556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 251556Srgrimes * SUCH DAMAGE. 261556Srgrimes */ 271556Srgrimes 281556Srgrimes#include <sys/cdefs.h> 291556Srgrimes__FBSDID("$FreeBSD$"); 301556Srgrimes 311556Srgrimes#include <sys/types.h> 321556Srgrimes#include <sys/elf32.h> 331556Srgrimes#include <sys/elf64.h> 341556Srgrimes#include <sys/endian.h> 351556Srgrimes#include <sys/mman.h> 361556Srgrimes#include <sys/stat.h> 371556Srgrimes#include <err.h> 3836150Scharnier#include <fcntl.h> 3936150Scharnier#include <inttypes.h> 4036150Scharnier#include <stddef.h> 4136150Scharnier#include <stdio.h> 4250471Speter#include <stdlib.h> 431556Srgrimes#include <string.h> 441556Srgrimes#include <unistd.h> 4517987Speter 4617987Speter#define ED_DYN (1<<0) 471556Srgrimes#define ED_EHDR (1<<1) 481556Srgrimes#define ED_GOT (1<<2) 491556Srgrimes#define ED_HASH (1<<3) 501556Srgrimes#define ED_INTERP (1<<4) 511556Srgrimes#define ED_NOTE (1<<5) 521556Srgrimes#define ED_PHDR (1<<6) 531556Srgrimes#define ED_REL (1<<7) 541556Srgrimes#define ED_SHDR (1<<8) 551556Srgrimes#define ED_SYMTAB (1<<9) 561556Srgrimes#define ED_ALL ((1<<10)-1) 571556Srgrimes 581556Srgrimes#define elf_get_addr elf_get_quad 591556Srgrimes#define elf_get_off elf_get_quad 601556Srgrimes#define elf_get_size elf_get_quad 6117987Speter 6259436Scracauerenum elf_member { 6317987Speter D_TAG = 1, D_PTR, D_VAL, 641556Srgrimes 6517987Speter E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY, 661556Srgrimes E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE, 671556Srgrimes E_SHNUM, E_SHSTRNDX, 681556Srgrimes 691556Srgrimes N_NAMESZ, N_DESCSZ, N_TYPE, 701556Srgrimes 711556Srgrimes P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS, 721556Srgrimes P_ALIGN, 731556Srgrimes 7417987Speter SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK, 751556Srgrimes SH_INFO, SH_ADDRALIGN, SH_ENTSIZE, 761556Srgrimes 771556Srgrimes ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX, 781556Srgrimes 791556Srgrimes R_OFFSET, R_INFO, 801556Srgrimes 811556Srgrimes RA_OFFSET, RA_INFO, RA_ADDEND 821556Srgrimes}; 831556Srgrimes 841556Srgrimestypedef enum elf_member elf_member_t; 851556Srgrimes 861556Srgrimesstatic int elf32_offsets[] = { 871556Srgrimes 0, 881556Srgrimes 891556Srgrimes offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr), 901556Srgrimes offsetof(Elf32_Dyn, d_un.d_val), 911556Srgrimes 921556Srgrimes offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 931556Srgrimes offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 941556Srgrimes offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 951556Srgrimes offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine), 961556Srgrimes offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry), 971556Srgrimes offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff), 981556Srgrimes offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize), 991556Srgrimes offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum), 1001556Srgrimes offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum), 10118018Speter offsetof(Elf32_Ehdr, e_shstrndx), 10218018Speter 1031556Srgrimes offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 1041556Srgrimes offsetof(Elf_Note, n_type), 1051556Srgrimes 1061556Srgrimes offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset), 1071556Srgrimes offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr), 1081556Srgrimes offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz), 1091556Srgrimes offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align), 1101556Srgrimes 11190111Simp offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type), 11290111Simp offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr), 11390111Simp offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size), 11490111Simp offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info), 11590111Simp offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize), 11690111Simp 11790111Simp offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value), 11890111Simp offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info), 11990111Simp offsetof(Elf32_Sym, st_shndx), 12090111Simp 12190111Simp offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info), 12290111Simp 12390111Simp offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info), 12490111Simp offsetof(Elf32_Rela, r_addend) 12590111Simp}; 12690111Simp 1271556Srgrimesstatic int elf64_offsets[] = { 12817987Speter 0, 1291556Srgrimes 1301556Srgrimes offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr), 1311556Srgrimes offsetof(Elf64_Dyn, d_un.d_val), 1321556Srgrimes 1331556Srgrimes offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 1341556Srgrimes offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 13590111Simp offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 13617987Speter offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine), 1371556Srgrimes offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry), 1381556Srgrimes offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff), 13960593Scracauer offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize), 1401556Srgrimes offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum), 1411556Srgrimes offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum), 1421556Srgrimes offsetof(Elf64_Ehdr, e_shstrndx), 1431556Srgrimes 1441556Srgrimes offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 1451556Srgrimes offsetof(Elf_Note, n_type), 1461556Srgrimes 1471556Srgrimes offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset), 1481556Srgrimes offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr), 1491556Srgrimes offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz), 1501556Srgrimes offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align), 1511556Srgrimes 1521556Srgrimes offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type), 1531556Srgrimes offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr), 1541556Srgrimes offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size), 1551556Srgrimes offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info), 1561556Srgrimes offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize), 15790111Simp 15817987Speter offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value), 1591556Srgrimes offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info), 16017987Speter offsetof(Elf64_Sym, st_shndx), 1611556Srgrimes 1621556Srgrimes offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info), 1631556Srgrimes 1641556Srgrimes offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info), 16517987Speter offsetof(Elf64_Rela, r_addend) 1661556Srgrimes}; 16717987Speter 16817987Speter/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 16917987Speterstatic const char * 17017987Speterd_tags(u_int64_t tag) { 17117987Speter switch (tag) { 17217987Speter case 0: return "DT_NULL"; 17317987Speter case 1: return "DT_NEEDED"; 17417987Speter case 2: return "DT_PLTRELSZ"; 17517987Speter case 3: return "DT_PLTGOT"; 17617987Speter case 4: return "DT_HASH"; 17717987Speter case 5: return "DT_STRTAB"; 17817987Speter case 6: return "DT_SYMTAB"; 17917987Speter case 7: return "DT_RELA"; 18017987Speter case 8: return "DT_RELASZ"; 18117987Speter case 9: return "DT_RELAENT"; 18217987Speter case 10: return "DT_STRSZ"; 18317987Speter case 11: return "DT_SYMENT"; 18417987Speter case 12: return "DT_INIT"; 18517987Speter case 13: return "DT_FINI"; 18617987Speter case 14: return "DT_SONAME"; 18717987Speter case 15: return "DT_RPATH"; 18817987Speter case 16: return "DT_SYMBOLIC"; 18917987Speter case 17: return "DT_REL"; 19017987Speter case 18: return "DT_RELSZ"; 19117987Speter case 19: return "DT_RELENT"; 19217987Speter case 20: return "DT_PLTREL"; 19313882Sjoerg case 21: return "DT_DEBUG"; 19417987Speter case 22: return "DT_TEXTREL"; 19517987Speter case 23: return "DT_JMPREL"; 19617987Speter case 24: return "DT_BIND_NOW"; 1971556Srgrimes case 25: return "DT_INIT_ARRAY"; 19817987Speter case 26: return "DT_FINI_ARRAY"; 19917987Speter case 27: return "DT_INIT_ARRAYSZ"; 20017987Speter case 28: return "DT_FINI_ARRAYSZ"; 20117987Speter case 29: return "DT_RUNPATH"; 20217987Speter case 30: return "DT_FLAGS"; 20317987Speter case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ 20417987Speter case 33: return "DT_PREINIT_ARRAYSZ"; 2051556Srgrimes /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 2061556Srgrimes case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 2071556Srgrimes case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 2081556Srgrimes case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 2091556Srgrimes case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 2101556Srgrimes case 0x6ffffdf9: return "DT_PLTPADSZ"; 2111556Srgrimes case 0x6ffffdfa: return "DT_MOVEENT"; 2121556Srgrimes case 0x6ffffdfb: return "DT_MOVESZ"; 2131556Srgrimes case 0x6ffffdfc: return "DT_FEATURE"; 2141556Srgrimes case 0x6ffffdfd: return "DT_POSFLAG_1"; 2151556Srgrimes case 0x6ffffdfe: return "DT_SYMINSZ"; 2161556Srgrimes case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; 2171556Srgrimes case 0x6ffffe00: return "DT_ADDRRNGLO"; 2181556Srgrimes case 0x6ffffef8: return "DT_GNU_CONFLICT"; 2191556Srgrimes case 0x6ffffef9: return "DT_GNU_LIBLIST"; 2201556Srgrimes case 0x6ffffefa: return "DT_SUNW_CONFIG"; 2211556Srgrimes case 0x6ffffefb: return "DT_SUNW_DEPAUDIT"; 2221556Srgrimes case 0x6ffffefc: return "DT_SUNW_AUDIT"; 2231556Srgrimes case 0x6ffffefd: return "DT_SUNW_PLTPAD"; 2241556Srgrimes case 0x6ffffefe: return "DT_SUNW_MOVETAB"; 2251556Srgrimes case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; 2261556Srgrimes case 0x6ffffff9: return "DT_RELACOUNT"; 22790111Simp case 0x6ffffffa: return "DT_RELCOUNT"; 22890111Simp case 0x6ffffffb: return "DT_FLAGS_1"; 2291556Srgrimes case 0x6ffffffc: return "DT_VERDEF"; 2301556Srgrimes case 0x6ffffffd: return "DT_VERDEFNUM"; 2311556Srgrimes case 0x6ffffffe: return "DT_VERNEED"; 2321556Srgrimes case 0x6fffffff: return "DT_VERNEEDNUM"; 2331556Srgrimes case 0x6ffffff0: return "DT_GNU_VERSYM"; 2341556Srgrimes /* 0x70000000 - 0x7fffffff processor-specific semantics */ 2351556Srgrimes case 0x70000000: return "DT_IA_64_PLT_RESERVE"; 2361556Srgrimes case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; 2371556Srgrimes case 0x7ffffffe: return "DT_SUNW_USED"; 2381556Srgrimes case 0x7fffffff: return "DT_SUNW_FILTER"; 2391556Srgrimes default: return "ERROR: TAG NOT DEFINED"; 2401556Srgrimes } 2411556Srgrimes} 2421556Srgrimes 2431556Srgrimesstatic const char * 2441556Srgrimese_machines(u_int mach) 2451556Srgrimes{ 2461556Srgrimes static char machdesc[64]; 2471556Srgrimes 2481556Srgrimes switch (mach) { 2491556Srgrimes case EM_NONE: return "EM_NONE"; 2501556Srgrimes case EM_M32: return "EM_M32"; 2511556Srgrimes case EM_SPARC: return "EM_SPARC"; 2521556Srgrimes case EM_386: return "EM_386"; 2531556Srgrimes case EM_68K: return "EM_68K"; 25490111Simp case EM_88K: return "EM_88K"; 25590111Simp case EM_860: return "EM_860"; 25675336Sbrian case EM_MIPS: return "EM_MIPS"; 2571556Srgrimes case EM_PPC: return "EM_PPC"; 25875336Sbrian case EM_ARM: return "EM_ARM"; 2591556Srgrimes case EM_ALPHA: return "EM_ALPHA (legacy)"; 26075336Sbrian case EM_SPARCV9:return "EM_SPARCV9"; 2611556Srgrimes case EM_IA_64: return "EM_IA_64"; 26275336Sbrian case EM_X86_64: return "EM_X86_64"; 26375336Sbrian } 26475336Sbrian snprintf(machdesc, sizeof(machdesc), 2651556Srgrimes "(unknown machine) -- type 0x%x", mach); 2661556Srgrimes return (machdesc); 2671556Srgrimes} 2681556Srgrimes 2691556Srgrimesstatic const char *e_types[] = { 2701556Srgrimes "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 2711556Srgrimes}; 2721556Srgrimes 2731556Srgrimesstatic const char *ei_versions[] = { 2741556Srgrimes "EV_NONE", "EV_CURRENT" 2751556Srgrimes}; 2761556Srgrimes 2771556Srgrimesstatic const char *ei_classes[] = { 2781556Srgrimes "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 2791556Srgrimes}; 2801556Srgrimes 2811556Srgrimesstatic const char *ei_data[] = { 2821556Srgrimes "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 28375336Sbrian}; 28475336Sbrian 28575336Sbrianstatic const char *ei_abis[256] = { 28675336Sbrian "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 28775336Sbrian "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX", 28875336Sbrian "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64", 28975336Sbrian "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD", 2901556Srgrimes [255] = "ELFOSABI_STANDALONE" 2911556Srgrimes}; 2921556Srgrimes 2931556Srgrimesstatic const char *p_types[] = { 2941556Srgrimes "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 29590111Simp "PT_SHLIB", "PT_PHDR", "PT_TLS" 29690111Simp}; 2971556Srgrimes 2981556Srgrimesstatic const char *p_flags[] = { 2991556Srgrimes "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 3001556Srgrimes "PF_X|PF_W|PF_R" 30175160Sbrian}; 3021556Srgrimes 3031556Srgrimes/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 30417987Speterstatic const char * 30517987Spetersh_types(u_int64_t sht) { 3061556Srgrimes switch (sht) { 30720425Ssteve case 0: return "SHT_NULL"; 3081556Srgrimes case 1: return "SHT_PROGBITS"; 3091556Srgrimes case 2: return "SHT_SYMTAB"; 3101556Srgrimes case 3: return "SHT_STRTAB"; 3111556Srgrimes case 4: return "SHT_RELA"; 3121556Srgrimes case 5: return "SHT_HASH"; 3131556Srgrimes case 6: return "SHT_DYNAMIC"; 3141556Srgrimes case 7: return "SHT_NOTE"; 3151556Srgrimes case 8: return "SHT_NOBITS"; 31675160Sbrian case 9: return "SHT_REL"; 31775160Sbrian case 10: return "SHT_SHLIB"; 31875160Sbrian case 11: return "SHT_DYNSYM"; 31975160Sbrian case 14: return "SHT_INIT_ARRAY"; 32075160Sbrian case 15: return "SHT_FINI_ARRAY"; 32175160Sbrian case 16: return "SHT_PREINIT_ARRAY"; 3221556Srgrimes case 17: return "SHT_GROUP"; 3231556Srgrimes case 18: return "SHT_SYMTAB_SHNDX"; 3241556Srgrimes /* 0x60000000 - 0x6fffffff operating system-specific semantics */ 3251556Srgrimes case 0x6ffffff0: return "XXX:VERSYM"; 3261556Srgrimes case 0x6ffffff4: return "SHT_SUNW_dof"; 3271556Srgrimes case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 3281556Srgrimes case 0x6ffffffc: return "XXX:VERDEF"; 3291556Srgrimes case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; 3301556Srgrimes case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; 3311556Srgrimes case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; 3321556Srgrimes /* 0x70000000 - 0x7fffffff processor-specific semantics */ 3331556Srgrimes case 0x70000000: return "SHT_IA_64_EXT"; 3341556Srgrimes case 0x70000001: return "SHT_IA_64_UNWIND"; 3351556Srgrimes case 0x7ffffffd: return "XXX:AUXILIARY"; 3361556Srgrimes case 0x7fffffff: return "XXX:FILTER"; 3371556Srgrimes /* 0x80000000 - 0xffffffff application programs */ 3381556Srgrimes default: return "ERROR: SHT NOT DEFINED"; 3391556Srgrimes } 3401556Srgrimes} 3411556Srgrimes 3421556Srgrimesstatic const char *sh_flags[] = { 3431556Srgrimes "", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR", 3441556Srgrimes "SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR", 3451556Srgrimes "SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR" 3461556Srgrimes}; 3471556Srgrimes 3481556Srgrimesstatic const char *st_types[] = { 3491556Srgrimes "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE" 3501556Srgrimes}; 3511556Srgrimes 3521556Srgrimesstatic const char *st_bindings[] = { 3531556Srgrimes "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 3541556Srgrimes}; 3551556Srgrimes 3561556Srgrimesstatic char *dynstr; 3571556Srgrimesstatic char *shstrtab; 3581556Srgrimesstatic char *strtab; 3591556Srgrimesstatic FILE *out; 3601556Srgrimes 3611556Srgrimesstatic u_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member); 3621556Srgrimesstatic u_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, 3631556Srgrimes elf_member_t member); 3641556Srgrimes#if 0 3651556Srgrimesstatic u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member); 3661556Srgrimes#endif 3671556Srgrimesstatic u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member); 3681556Srgrimesstatic u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member); 3691556Srgrimes 3701556Srgrimesstatic void elf_print_ehdr(Elf32_Ehdr *e); 3711556Srgrimesstatic void elf_print_phdr(Elf32_Ehdr *e, void *p); 3721556Srgrimesstatic void elf_print_shdr(Elf32_Ehdr *e, void *sh); 3731556Srgrimesstatic void elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str); 3741556Srgrimesstatic void elf_print_dynamic(Elf32_Ehdr *e, void *sh); 3751556Srgrimesstatic void elf_print_rel(Elf32_Ehdr *e, void *r); 3761556Srgrimesstatic void elf_print_rela(Elf32_Ehdr *e, void *ra); 3771556Srgrimesstatic void elf_print_interp(Elf32_Ehdr *e, void *p); 3781556Srgrimesstatic void elf_print_got(Elf32_Ehdr *e, void *sh); 3791556Srgrimesstatic void elf_print_hash(Elf32_Ehdr *e, void *sh); 3801556Srgrimesstatic void elf_print_note(Elf32_Ehdr *e, void *sh); 3811556Srgrimes 3821556Srgrimesstatic void usage(void); 3831556Srgrimes 3841556Srgrimesint 3851556Srgrimesmain(int ac, char **av) 3861556Srgrimes{ 3871556Srgrimes u_int64_t phoff; 3881556Srgrimes u_int64_t shoff; 3891556Srgrimes u_int64_t phentsize; 3901556Srgrimes u_int64_t phnum; 3911556Srgrimes u_int64_t shentsize; 3921556Srgrimes u_int64_t shnum; 3931556Srgrimes u_int64_t shstrndx; 3941556Srgrimes u_int64_t offset; 3951556Srgrimes u_int64_t name; 3961556Srgrimes u_int64_t type; 3971556Srgrimes struct stat sb; 3981556Srgrimes u_int flags; 3991556Srgrimes Elf32_Ehdr *e; 4001556Srgrimes void *p; 4011556Srgrimes void *sh; 4021556Srgrimes void *v; 4031556Srgrimes int fd; 4041556Srgrimes int ch; 4051556Srgrimes int i; 4061556Srgrimes 4071556Srgrimes out = stdout; 4081556Srgrimes flags = 0; 4091556Srgrimes while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1) 4101556Srgrimes switch (ch) { 4111556Srgrimes case 'a': 4121556Srgrimes flags = ED_ALL; 4131556Srgrimes break; 4141556Srgrimes case 'c': 4151556Srgrimes flags |= ED_SHDR; 4161556Srgrimes break; 4171556Srgrimes case 'd': 4181556Srgrimes flags |= ED_DYN; 4191556Srgrimes break; 4201556Srgrimes case 'e': 4211556Srgrimes flags |= ED_EHDR; 4221556Srgrimes break; 4231556Srgrimes case 'i': 4241556Srgrimes flags |= ED_INTERP; 4251556Srgrimes break; 4261556Srgrimes case 'G': 4271556Srgrimes flags |= ED_GOT; 4281556Srgrimes break; 4291556Srgrimes case 'h': 43018018Speter flags |= ED_HASH; 4312760Ssef break; 4322760Ssef case 'n': 4331556Srgrimes flags |= ED_NOTE; 4341556Srgrimes break; 4351556Srgrimes case 'p': 4361556Srgrimes flags |= ED_PHDR; 4371556Srgrimes break; 4381556Srgrimes case 'r': 4391556Srgrimes flags |= ED_REL; 4401556Srgrimes break; 4412760Ssef case 's': 4421556Srgrimes flags |= ED_SYMTAB; 4431556Srgrimes break; 4442760Ssef case 'w': 4451556Srgrimes if ((out = fopen(optarg, "w")) == NULL) 4461556Srgrimes err(1, "%s", optarg); 4471556Srgrimes break; 44818018Speter case '?': 4491556Srgrimes default: 4502760Ssef usage(); 4512760Ssef } 4522760Ssef ac -= optind; 4532760Ssef av += optind; 45418018Speter if (ac == 0 || flags == 0) 4552760Ssef usage(); 4562760Ssef if ((fd = open(*av, O_RDONLY)) < 0 || 4572760Ssef fstat(fd, &sb) < 0) 4581556Srgrimes err(1, "%s", *av); 4592760Ssef e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 46018018Speter if (e == MAP_FAILED) 4611556Srgrimes err(1, NULL); 4621556Srgrimes if (!IS_ELF(*(Elf32_Ehdr *)e)) 4631556Srgrimes errx(1, "not an elf file"); 4641556Srgrimes phoff = elf_get_off(e, e, E_PHOFF); 4651556Srgrimes shoff = elf_get_off(e, e, E_SHOFF); 4661556Srgrimes phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 4671556Srgrimes phnum = elf_get_quarter(e, e, E_PHNUM); 4681556Srgrimes shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 4691556Srgrimes shnum = elf_get_quarter(e, e, E_SHNUM); 4701556Srgrimes shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 4711556Srgrimes p = (char *)e + phoff; 4721556Srgrimes sh = (char *)e + shoff; 4731556Srgrimes offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, SH_OFFSET); 4741556Srgrimes shstrtab = (char *)e + offset; 4751556Srgrimes for (i = 0; (u_int64_t)i < shnum; i++) { 4761556Srgrimes name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME); 4771556Srgrimes offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET); 4781556Srgrimes if (strcmp(shstrtab + name, ".strtab") == 0) 4791556Srgrimes strtab = (char *)e + offset; 48017987Speter if (strcmp(shstrtab + name, ".dynstr") == 0) 48117987Speter dynstr = (char *)e + offset; 48217987Speter } 48317987Speter if (flags & ED_EHDR) 48417987Speter elf_print_ehdr(e); 48517987Speter if (flags & ED_PHDR) 48617987Speter elf_print_phdr(e, p); 48720425Ssteve if (flags & ED_SHDR) 48820425Ssteve elf_print_shdr(e, sh); 4891556Srgrimes for (i = 0; (u_int64_t)i < phnum; i++) { 49010399Sjoerg v = (char *)p + i * phentsize; 4911556Srgrimes type = elf_get_word(e, v, P_TYPE); 49217987Speter switch (type) { 4931556Srgrimes case PT_INTERP: 49475160Sbrian if (flags & ED_INTERP) 49575160Sbrian elf_print_interp(e, v); 4961556Srgrimes break; 4971556Srgrimes case PT_NULL: 4981556Srgrimes case PT_LOAD: 4991556Srgrimes case PT_DYNAMIC: 5001556Srgrimes case PT_NOTE: 5011556Srgrimes case PT_SHLIB: 5021556Srgrimes case PT_PHDR: 5031556Srgrimes break; 5041556Srgrimes } 5051556Srgrimes } 5061556Srgrimes for (i = 0; (u_int64_t)i < shnum; i++) { 5071556Srgrimes v = (char *)sh + i * shentsize; 5081556Srgrimes type = elf_get_word(e, v, SH_TYPE); 5091556Srgrimes switch (type) { 5101556Srgrimes case SHT_SYMTAB: 5111556Srgrimes if (flags & ED_SYMTAB) 5121556Srgrimes elf_print_symtab(e, v, strtab); 5131556Srgrimes break; 5141556Srgrimes case SHT_DYNAMIC: 5151556Srgrimes if (flags & ED_DYN) 5161556Srgrimes elf_print_dynamic(e, v); 51775160Sbrian break; 51875160Sbrian case SHT_RELA: 51975160Sbrian if (flags & ED_REL) 52075160Sbrian elf_print_rela(e, v); 52175160Sbrian break; 52275160Sbrian case SHT_REL: 52375160Sbrian if (flags & ED_REL) 52475160Sbrian elf_print_rel(e, v); 52575160Sbrian break; 52675160Sbrian case SHT_NOTE: 5271556Srgrimes name = elf_get_word(e, v, SH_NAME); 5281556Srgrimes if (flags & ED_NOTE && 5291556Srgrimes strcmp(shstrtab + name, ".note.ABI-tag") == 0) 5301556Srgrimes elf_print_note(e, v); 53190111Simp break; 53290111Simp case SHT_DYNSYM: 5331556Srgrimes if (flags & ED_SYMTAB) 5341556Srgrimes elf_print_symtab(e, v, dynstr); 53575160Sbrian break; 53675160Sbrian case SHT_PROGBITS: 5371556Srgrimes name = elf_get_word(e, v, SH_NAME); 5381556Srgrimes if (flags & ED_GOT && 5391556Srgrimes strcmp(shstrtab + name, ".got") == 0) 5401556Srgrimes elf_print_got(e, v); 5411556Srgrimes break; 5421556Srgrimes case SHT_HASH: 5431556Srgrimes if (flags & ED_HASH) 5441556Srgrimes elf_print_hash(e, v); 5458855Srgrimes break; 5461556Srgrimes case SHT_NULL: 5471556Srgrimes case SHT_STRTAB: 5488855Srgrimes case SHT_NOBITS: 5491556Srgrimes case SHT_SHLIB: 5501556Srgrimes break; 5511556Srgrimes } 55275160Sbrian } 55375160Sbrian 55475160Sbrian return 0; 55575160Sbrian} 55675160Sbrian 55775160Sbrianstatic void 5581556Srgrimeself_print_ehdr(Elf32_Ehdr *e) 5591556Srgrimes{ 5601556Srgrimes u_int64_t class; 5611556Srgrimes u_int64_t data; 5621556Srgrimes u_int64_t osabi; 5631556Srgrimes u_int64_t type; 5641556Srgrimes u_int64_t machine; 5651556Srgrimes u_int64_t version; 5661556Srgrimes u_int64_t entry; 5671556Srgrimes u_int64_t phoff; 5681556Srgrimes u_int64_t shoff; 5691556Srgrimes u_int64_t flags; 5701556Srgrimes u_int64_t ehsize; 5711556Srgrimes u_int64_t phentsize; 5721556Srgrimes u_int64_t phnum; 5731556Srgrimes u_int64_t shentsize; 5741556Srgrimes u_int64_t shnum; 5751556Srgrimes u_int64_t shstrndx; 5761556Srgrimes 5771556Srgrimes class = elf_get_byte(e, e, E_CLASS); 5781556Srgrimes data = elf_get_byte(e, e, E_DATA); 5791556Srgrimes osabi = elf_get_byte(e, e, E_OSABI); 5801556Srgrimes type = elf_get_quarter(e, e, E_TYPE); 58175160Sbrian machine = elf_get_quarter(e, e, E_MACHINE); 5821556Srgrimes version = elf_get_word(e, e, E_VERSION); 5831556Srgrimes entry = elf_get_addr(e, e, E_ENTRY); 5841556Srgrimes phoff = elf_get_off(e, e, E_PHOFF); 5851556Srgrimes shoff = elf_get_off(e, e, E_SHOFF); 5861556Srgrimes flags = elf_get_word(e, e, E_FLAGS); 5871556Srgrimes ehsize = elf_get_quarter(e, e, E_EHSIZE); 5881556Srgrimes phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 5891556Srgrimes phnum = elf_get_quarter(e, e, E_PHNUM); 5901556Srgrimes shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 5911556Srgrimes shnum = elf_get_quarter(e, e, E_SHNUM); 5921556Srgrimes shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 5931556Srgrimes fprintf(out, "\nelf header:\n"); 59475160Sbrian fprintf(out, "\n"); 59575160Sbrian fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data], 59675160Sbrian ei_abis[osabi]); 59775160Sbrian fprintf(out, "\te_type: %s\n", e_types[type]); 59875160Sbrian fprintf(out, "\te_machine: %s\n", e_machines(machine)); 59975160Sbrian fprintf(out, "\te_version: %s\n", ei_versions[version]); 60075160Sbrian fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry); 60175160Sbrian fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff); 60275160Sbrian fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff); 60375160Sbrian fprintf(out, "\te_flags: %jd\n", (intmax_t)flags); 6041556Srgrimes fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize); 6051556Srgrimes fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize); 60617987Speter fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum); 60790111Simp fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize); 60890111Simp fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum); 60917987Speter fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx); 6101556Srgrimes} 61117987Speter 61217987Speterstatic void 61317987Speterelf_print_phdr(Elf32_Ehdr *e, void *p) 61417987Speter{ 61517987Speter u_int64_t phentsize; 61617987Speter u_int64_t phnum; 61717987Speter u_int64_t type; 61817987Speter u_int64_t offset; 61990111Simp u_int64_t vaddr; 62090111Simp u_int64_t paddr; 62117987Speter u_int64_t filesz; 62217987Speter u_int64_t memsz; 62317987Speter u_int64_t flags; 62417987Speter u_int64_t align; 62517987Speter void *v; 62617987Speter int i; 62717987Speter 62817987Speter phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 62917987Speter phnum = elf_get_quarter(e, e, E_PHNUM); 63020425Ssteve fprintf(out, "\nprogram header:\n"); 63117987Speter for (i = 0; (u_int64_t)i < phnum; i++) { 63217987Speter v = (char *)p + i * phentsize; 63317987Speter type = elf_get_word(e, v, P_TYPE); 63417987Speter offset = elf_get_off(e, v, P_OFFSET); 63517987Speter vaddr = elf_get_addr(e, v, P_VADDR); 63617987Speter paddr = elf_get_addr(e, v, P_PADDR); 63717987Speter filesz = elf_get_size(e, v, P_FILESZ); 63817987Speter memsz = elf_get_size(e, v, P_MEMSZ); 6391556Srgrimes flags = elf_get_word(e, v, P_FLAGS); 64090111Simp align = elf_get_size(e, v, P_ALIGN); 64190111Simp fprintf(out, "\n"); 6421556Srgrimes fprintf(out, "entry: %d\n", i); 6431556Srgrimes fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]); 6441556Srgrimes fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset); 6451556Srgrimes fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr); 6461556Srgrimes fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr); 6471556Srgrimes fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz); 6481556Srgrimes fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz); 6491556Srgrimes fprintf(out, "\tp_flags: %s\n", p_flags[flags]); 6501556Srgrimes fprintf(out, "\tp_align: %jd\n", (intmax_t)align); 6511556Srgrimes } 6521556Srgrimes} 6531556Srgrimes 6541556Srgrimesstatic void 6551556Srgrimeself_print_shdr(Elf32_Ehdr *e, void *sh) 6561556Srgrimes{ 6571556Srgrimes u_int64_t shentsize; 6581556Srgrimes u_int64_t shnum; 6591556Srgrimes u_int64_t name; 6601556Srgrimes u_int64_t type; 6611556Srgrimes u_int64_t flags; 6621556Srgrimes u_int64_t addr; 6631556Srgrimes u_int64_t offset; 6641556Srgrimes u_int64_t size; 6651556Srgrimes u_int64_t shlink; 6661556Srgrimes u_int64_t info; 6671556Srgrimes u_int64_t addralign; 6681556Srgrimes u_int64_t entsize; 6691556Srgrimes void *v; 67017987Speter int i; 6711556Srgrimes 67217987Speter shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 6731556Srgrimes shnum = elf_get_quarter(e, e, E_SHNUM); 6741556Srgrimes fprintf(out, "\nsection header:\n"); 6751556Srgrimes for (i = 0; (u_int64_t)i < shnum; i++) { 6761556Srgrimes v = (char *)sh + i * shentsize; 6771556Srgrimes name = elf_get_word(e, v, SH_NAME); 6781556Srgrimes type = elf_get_word(e, v, SH_TYPE); 6791556Srgrimes flags = elf_get_word(e, v, SH_FLAGS); 6801556Srgrimes addr = elf_get_addr(e, v, SH_ADDR); 6811556Srgrimes offset = elf_get_off(e, v, SH_OFFSET); 68290111Simp size = elf_get_size(e, v, SH_SIZE); 68390111Simp shlink = elf_get_word(e, v, SH_LINK); 6841556Srgrimes info = elf_get_word(e, v, SH_INFO); 6851556Srgrimes addralign = elf_get_size(e, v, SH_ADDRALIGN); 6861556Srgrimes entsize = elf_get_size(e, v, SH_ENTSIZE); 6871556Srgrimes fprintf(out, "\n"); 6881556Srgrimes fprintf(out, "entry: %d\n", i); 6891556Srgrimes fprintf(out, "\tsh_name: %s\n", shstrtab + name); 6901556Srgrimes fprintf(out, "\tsh_type: %s\n", sh_types(type)); 6911556Srgrimes fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]); 6921556Srgrimes fprintf(out, "\tsh_addr: %#jx\n", addr); 6931556Srgrimes fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset); 6941556Srgrimes fprintf(out, "\tsh_size: %jd\n", (intmax_t)size); 6951556Srgrimes fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink); 6961556Srgrimes fprintf(out, "\tsh_info: %jd\n", (intmax_t)info); 6971556Srgrimes fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign); 6981556Srgrimes fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize); 6991556Srgrimes } 7001556Srgrimes} 7011556Srgrimes 7021556Srgrimesstatic void 7031556Srgrimeself_print_symtab(Elf32_Ehdr *e, void *sh, char *str) 7041556Srgrimes{ 7051556Srgrimes u_int64_t offset; 70690111Simp u_int64_t entsize; 70790111Simp u_int64_t size; 7081556Srgrimes u_int64_t name; 7091556Srgrimes u_int64_t value; 7101556Srgrimes u_int64_t info; 7111556Srgrimes u_int64_t shndx; 7121556Srgrimes void *st; 7131556Srgrimes int len; 7141556Srgrimes int i; 7151556Srgrimes 71690111Simp offset = elf_get_off(e, sh, SH_OFFSET); 71790111Simp entsize = elf_get_size(e, sh, SH_ENTSIZE); 7181556Srgrimes size = elf_get_size(e, sh, SH_SIZE); 7191556Srgrimes name = elf_get_word(e, sh, SH_NAME); 7201556Srgrimes len = size / entsize; 7211556Srgrimes fprintf(out, "\nsymbol table (%s):\n", shstrtab + name); 7221556Srgrimes for (i = 0; i < len; i++) { 7231556Srgrimes st = (char *)e + offset + i * entsize; 7248855Srgrimes name = elf_get_word(e, st, ST_NAME); 7251556Srgrimes value = elf_get_addr(e, st, ST_VALUE); 7261556Srgrimes size = elf_get_size(e, st, ST_SIZE); 7271556Srgrimes info = elf_get_byte(e, st, ST_INFO); 7281556Srgrimes shndx = elf_get_quarter(e, st, ST_SHNDX); 7291556Srgrimes fprintf(out, "\n"); 7301556Srgrimes fprintf(out, "entry: %d\n", i); 7311556Srgrimes fprintf(out, "\tst_name: %s\n", str + name); 7321556Srgrimes fprintf(out, "\tst_value: %#jx\n", value); 7331556Srgrimes fprintf(out, "\tst_size: %jd\n", (intmax_t)size); 7341556Srgrimes fprintf(out, "\tst_info: %s %s\n", 7351556Srgrimes st_types[ELF32_ST_TYPE(info)], 7361556Srgrimes st_bindings[ELF32_ST_BIND(info)]); 7371556Srgrimes fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx); 7381556Srgrimes } 7391556Srgrimes} 7401556Srgrimes 7411556Srgrimesstatic void 7421556Srgrimeself_print_dynamic(Elf32_Ehdr *e, void *sh) 74320425Ssteve{ 74417987Speter u_int64_t offset; 74525230Ssteve u_int64_t entsize; 7461556Srgrimes u_int64_t size; 7471556Srgrimes int64_t tag; 74820425Ssteve u_int64_t ptr; 74917987Speter u_int64_t val; 7501556Srgrimes void *d; 7511556Srgrimes int i; 7521556Srgrimes 7531556Srgrimes offset = elf_get_off(e, sh, SH_OFFSET); 7541556Srgrimes entsize = elf_get_size(e, sh, SH_ENTSIZE); 75518018Speter size = elf_get_size(e, sh, SH_SIZE); 75618018Speter fprintf(out, "\ndynamic:\n"); 7571556Srgrimes for (i = 0; (u_int64_t)i < size / entsize; i++) { 7581556Srgrimes d = (char *)e + offset + i * entsize; 7591556Srgrimes tag = elf_get_size(e, d, D_TAG); 7601556Srgrimes ptr = elf_get_size(e, d, D_PTR); 7611556Srgrimes val = elf_get_addr(e, d, D_VAL); 7621556Srgrimes fprintf(out, "\n"); 76375160Sbrian fprintf(out, "entry: %d\n", i); 7641556Srgrimes fprintf(out, "\td_tag: %s\n", d_tags(tag)); 7651556Srgrimes switch (tag) { 7661556Srgrimes case DT_NEEDED: 7671556Srgrimes case DT_SONAME: 7681556Srgrimes case DT_RPATH: 7691556Srgrimes fprintf(out, "\td_val: %s\n", dynstr + val); 7701556Srgrimes break; 7711556Srgrimes case DT_PLTRELSZ: 7721556Srgrimes case DT_RELA: 7731556Srgrimes case DT_RELASZ: 7741556Srgrimes case DT_RELAENT: 7751556Srgrimes case DT_STRSZ: 7761556Srgrimes case DT_SYMENT: 7771556Srgrimes case DT_RELSZ: 7781556Srgrimes case DT_RELENT: 7791556Srgrimes case DT_PLTREL: 7801556Srgrimes fprintf(out, "\td_val: %jd\n", (intmax_t)val); 7811556Srgrimes break; 7821556Srgrimes case DT_PLTGOT: 7831556Srgrimes case DT_HASH: 7841556Srgrimes case DT_STRTAB: 7851556Srgrimes case DT_SYMTAB: 7861556Srgrimes case DT_INIT: 7871556Srgrimes case DT_FINI: 7881556Srgrimes case DT_REL: 7891556Srgrimes case DT_JMPREL: 7901556Srgrimes fprintf(out, "\td_ptr: %#jx\n", ptr); 7911556Srgrimes break; 7921556Srgrimes case DT_NULL: 7931556Srgrimes case DT_SYMBOLIC: 7941556Srgrimes case DT_DEBUG: 7951556Srgrimes case DT_TEXTREL: 79690111Simp break; 79790111Simp } 79825230Ssteve } 7991556Srgrimes} 8001556Srgrimes 8011556Srgrimesstatic void 8021556Srgrimeself_print_rela(Elf32_Ehdr *e, void *sh) 8031556Srgrimes{ 8041556Srgrimes u_int64_t offset; 8051556Srgrimes u_int64_t entsize; 8061556Srgrimes u_int64_t size; 8071556Srgrimes u_int64_t name; 8081556Srgrimes u_int64_t info; 8091556Srgrimes int64_t addend; 8101556Srgrimes void *ra; 8111556Srgrimes void *v; 8121556Srgrimes int i; 8131556Srgrimes 8141556Srgrimes offset = elf_get_off(e, sh, SH_OFFSET); 8151556Srgrimes entsize = elf_get_size(e, sh, SH_ENTSIZE); 8161556Srgrimes size = elf_get_size(e, sh, SH_SIZE); 8171556Srgrimes name = elf_get_word(e, sh, SH_NAME); 8181556Srgrimes v = (char *)e + offset; 8191556Srgrimes fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name); 8201556Srgrimes for (i = 0; (u_int64_t)i < size / entsize; i++) { 8211556Srgrimes ra = (char *)v + i * entsize; 8221556Srgrimes offset = elf_get_addr(e, ra, RA_OFFSET); 8231556Srgrimes info = elf_get_word(e, ra, RA_INFO); 8241556Srgrimes addend = elf_get_off(e, ra, RA_ADDEND); 8251556Srgrimes fprintf(out, "\n"); 8261556Srgrimes fprintf(out, "entry: %d\n", i); 8271556Srgrimes fprintf(out, "\tr_offset: %#jx\n", offset); 8281556Srgrimes fprintf(out, "\tr_info: %jd\n", (intmax_t)info); 8291556Srgrimes fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend); 8301556Srgrimes } 8311556Srgrimes} 8321556Srgrimes 8331556Srgrimesstatic void 8341556Srgrimeself_print_rel(Elf32_Ehdr *e, void *sh) 8351556Srgrimes{ 8361556Srgrimes u_int64_t offset; 8371556Srgrimes u_int64_t entsize; 8381556Srgrimes u_int64_t size; 8391556Srgrimes u_int64_t name; 8401556Srgrimes u_int64_t info; 8411556Srgrimes void *r; 8421556Srgrimes void *v; 8431556Srgrimes int i; 8441556Srgrimes 8451556Srgrimes offset = elf_get_off(e, sh, SH_OFFSET); 8461556Srgrimes entsize = elf_get_size(e, sh, SH_ENTSIZE); 8471556Srgrimes size = elf_get_size(e, sh, SH_SIZE); 8481556Srgrimes name = elf_get_word(e, sh, SH_NAME); 8491556Srgrimes v = (char *)e + offset; 8501556Srgrimes fprintf(out, "\nrelocation (%s):\n", shstrtab + name); 8511556Srgrimes for (i = 0; (u_int64_t)i < size / entsize; i++) { 8521556Srgrimes r = (char *)v + i * entsize; 8531556Srgrimes offset = elf_get_addr(e, r, R_OFFSET); 8541556Srgrimes info = elf_get_word(e, r, R_INFO); 8551556Srgrimes fprintf(out, "\n"); 8561556Srgrimes fprintf(out, "entry: %d\n", i); 8571556Srgrimes fprintf(out, "\tr_offset: %#jx\n", offset); 8581556Srgrimes fprintf(out, "\tr_info: %jd\n", (intmax_t)info); 8591556Srgrimes } 8601556Srgrimes} 8611556Srgrimes 8621556Srgrimesstatic void 8631556Srgrimeself_print_interp(Elf32_Ehdr *e, void *p) 8641556Srgrimes{ 8651556Srgrimes u_int64_t offset; 8661556Srgrimes char *s; 8671556Srgrimes 8681556Srgrimes offset = elf_get_off(e, p, P_OFFSET); 8691556Srgrimes s = (char *)e + offset; 8701556Srgrimes fprintf(out, "\ninterp:\n"); 8711556Srgrimes fprintf(out, "\t%s\n", s); 8721556Srgrimes} 8731556Srgrimes 8741556Srgrimesstatic void 8751556Srgrimeself_print_got(Elf32_Ehdr *e, void *sh) 8761556Srgrimes{ 8771556Srgrimes u_int64_t offset; 8781556Srgrimes u_int64_t addralign; 8791556Srgrimes u_int64_t size; 8801556Srgrimes u_int64_t addr; 8811556Srgrimes void *v; 8821556Srgrimes int i; 8831556Srgrimes 8841556Srgrimes offset = elf_get_off(e, sh, SH_OFFSET); 8851556Srgrimes addralign = elf_get_size(e, sh, SH_ADDRALIGN); 8861556Srgrimes size = elf_get_size(e, sh, SH_SIZE); 88790111Simp v = (char *)e + offset; 88890111Simp fprintf(out, "\nglobal offset table:\n"); 88917987Speter for (i = 0; (u_int64_t)i < size / addralign; i++) { 89017987Speter addr = elf_get_addr(e, (char *)v + i * addralign, 0); 8911556Srgrimes fprintf(out, "\n"); 8921556Srgrimes fprintf(out, "entry: %d\n", i); 8931556Srgrimes fprintf(out, "\t%#jx\n", addr); 8941556Srgrimes } 8951556Srgrimes} 8961556Srgrimes 8971556Srgrimesstatic void 8981556Srgrimeself_print_hash(Elf32_Ehdr *e __unused, void *sh __unused) 8991556Srgrimes{ 9001556Srgrimes} 90154679Scracauer 90217987Speterstatic void 90317987Speterelf_print_note(Elf32_Ehdr *e, void *sh) 90417987Speter{ 90517987Speter u_int64_t offset; 90617987Speter u_int64_t size; 90717987Speter u_int64_t name; 90817987Speter u_int32_t namesz; 90917987Speter u_int32_t descsz; 91017987Speter u_int32_t desc; 91117987Speter char *n, *s; 91217987Speter 91354679Scracauer offset = elf_get_off(e, sh, SH_OFFSET); 91417987Speter size = elf_get_size(e, sh, SH_SIZE); 9151556Srgrimes name = elf_get_word(e, sh, SH_NAME); 9161556Srgrimes n = (char *)e + offset; 9171556Srgrimes fprintf(out, "\nnote (%s):\n", shstrtab + name); 9181556Srgrimes while (n < ((char *)e + offset + size)) { 9191556Srgrimes namesz = elf_get_word(e, n, N_NAMESZ); 9201556Srgrimes descsz = elf_get_word(e, n, N_DESCSZ); 9211556Srgrimes s = n + sizeof(Elf_Note); 9221556Srgrimes desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0); 9231556Srgrimes fprintf(out, "\t%s %d\n", s, desc); 9241556Srgrimes n += sizeof(Elf_Note) + namesz + descsz; 9251556Srgrimes } 9261556Srgrimes} 9271556Srgrimes 9281556Srgrimesstatic u_int64_t 9291556Srgrimeself_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member) 9301556Srgrimes{ 9311556Srgrimes u_int64_t val; 9321556Srgrimes 9331556Srgrimes val = 0; 9341556Srgrimes switch (e->e_ident[EI_CLASS]) { 9351556Srgrimes case ELFCLASS32: 9361556Srgrimes val = ((uint8_t *)base)[elf32_offsets[member]]; 9371556Srgrimes break; 9381556Srgrimes case ELFCLASS64: 9391556Srgrimes val = ((uint8_t *)base)[elf64_offsets[member]]; 9401556Srgrimes break; 94154679Scracauer case ELFCLASSNONE: 94264705Scracauer errx(1, "invalid class"); 94354679Scracauer } 94454679Scracauer 9451556Srgrimes return val; 9461556Srgrimes} 9471556Srgrimes 9481556Srgrimesstatic u_int64_t 9491556Srgrimeself_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member) 9501556Srgrimes{ 9511556Srgrimes u_int64_t val; 9521556Srgrimes 9531556Srgrimes val = 0; 9541556Srgrimes switch (e->e_ident[EI_CLASS]) { 9551556Srgrimes case ELFCLASS32: 9561556Srgrimes base = (char *)base + elf32_offsets[member]; 9571556Srgrimes switch (e->e_ident[EI_DATA]) { 9581556Srgrimes case ELFDATA2MSB: 9591556Srgrimes val = be16dec(base); 9601556Srgrimes break; 9611556Srgrimes case ELFDATA2LSB: 9621556Srgrimes val = le16dec(base); 9631556Srgrimes break; 9641556Srgrimes case ELFDATANONE: 9651556Srgrimes errx(1, "invalid data format"); 9661556Srgrimes } 9671556Srgrimes break; 9681556Srgrimes case ELFCLASS64: 9691556Srgrimes base = (char *)base + elf64_offsets[member]; 9701556Srgrimes switch (e->e_ident[EI_DATA]) { 9711556Srgrimes case ELFDATA2MSB: 9721556Srgrimes val = be16dec(base); 9731556Srgrimes break; 9741556Srgrimes case ELFDATA2LSB: 97554631Scracauer val = le16dec(base); 97654631Scracauer break; 97754631Scracauer case ELFDATANONE: 9781556Srgrimes errx(1, "invalid data format"); 97983675Stegge } 9801556Srgrimes break; 98139137Stegge case ELFCLASSNONE: 98238887Stegge errx(1, "invalid class"); 9831556Srgrimes } 9841556Srgrimes 9851556Srgrimes return val; 9861556Srgrimes} 9871556Srgrimes 98839137Stegge#if 0 98939137Steggestatic u_int64_t 9901556Srgrimeself_get_half(Elf32_Ehdr *e, void *base, elf_member_t member) 9911556Srgrimes{ 9921556Srgrimes u_int64_t val; 99339137Stegge 99439137Stegge val = 0; 9951556Srgrimes switch (e->e_ident[EI_CLASS]) { 9961556Srgrimes case ELFCLASS32: 9971556Srgrimes base = (char *)base + elf32_offsets[member]; 9981556Srgrimes switch (e->e_ident[EI_DATA]) { 99939137Stegge case ELFDATA2MSB: 100039137Stegge val = be16dec(base); 10011556Srgrimes break; 10021556Srgrimes case ELFDATA2LSB: 100339137Stegge val = le16dec(base); 10041556Srgrimes break; 100539137Stegge case ELFDATANONE: 100639137Stegge errx(1, "invalid data format"); 10071556Srgrimes } 100839137Stegge break; 100939137Stegge case ELFCLASS64: 10101556Srgrimes base = (char *)base + elf64_offsets[member]; 10111556Srgrimes switch (e->e_ident[EI_DATA]) { 10121556Srgrimes case ELFDATA2MSB: 10131556Srgrimes val = be32dec(base); 10141556Srgrimes break; 10151556Srgrimes case ELFDATA2LSB: 10161556Srgrimes val = le32dec(base); 10171556Srgrimes break; 10181556Srgrimes case ELFDATANONE: 10191556Srgrimes errx(1, "invalid data format"); 10201556Srgrimes } 10211556Srgrimes break; 10221556Srgrimes case ELFCLASSNONE: 10231556Srgrimes errx(1, "invalid class"); 10241556Srgrimes } 10251556Srgrimes 10261556Srgrimes return val; 10271556Srgrimes} 10281556Srgrimes#endif 10291556Srgrimes 10301556Srgrimesstatic u_int64_t 10311556Srgrimeself_get_word(Elf32_Ehdr *e, void *base, elf_member_t member) 10321556Srgrimes{ 10331556Srgrimes u_int64_t val; 10341556Srgrimes 10351556Srgrimes val = 0; 10361556Srgrimes switch (e->e_ident[EI_CLASS]) { 103739137Stegge case ELFCLASS32: 103839137Stegge base = (char *)base + elf32_offsets[member]; 103939137Stegge switch (e->e_ident[EI_DATA]) { 104039137Stegge case ELFDATA2MSB: 10411556Srgrimes val = be32dec(base); 10421556Srgrimes break; 10431556Srgrimes case ELFDATA2LSB: 10448855Srgrimes val = le32dec(base); 10451556Srgrimes break; 10461556Srgrimes case ELFDATANONE: 10471556Srgrimes errx(1, "invalid data format"); 10481556Srgrimes } 10491556Srgrimes break; 10501556Srgrimes case ELFCLASS64: 10511556Srgrimes base = (char *)base + elf64_offsets[member]; 10521556Srgrimes switch (e->e_ident[EI_DATA]) { 10531556Srgrimes case ELFDATA2MSB: 10541556Srgrimes val = be32dec(base); 10551556Srgrimes break; 10561556Srgrimes case ELFDATA2LSB: 10571556Srgrimes val = le32dec(base); 10581556Srgrimes break; 10591556Srgrimes case ELFDATANONE: 10601556Srgrimes errx(1, "invalid data format"); 10611556Srgrimes } 10621556Srgrimes break; 10631556Srgrimes case ELFCLASSNONE: 10641556Srgrimes errx(1, "invalid class"); 10651556Srgrimes } 10661556Srgrimes 10671556Srgrimes return val; 10681556Srgrimes} 10691556Srgrimes 10701556Srgrimesstatic u_int64_t 10711556Srgrimeself_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member) 10721556Srgrimes{ 10731556Srgrimes u_int64_t val; 10741556Srgrimes 10751556Srgrimes val = 0; 10761556Srgrimes switch (e->e_ident[EI_CLASS]) { 10771556Srgrimes case ELFCLASS32: 10781556Srgrimes base = (char *)base + elf32_offsets[member]; 10791556Srgrimes switch (e->e_ident[EI_DATA]) { 10801556Srgrimes case ELFDATA2MSB: 10811556Srgrimes val = be32dec(base); 10821556Srgrimes break; 10831556Srgrimes case ELFDATA2LSB: 10841556Srgrimes val = le32dec(base); 10851556Srgrimes break; 10861556Srgrimes case ELFDATANONE: 10871556Srgrimes errx(1, "invalid data format"); 10881556Srgrimes } 10891556Srgrimes break; 10901556Srgrimes case ELFCLASS64: 10911556Srgrimes base = (char *)base + elf64_offsets[member]; 10921556Srgrimes switch (e->e_ident[EI_DATA]) { 10931556Srgrimes case ELFDATA2MSB: 10941556Srgrimes val = be64dec(base); 10951556Srgrimes break; 10961556Srgrimes case ELFDATA2LSB: 10971556Srgrimes val = le64dec(base); 10981556Srgrimes break; 10991556Srgrimes case ELFDATANONE: 11001556Srgrimes errx(1, "invalid data format"); 11011556Srgrimes } 11021556Srgrimes break; 11031556Srgrimes case ELFCLASSNONE: 11041556Srgrimes errx(1, "invalid class"); 11051556Srgrimes } 11061556Srgrimes 11071556Srgrimes return val; 11081556Srgrimes} 11091556Srgrimes 11101556Srgrimesstatic void 11111556Srgrimesusage(void) 111225230Ssteve{ 11131556Srgrimes fprintf(stderr, "usage: elfdump -a | -cdeGhinprs [-w file] file\n"); 11141556Srgrimes exit(1); 11151556Srgrimes} 11161556Srgrimes