elfdump.c revision 110257
1233294Sstas/*- 2102644Snectar * Copyright (c) 2003 David O'Brien. All rights reserved. 357416Smarkm * Copyright (c) 2001 Jake Burkholder 4142403Snectar * All rights reserved. 5233294Sstas * 6233294Sstas * Redistribution and use in source and binary forms, with or without 757416Smarkm * modification, are permitted provided that the following conditions 857416Smarkm * are met: 957416Smarkm * 1. Redistributions of source code must retain the above copyright 1057416Smarkm * notice, this list of conditions and the following disclaimer. 1157416Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1257416Smarkm * notice, this list of conditions and the following disclaimer in the 1357416Smarkm * documentation and/or other materials provided with the distribution. 1457416Smarkm * 1557416Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1690926Snectar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1790926Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1990926Snectar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2190926Snectar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2357416Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2457416Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25233294Sstas * SUCH DAMAGE. 2657416Smarkm */ 27233294Sstas 28102644Snectar#include <sys/cdefs.h> 29102644Snectar__FBSDID("$FreeBSD: head/usr.bin/elfdump/elfdump.c 110257 2003-02-03 01:30:47Z obrien $"); 30102644Snectar 31127808Snectar#include <sys/types.h> 3290926Snectar#include <sys/elf32.h> 33127808Snectar#include <sys/elf64.h> 3457416Smarkm#include <sys/mman.h> 3557416Smarkm#include <sys/stat.h> 3657416Smarkm#include <err.h> 3757416Smarkm#include <fcntl.h> 3857416Smarkm#include <inttypes.h> 3957416Smarkm#include <stddef.h> 40178825Sdfr#include <stdio.h> 4157416Smarkm#include <stdlib.h> 42142403Snectar#include <string.h> 43142403Snectar#include <unistd.h> 44142403Snectar 45142403Snectar#define ED_DYN (1<<0) 46142403Snectar#define ED_EHDR (1<<1) 47142403Snectar#define ED_GOT (1<<2) 48233294Sstas#define ED_HASH (1<<3) 49142403Snectar#define ED_INTERP (1<<4) 50142403Snectar#define ED_NOTE (1<<5) 51142403Snectar#define ED_PHDR (1<<6) 52142403Snectar#define ED_REL (1<<7) 53142403Snectar#define ED_SHDR (1<<8) 54142403Snectar#define ED_SYMTAB (1<<9) 55142403Snectar#define ED_ALL ((1<<10)-1) 56142403Snectar 57142403Snectar#define elf_get_addr elf_get_quad 58142403Snectar#define elf_get_off elf_get_quad 59142403Snectar#define elf_get_size elf_get_quad 60142403Snectar 61142403Snectarenum elf_member { 62142403Snectar D_TAG = 1, D_PTR, D_VAL, 63233294Sstas 64142403Snectar E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY, 65142403Snectar E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE, 66142403Snectar E_SHNUM, E_SHSTRNDX, 67142403Snectar 68178825Sdfr N_NAMESZ, N_DESCSZ, N_TYPE, 69142403Snectar 70142403Snectar P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS, 71142403Snectar P_ALIGN, 72142403Snectar 73142403Snectar SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK, 74142403Snectar SH_INFO, SH_ADDRALIGN, SH_ENTSIZE, 75142403Snectar 76142403Snectar ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX, 77233294Sstas 78233294Sstas R_OFFSET, R_INFO, 79233294Sstas 80233294Sstas RA_OFFSET, RA_INFO, RA_ADDEND 81233294Sstas}; 82233294Sstas 83178825Sdfrtypedef enum elf_member elf_member_t; 84178825Sdfr 85178825Sdfrint elf32_offsets[] = { 86178825Sdfr 0, 87178825Sdfr 88178825Sdfr offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr), 89178825Sdfr offsetof(Elf32_Dyn, d_un.d_val), 90233294Sstas 91142403Snectar offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 92142403Snectar offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 93178825Sdfr offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 94142403Snectar offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine), 95142403Snectar offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry), 96233294Sstas offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff), 97142403Snectar offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize), 98142403Snectar offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum), 99142403Snectar offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum), 100142403Snectar offsetof(Elf32_Ehdr, e_shstrndx), 101178825Sdfr 102178825Sdfr offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 103178825Sdfr offsetof(Elf_Note, n_type), 104178825Sdfr 105178825Sdfr offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset), 106178825Sdfr offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr), 107178825Sdfr offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz), 108233294Sstas offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align), 109233294Sstas 110233294Sstas offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type), 111142403Snectar offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr), 112142403Snectar offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size), 113142403Snectar offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info), 114142403Snectar offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize), 115233294Sstas 116233294Sstas offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value), 117233294Sstas offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info), 118233294Sstas offsetof(Elf32_Sym, st_shndx), 119233294Sstas 120233294Sstas offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info), 121233294Sstas 122233294Sstas offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info), 123233294Sstas offsetof(Elf32_Rela, r_addend) 124233294Sstas}; 125233294Sstas 126233294Sstasint elf64_offsets[] = { 127233294Sstas 0, 128233294Sstas 129233294Sstas offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr), 130233294Sstas offsetof(Elf64_Dyn, d_un.d_val), 131233294Sstas 132233294Sstas offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 133233294Sstas offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 134233294Sstas offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 135233294Sstas offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine), 136233294Sstas offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry), 137233294Sstas offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff), 138233294Sstas offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize), 139233294Sstas offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum), 140127808Snectar offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum), 14157416Smarkm offsetof(Elf64_Ehdr, e_shstrndx), 14272445Sassar 143127808Snectar offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 144233294Sstas offsetof(Elf_Note, n_type), 145233294Sstas 146127808Snectar offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset), 147127808Snectar offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr), 148127808Snectar offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz), 14957416Smarkm offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align), 15057416Smarkm 151233294Sstas offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type), 152233294Sstas offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr), 15357416Smarkm offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size), 15457416Smarkm offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info), 15557416Smarkm offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize), 156233294Sstas 157127808Snectar offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value), 15890926Snectar offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info), 15972445Sassar offsetof(Elf64_Sym, st_shndx), 160127808Snectar 161127808Snectar offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info), 162233294Sstas 16357416Smarkm offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info), 164127808Snectar offsetof(Elf64_Rela, r_addend) 165233294Sstas}; 16690926Snectar 167178825Sdfr/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 168178825Sdfrstatic const char * 16972445Sassard_tags(u_int64_t tag) { 170233294Sstas switch (tag) { 171233294Sstas case 0: return "DT_NULL"; 172233294Sstas case 1: return "DT_NEEDED"; 173127808Snectar case 2: return "DT_PLTRELSZ"; 174127808Snectar case 3: return "DT_PLTGOT"; 175127808Snectar case 4: return "DT_HASH"; 176127808Snectar case 5: return "DT_STRTAB"; 177127808Snectar case 6: return "DT_SYMTAB"; 178233294Sstas case 7: return "DT_RELA"; 179178825Sdfr case 8: return "DT_RELASZ"; 18057416Smarkm case 9: return "DT_RELAENT"; 18172445Sassar case 10: return "DT_STRSZ"; 182178825Sdfr case 11: return "DT_SYMENT"; 183127808Snectar case 12: return "DT_INIT"; 184127808Snectar case 13: return "DT_FINI"; 185233294Sstas case 14: return "DT_SONAME"; 186233294Sstas case 15: return "DT_RPATH"; 187127808Snectar case 16: return "DT_SYMBOLIC"; 188127808Snectar case 17: return "DT_REL"; 189233294Sstas case 18: return "DT_RELSZ"; 190178825Sdfr case 19: return "DT_RELENT"; 191127808Snectar case 20: return "DT_PLTREL"; 192127808Snectar case 21: return "DT_DEBUG"; 193127808Snectar case 22: return "DT_TEXTREL"; 19490926Snectar case 23: return "DT_JMPREL"; 195233294Sstas case 24: return "DT_BIND_NOW"; 196127808Snectar case 25: return "DT_INIT_ARRAY"; 197178825Sdfr case 26: return "DT_FINI_ARRAY"; 19857416Smarkm case 27: return "DT_INIT_ARRAYSZ"; 199102644Snectar case 28: return "DT_FINI_ARRAYSZ"; 200102644Snectar case 29: return "DT_RUNPATH"; 201178825Sdfr case 30: return "DT_FLAGS"; 202127808Snectar case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ 203127808Snectar case 33: return "DT_PREINIT_ARRAYSZ"; 20457416Smarkm /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 20557416Smarkm case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 20690926Snectar case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 207127808Snectar case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 208127808Snectar case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 209127808Snectar case 0x6ffffdf9: return "DT_PLTPADSZ"; 210127808Snectar case 0x6ffffdfa: return "DT_MOVEENT"; 211127808Snectar case 0x6ffffdfb: return "DT_MOVESZ"; 21290926Snectar case 0x6ffffdfc: return "DT_FEATURE"; 21390926Snectar case 0x6ffffdfd: return "DT_POSFLAG_1"; 21490926Snectar case 0x6ffffdfe: return "DT_SYMINSZ"; 215127808Snectar case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; 216127808Snectar case 0x6ffffe00: return "DT_ADDRRNGLO"; 217127808Snectar case 0x6ffffef8: return "DT_GNU_CONFLICT"; 218127808Snectar case 0x6ffffef9: return "DT_GNU_LIBLIST"; 219233294Sstas case 0x6ffffefa: return "DT_SUNW_CONFIG"; 220127808Snectar case 0x6ffffefb: return "DT_SUNW_DEPAUDIT"; 221127808Snectar case 0x6ffffefc: return "DT_SUNW_AUDIT"; 222233294Sstas case 0x6ffffefd: return "DT_SUNW_PLTPAD"; 223178825Sdfr case 0x6ffffefe: return "DT_SUNW_MOVETAB"; 224127808Snectar case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; 225127808Snectar case 0x6ffffff9: return "DT_RELACOUNT"; 226127808Snectar case 0x6ffffffa: return "DT_RELCOUNT"; 227127808Snectar case 0x6ffffffb: return "DT_FLAGS_1"; 228127808Snectar case 0x6ffffffc: return "DT_VERDEF"; 229127808Snectar case 0x6ffffffd: return "DT_VERDEFNUM"; 230127808Snectar case 0x6ffffffe: return "DT_VERNEED"; 231127808Snectar case 0x6fffffff: return "DT_VERNEEDNUM"; 232178825Sdfr case 0x6ffffff0: return "DT_GNU_VERSYM"; 233178825Sdfr /* 0x70000000 - 0x7fffffff processor-specific semantics */ 234178825Sdfr case 0x70000000: return "DT_IA64_PLT_RESERVE"; 235178825Sdfr case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; 236127808Snectar case 0x7ffffffe: return "DT_SUNW_USED"; 237127808Snectar case 0x7fffffff: return "DT_SUNW_FILTER"; 23857416Smarkm default: return "ERROR: TAG NOT DEFINED"; 239127808Snectar } 240233294Sstas}; 241233294Sstas 242127808Snectarstatic const char * 243127808Snectare_machines(u_int mach) 244127808Snectar{ 245127808Snectar switch (mach) { 246127808Snectar case EM_NONE: return "EM_NONE"; 24757416Smarkm case EM_M32: return "EM_M32"; 248127808Snectar case EM_SPARC: return "EM_SPARC"; 249127808Snectar case EM_386: return "EM_386"; 250178825Sdfr case EM_68K: return "EM_68K"; 251127808Snectar case EM_88K: return "EM_88K"; 252127808Snectar case EM_486: return "EM_486"; 25357416Smarkm case EM_860: return "EM_860"; 25457416Smarkm case EM_MIPS: return "EM_MIPS"; 255127808Snectar case EM_IA_64: return "EM_IA_64"; 256127808Snectar } 257233294Sstas return "(unknown machine)"; 258127808Snectar}; 259127808Snectar 260233294Sstasconst char *e_types[] = { 26157416Smarkm "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 26257416Smarkm}; 263120945Snectar 264127808Snectarconst char *ei_versions[] = { 265233294Sstas "EV_NONE", "EV_CURRENT" 266178825Sdfr}; 267233294Sstas 268233294Sstasconst char *ei_classes[] = { 269233294Sstas "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 27057416Smarkm}; 271233294Sstas 272127808Snectarconst char *ei_data[] = { 273233294Sstas "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 274233294Sstas}; 27557416Smarkm 276127808Snectarconst char *ei_abis[] = { 277127808Snectar "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 278127808Snectar "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", 279127808Snectar "ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", 280233294Sstas "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD" 281127808Snectar}; 282127808Snectar 283233294Sstasconst char *p_types[] = { 284233294Sstas "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 285233294Sstas "PT_SHLIB", "PT_PHDR" 286233294Sstas}; 28757416Smarkm 288233294Sstasconst char *p_flags[] = { 289127808Snectar "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 290127808Snectar "PF_X|PF_W|PF_R" 291233294Sstas}; 292233294Sstas 293102644Snectar/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 29457416Smarkmstatic const char * 295178825Sdfrsh_types(u_int64_t sht) { 29657416Smarkm switch (sht) { 29757416Smarkm case 0: return "SHT_NULL"; 29857416Smarkm case 1: return "SHT_PROGBITS"; 299178825Sdfr case 2: return "SHT_SYMTAB"; 30090926Snectar case 3: return "SHT_STRTAB"; 30190926Snectar case 4: return "SHT_RELA"; 30290926Snectar case 5: return "SHT_HASH"; 30390926Snectar case 6: return "SHT_DYNAMIC"; 30457416Smarkm case 7: return "SHT_NOTE"; 305178825Sdfr case 8: return "SHT_NOBITS"; 306178825Sdfr case 9: return "SHT_REL"; 307178825Sdfr case 10: return "SHT_SHLIB"; 308178825Sdfr case 11: return "SHT_DYNSYM"; 309178825Sdfr case 14: return "SHT_INIT_ARRAY"; 310233294Sstas case 15: return "SHT_FINI_ARRAY"; 311127808Snectar case 16: return "SHT_PREINIT_ARRAY"; 312233294Sstas case 17: return "SHT_GROUP"; 313233294Sstas case 18: return "SHT_SYMTAB_SHNDX"; 314127808Snectar /* 0x60000000 - 0x6fffffff operating system-specific semantics */ 315233294Sstas case 0x6ffffff0: return "XXX:VERSYM"; 316178825Sdfr case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 317178825Sdfr case 0x6ffffffc: return "XXX:VERDEF"; 318127808Snectar case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; 319127808Snectar case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; 320127808Snectar case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; 321127808Snectar /* 0x70000000 - 0x7fffffff processor-specific semantics */ 322127808Snectar case 0x70000000: return "SHT_IA_64_EXT"; 323127808Snectar case 0x70000001: return "SHT_IA_64_UNWIND"; 324178825Sdfr case 0x7ffffffd: return "XXX:AUXILIARY"; 325127808Snectar case 0x7fffffff: return "XXX:FILTER"; 326178825Sdfr /* 0x80000000 - 0xffffffff application programs */ 327178825Sdfr default: return "ERROR: SHT NOT DEFINED"; 328102644Snectar } 329102644Snectar}; 330102644Snectar 331178825Sdfrconst char *sh_flags[] = { 332127808Snectar "", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR", 333127808Snectar "SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR", 334127808Snectar "SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR" 335127808Snectar}; 336127808Snectar 337127808Snectarconst char *st_types[] = { 338178825Sdfr "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE" 339127808Snectar}; 340127808Snectar 34172445Sassarconst char *st_bindings[] = { 342127808Snectar "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 343127808Snectar}; 344178825Sdfr 345127808Snectarchar *dynstr; 346127808Snectarchar *shstrtab; 347142403Snectarchar *strtab; 348127808SnectarFILE *out; 349178825Sdfr 350127808Snectaru_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member); 351127808Snectaru_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member); 352178825Sdfru_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member); 353127808Snectaru_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member); 354127808Snectaru_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member); 355178825Sdfr 356233294Sstasvoid elf_print_ehdr(Elf32_Ehdr *e); 357127808Snectarvoid elf_print_phdr(Elf32_Ehdr *e, void *p); 358127808Snectarvoid elf_print_shdr(Elf32_Ehdr *e, void *sh); 359233294Sstasvoid elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str); 360178825Sdfrvoid elf_print_dynamic(Elf32_Ehdr *e, void *sh); 361178825Sdfrvoid elf_print_rel(Elf32_Ehdr *e, void *r); 362233294Sstasvoid elf_print_rela(Elf32_Ehdr *e, void *ra); 363233294Sstasvoid elf_print_interp(Elf32_Ehdr *e, void *p); 364233294Sstasvoid elf_print_got(Elf32_Ehdr *e, void *sh); 365102644Snectarvoid elf_print_hash(Elf32_Ehdr *e, void *sh); 36690926Snectarvoid elf_print_note(Elf32_Ehdr *e, void *sh); 36772445Sassar 36857416Smarkmvoid usage(void); 369233294Sstas 37057416Smarkmint 37157416Smarkmmain(int ac, char **av) 37257416Smarkm{ 37357416Smarkm u_int64_t phoff; 37457416Smarkm u_int64_t shoff; 37557416Smarkm u_int64_t phentsize; 376233294Sstas u_int64_t phnum; 37757416Smarkm u_int64_t shentsize; 378120945Snectar u_int64_t shnum; 37990926Snectar u_int64_t shstrndx; 38072445Sassar u_int64_t offset; 38157416Smarkm u_int64_t name; 38290926Snectar u_int64_t type; 383233294Sstas struct stat sb; 38490926Snectar u_int flags; 38557416Smarkm Elf32_Ehdr *e; 386233294Sstas void *p; 38790926Snectar void *sh; 38857416Smarkm void *v; 38957416Smarkm int fd; 390233294Sstas int ch; 391142403Snectar int i; 392142403Snectar 393142403Snectar out = stdout; 394142403Snectar flags = 0; 395233294Sstas while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1) 396233294Sstas switch (ch) { 397142403Snectar case 'a': 398142403Snectar flags = ED_ALL; 399142403Snectar break; 400233294Sstas case 'c': 401233294Sstas flags |= ED_SHDR; 402233294Sstas break; 403142403Snectar case 'd': 404142403Snectar flags |= ED_DYN; 405142403Snectar break; 406142403Snectar case 'e': 407142403Snectar flags |= ED_EHDR; 408142403Snectar break; 409142403Snectar case 'i': 410142403Snectar flags |= ED_INTERP; 411142403Snectar break; 41257416Smarkm case 'G': 413142403Snectar flags |= ED_GOT; 414142403Snectar break; 415142403Snectar case 'h': 416142403Snectar flags |= ED_HASH; 417142403Snectar break; 418142403Snectar case 'n': 419142403Snectar flags |= ED_NOTE; 420233294Sstas break; 421142403Snectar case 'p': 42290926Snectar flags |= ED_PHDR; 42390926Snectar break; 42457416Smarkm case 'r': 42590926Snectar flags |= ED_REL; 42690926Snectar break; 42757416Smarkm case 's': 42857416Smarkm flags |= ED_SYMTAB; 42957416Smarkm break; 43057416Smarkm case 'w': 43157416Smarkm if ((out = fopen(optarg, "w")) == NULL) 43257416Smarkm err(1, "%s", optarg); 43357416Smarkm break; 43490926Snectar case '?': 435233294Sstas default: 436178825Sdfr usage(); 437178825Sdfr } 438178825Sdfr ac -= optind; 439178825Sdfr av += optind; 440178825Sdfr if (ac == 0 || flags == 0) 441178825Sdfr usage(); 44257416Smarkm if ((fd = open(*av, O_RDONLY)) < 0 || 44357416Smarkm fstat(fd, &sb) < 0) 44457416Smarkm err(1, NULL); 44557416Smarkm e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 44657416Smarkm if (e == MAP_FAILED) 44757416Smarkm err(1, NULL); 44857416Smarkm if (!IS_ELF(*(Elf32_Ehdr *)e)) 44957416Smarkm errx(1, "not an elf file"); 45057416Smarkm phoff = elf_get_off(e, e, E_PHOFF); 45157416Smarkm shoff = elf_get_off(e, e, E_SHOFF); 452233294Sstas phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 453178825Sdfr phnum = elf_get_quarter(e, e, E_PHNUM); 45457416Smarkm shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 45557416Smarkm shnum = elf_get_quarter(e, e, E_SHNUM); 45657416Smarkm shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 45757416Smarkm p = (char *)e + phoff; 45857416Smarkm sh = (char *)e + shoff; 459178825Sdfr offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, SH_OFFSET); 460233294Sstas shstrtab = (char *)e + offset; 461178825Sdfr for (i = 0; (u_int64_t)i < shnum; i++) { 462178825Sdfr name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME); 463178825Sdfr offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET); 464178825Sdfr if (strcmp(shstrtab + name, ".strtab") == 0) 465178825Sdfr strtab = (char *)e + offset; 466178825Sdfr if (strcmp(shstrtab + name, ".dynstr") == 0) 46757416Smarkm dynstr = (char *)e + offset; 46878527Sassar } 46978527Sassar if (flags & ED_EHDR) 47078527Sassar elf_print_ehdr(e); 47178527Sassar if (flags & ED_PHDR) 47278527Sassar elf_print_phdr(e, p); 47378527Sassar if (flags & ED_SHDR) 47478527Sassar elf_print_shdr(e, sh); 47578527Sassar for (i = 0; (u_int64_t)i < phnum; i++) { 47657416Smarkm v = (char *)p + i * phentsize; 47778527Sassar type = elf_get_word(e, v, P_TYPE); 47857416Smarkm switch (type) { 47957416Smarkm case PT_INTERP: 48057416Smarkm if (flags & ED_INTERP) 48157416Smarkm elf_print_interp(e, v); 48257416Smarkm break; 48357416Smarkm case PT_NULL: 48457416Smarkm case PT_LOAD: 48557416Smarkm case PT_DYNAMIC: 486233294Sstas case PT_NOTE: 487178825Sdfr case PT_SHLIB: 48857416Smarkm case PT_PHDR: 48957416Smarkm break; 49057416Smarkm } 491233294Sstas } 49257416Smarkm for (i = 0; (u_int64_t)i < shnum; i++) { 493127808Snectar v = (char *)sh + i * shentsize; 494127808Snectar type = elf_get_word(e, v, SH_TYPE); 495233294Sstas switch (type) { 496127808Snectar case SHT_SYMTAB: 49757416Smarkm if (flags & ED_SYMTAB) 49872445Sassar elf_print_symtab(e, v, strtab); 499102644Snectar break; 50072445Sassar case SHT_DYNAMIC: 50172445Sassar if (flags & ED_DYN) 50272445Sassar elf_print_dynamic(e, v); 503233294Sstas break; 504233294Sstas case SHT_RELA: 505102644Snectar if (flags & ED_REL) 506142403Snectar elf_print_rela(e, v); 50757416Smarkm break; 50872445Sassar case SHT_REL: 50972445Sassar if (flags & ED_REL) 510233294Sstas elf_print_rel(e, v); 51157416Smarkm break; 512178825Sdfr case SHT_NOTE: 513127808Snectar name = elf_get_word(e, v, SH_NAME); 514178825Sdfr if (flags & ED_NOTE && 515127808Snectar strcmp(shstrtab + name, ".note.ABI-tag") == 0) 516127808Snectar elf_print_note(e, v); 517178825Sdfr break; 518127808Snectar case SHT_DYNSYM: 51957416Smarkm if (flags & ED_SYMTAB) 52090926Snectar elf_print_symtab(e, v, dynstr); 521178825Sdfr break; 522233294Sstas case SHT_PROGBITS: 52390926Snectar name = elf_get_word(e, v, SH_NAME); 52457416Smarkm if (flags & ED_GOT && 525102644Snectar strcmp(shstrtab + name, ".got") == 0) 52672445Sassar elf_print_got(e, v); 52772445Sassar break; 52872445Sassar case SHT_HASH: 529233294Sstas if (flags & ED_HASH) 530233294Sstas elf_print_hash(e, v); 531233294Sstas break; 532233294Sstas case SHT_NULL: 533178825Sdfr case SHT_STRTAB: 534233294Sstas case SHT_NOBITS: 535233294Sstas case SHT_SHLIB: 536233294Sstas break; 537233294Sstas } 538233294Sstas } 539233294Sstas 540233294Sstas return 0; 541178825Sdfr} 542127808Snectar 543127808Snectarvoid 544127808Snectarelf_print_ehdr(Elf32_Ehdr *e) 545127808Snectar{ 546127808Snectar u_int64_t class; 547127808Snectar u_int64_t data; 548127808Snectar u_int64_t osabi; 549233294Sstas u_int64_t type; 550233294Sstas u_int64_t machine; 551233294Sstas u_int64_t version; 552127808Snectar u_int64_t entry; 553233294Sstas u_int64_t phoff; 554127808Snectar u_int64_t shoff; 55578527Sassar u_int64_t flags; 556102644Snectar u_int64_t ehsize; 557233294Sstas u_int64_t phentsize; 558233294Sstas u_int64_t phnum; 55978527Sassar u_int64_t shentsize; 56057416Smarkm u_int64_t shnum; 561127808Snectar u_int64_t shstrndx; 56257416Smarkm 56357416Smarkm class = elf_get_byte(e, e, E_CLASS); 564178825Sdfr data = elf_get_byte(e, e, E_DATA); 565178825Sdfr osabi = elf_get_byte(e, e, E_OSABI); 566178825Sdfr type = elf_get_quarter(e, e, E_TYPE); 567178825Sdfr machine = elf_get_quarter(e, e, E_MACHINE); 568178825Sdfr version = elf_get_word(e, e, E_VERSION); 569178825Sdfr entry = elf_get_addr(e, e, E_ENTRY); 570178825Sdfr phoff = elf_get_off(e, e, E_PHOFF); 571178825Sdfr shoff = elf_get_off(e, e, E_SHOFF); 572178825Sdfr flags = elf_get_word(e, e, E_FLAGS); 573178825Sdfr ehsize = elf_get_quarter(e, e, E_EHSIZE); 574178825Sdfr phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 575178825Sdfr phnum = elf_get_quarter(e, e, E_PHNUM); 576102644Snectar shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 57757416Smarkm shnum = elf_get_quarter(e, e, E_SHNUM); 578178825Sdfr shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 579233294Sstas fprintf(out, "\nelf header:\n"); 580233294Sstas fprintf(out, "\n"); 581233294Sstas fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data], 582102644Snectar ei_abis[osabi]); 583233294Sstas fprintf(out, "\te_type: %s\n", e_types[type]); 584233294Sstas fprintf(out, "\te_machine: %s\n", e_machines(machine)); 585102644Snectar fprintf(out, "\te_version: %s\n", ei_versions[version]); 586233294Sstas fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry); 58757416Smarkm fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff); 588233294Sstas fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff); 589233294Sstas fprintf(out, "\te_flags: %jd\n", (intmax_t)flags); 59072445Sassar fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize); 59157416Smarkm fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize); 59257416Smarkm fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum); 593233294Sstas fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize); 59457416Smarkm fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum); 595142403Snectar fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx); 596178825Sdfr} 59757416Smarkm 598233294Sstasvoid 599233294Sstaself_print_phdr(Elf32_Ehdr *e, void *p) 600233294Sstas{ 601233294Sstas u_int64_t phentsize; 602233294Sstas u_int64_t phnum; 603233294Sstas u_int64_t type; 604233294Sstas u_int64_t offset; 605233294Sstas u_int64_t vaddr; 606233294Sstas u_int64_t paddr; 607233294Sstas u_int64_t filesz; 608233294Sstas u_int64_t memsz; 609233294Sstas u_int64_t flags; 610233294Sstas u_int64_t align; 61190926Snectar void *v; 612233294Sstas int i; 613233294Sstas 614178825Sdfr phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 615178825Sdfr phnum = elf_get_quarter(e, e, E_PHNUM); 616233294Sstas fprintf(out, "\nprogram header:\n"); 61790926Snectar for (i = 0; (u_int64_t)i < phnum; i++) { 61857416Smarkm v = (char *)p + i * phentsize; 61957416Smarkm type = elf_get_word(e, v, P_TYPE); 62057416Smarkm offset = elf_get_off(e, v, P_OFFSET); 62190926Snectar vaddr = elf_get_addr(e, v, P_VADDR); 622127808Snectar paddr = elf_get_addr(e, v, P_PADDR); 62390926Snectar filesz = elf_get_size(e, v, P_FILESZ); 62457416Smarkm memsz = elf_get_size(e, v, P_MEMSZ); 62557416Smarkm flags = elf_get_word(e, v, P_FLAGS); 62657416Smarkm align = elf_get_size(e, v, P_ALIGN); 62790926Snectar fprintf(out, "\n"); 62890926Snectar fprintf(out, "entry: %d\n", i); 62990926Snectar fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]); 63090926Snectar fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset); 63157416Smarkm fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr); 63257416Smarkm fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr); 63390926Snectar fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz); 63457416Smarkm fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz); 63557416Smarkm fprintf(out, "\tp_flags: %s\n", p_flags[flags]); 63657416Smarkm fprintf(out, "\tp_align: %jd\n", (intmax_t)align); 63790926Snectar } 63890926Snectar} 63957416Smarkm 64090926Snectarvoid 641127808Snectarelf_print_shdr(Elf32_Ehdr *e, void *sh) 64290926Snectar{ 64390926Snectar u_int64_t shentsize; 64457416Smarkm u_int64_t shnum; 64557416Smarkm u_int64_t name; 64657416Smarkm u_int64_t type; 64757416Smarkm u_int64_t flags; 64857416Smarkm u_int64_t addr; 649178825Sdfr u_int64_t offset; 650233294Sstas u_int64_t size; 65157416Smarkm u_int64_t shlink; 65257416Smarkm u_int64_t info; 65390926Snectar u_int64_t addralign; 65490926Snectar u_int64_t entsize; 65590926Snectar void *v; 65657416Smarkm int i; 65790926Snectar 65857416Smarkm shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 65990926Snectar shnum = elf_get_quarter(e, e, E_SHNUM); 660127808Snectar fprintf(out, "\nsection header:\n"); 661178825Sdfr for (i = 0; (u_int64_t)i < shnum; i++) { 66257416Smarkm v = (char *)sh + i * shentsize; 66390926Snectar name = elf_get_word(e, v, SH_NAME); 66457416Smarkm type = elf_get_word(e, v, SH_TYPE); 66590926Snectar flags = elf_get_word(e, v, SH_FLAGS); 66657416Smarkm addr = elf_get_addr(e, v, SH_ADDR); 667142403Snectar offset = elf_get_off(e, v, SH_OFFSET); 668142403Snectar size = elf_get_size(e, v, SH_SIZE); 669233294Sstas shlink = elf_get_word(e, v, SH_LINK); 670233294Sstas info = elf_get_word(e, v, SH_INFO); 67190926Snectar addralign = elf_get_size(e, v, SH_ADDRALIGN); 67257416Smarkm entsize = elf_get_size(e, v, SH_ENTSIZE); 67390926Snectar fprintf(out, "\n"); 67490926Snectar fprintf(out, "entry: %d\n", i); 675120945Snectar fprintf(out, "\tsh_name: %s\n", shstrtab + name); 676120945Snectar fprintf(out, "\tsh_type: %s\n", sh_types(type)); 677120945Snectar fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]); 678178825Sdfr fprintf(out, "\tsh_addr: %#jx\n", addr); 679178825Sdfr fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset); 680233294Sstas fprintf(out, "\tsh_size: %jd\n", (intmax_t)size); 681233294Sstas fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink); 68290926Snectar fprintf(out, "\tsh_info: %jd\n", (intmax_t)info); 68390926Snectar fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign); 68490926Snectar fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize); 685178825Sdfr } 686178825Sdfr} 687233294Sstas 688233294Sstasvoid 68990926Snectarelf_print_symtab(Elf32_Ehdr *e, void *sh, char *str) 69090926Snectar{ 691233294Sstas u_int64_t offset; 692233294Sstas u_int64_t entsize; 69390926Snectar u_int64_t size; 69490926Snectar u_int64_t name; 695178825Sdfr u_int64_t value; 696178825Sdfr u_int64_t info; 697233294Sstas u_int64_t shndx; 698233294Sstas void *st; 699178825Sdfr int len; 700178825Sdfr int i; 701233294Sstas 702233294Sstas offset = elf_get_off(e, sh, SH_OFFSET); 70390926Snectar entsize = elf_get_size(e, sh, SH_ENTSIZE); 70490926Snectar size = elf_get_size(e, sh, SH_SIZE); 70557416Smarkm name = elf_get_word(e, sh, SH_NAME); 706127808Snectar len = size / entsize; 70790926Snectar fprintf(out, "\nsymbol table (%s):\n", shstrtab + name); 70857416Smarkm for (i = 0; i < len; i++) { 70990926Snectar st = (char *)e + offset + i * entsize; 71057416Smarkm name = elf_get_word(e, st, ST_NAME); 71190926Snectar value = elf_get_addr(e, st, ST_VALUE); 71290926Snectar size = elf_get_size(e, st, ST_SIZE); 713127808Snectar info = elf_get_byte(e, st, ST_INFO); 714127808Snectar shndx = elf_get_quarter(e, st, ST_SHNDX); 715127808Snectar fprintf(out, "\n"); 716127808Snectar fprintf(out, "entry: %d\n", i); 717127808Snectar fprintf(out, "\tst_name: %s\n", str + name); 718127808Snectar fprintf(out, "\tst_value: %#jx\n", value); 719127808Snectar fprintf(out, "\tst_size: %jd\n", (intmax_t)size); 720127808Snectar fprintf(out, "\tst_info: %s %s\n", 721178825Sdfr st_types[ELF32_ST_TYPE(info)], 722178825Sdfr st_bindings[ELF32_ST_BIND(info)]); 723178825Sdfr fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx); 724233294Sstas } 725233294Sstas} 726233294Sstas 72790926Snectarvoid 728178825Sdfrelf_print_dynamic(Elf32_Ehdr *e, void *sh) 729178825Sdfr{ 730178825Sdfr u_int64_t offset; 731178825Sdfr u_int64_t entsize; 732178825Sdfr u_int64_t size; 733178825Sdfr int64_t tag; 734178825Sdfr u_int64_t ptr; 735178825Sdfr u_int64_t val; 736178825Sdfr void *d; 737178825Sdfr int i; 738178825Sdfr 739178825Sdfr offset = elf_get_off(e, sh, SH_OFFSET); 740178825Sdfr entsize = elf_get_size(e, sh, SH_ENTSIZE); 741178825Sdfr size = elf_get_size(e, sh, SH_SIZE); 74290926Snectar fprintf(out, "\ndynamic:\n"); 74390926Snectar for (i = 0; (u_int64_t)i < size / entsize; i++) { 74457416Smarkm d = (char *)e + offset + i * entsize; 74557416Smarkm tag = elf_get_size(e, d, D_TAG); 74657416Smarkm ptr = elf_get_size(e, d, D_PTR); 74757416Smarkm val = elf_get_addr(e, d, D_VAL); 74857416Smarkm fprintf(out, "\n"); 74972445Sassar fprintf(out, "entry: %d\n", i); 75072445Sassar fprintf(out, "\td_tag: %s\n", d_tags(tag)); 75172445Sassar switch (tag) { 75272445Sassar case DT_NEEDED: 75357416Smarkm case DT_SONAME: 75457416Smarkm case DT_RPATH: 75557416Smarkm fprintf(out, "\td_val: %s\n", dynstr + val); 756178825Sdfr break; 757178825Sdfr case DT_PLTRELSZ: 75857416Smarkm case DT_RELA: 75957416Smarkm case DT_RELASZ: 76057416Smarkm case DT_RELAENT: 76157416Smarkm case DT_STRSZ: 76257416Smarkm case DT_SYMENT: 76357416Smarkm case DT_RELSZ: 76472445Sassar case DT_RELENT: 76572445Sassar case DT_PLTREL: 76657416Smarkm fprintf(out, "\td_val: %jd\n", (intmax_t)val); 767178825Sdfr break; 768178825Sdfr case DT_PLTGOT: 769178825Sdfr case DT_HASH: 770178825Sdfr case DT_STRTAB: 771178825Sdfr case DT_SYMTAB: 772178825Sdfr case DT_INIT: 773178825Sdfr case DT_FINI: 774178825Sdfr case DT_REL: 775178825Sdfr case DT_JMPREL: 776178825Sdfr fprintf(out, "\td_ptr: %#jx\n", ptr); 777178825Sdfr break; 77857416Smarkm case DT_NULL: 77957416Smarkm case DT_SYMBOLIC: 78057416Smarkm case DT_DEBUG: 781102644Snectar case DT_TEXTREL: 782102644Snectar break; 783178825Sdfr } 784178825Sdfr } 785102644Snectar} 786102644Snectar 787102644Snectarvoid 788102644Snectarelf_print_rela(Elf32_Ehdr *e, void *sh) 789102644Snectar{ 790102644Snectar u_int64_t offset; 791178825Sdfr u_int64_t entsize; 792102644Snectar u_int64_t size; 793102644Snectar u_int64_t name; 794102644Snectar u_int64_t info; 795102644Snectar int64_t addend; 796102644Snectar void *ra; 797102644Snectar void *v; 798102644Snectar int i; 799102644Snectar 800102644Snectar offset = elf_get_off(e, sh, SH_OFFSET); 801102644Snectar entsize = elf_get_size(e, sh, SH_ENTSIZE); 802102644Snectar size = elf_get_size(e, sh, SH_SIZE); 803102644Snectar name = elf_get_word(e, sh, SH_NAME); 804102644Snectar v = (char *)e + offset; 805102644Snectar fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name); 806102644Snectar for (i = 0; (u_int64_t)i < size / entsize; i++) { 807178825Sdfr ra = (char *)v + i * entsize; 808102644Snectar offset = elf_get_addr(e, ra, RA_OFFSET); 809102644Snectar info = elf_get_word(e, ra, RA_INFO); 810102644Snectar addend = elf_get_off(e, ra, RA_ADDEND); 811102644Snectar fprintf(out, "\n"); 812233294Sstas fprintf(out, "entry: %d\n", i); 813233294Sstas fprintf(out, "\tr_offset: %#jx\n", offset); 814233294Sstas fprintf(out, "\tr_info: %jd\n", (intmax_t)info); 81557416Smarkm fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend); 81657416Smarkm } 81757416Smarkm} 81857416Smarkm 81957416Smarkmvoid 82057416Smarkmelf_print_rel(Elf32_Ehdr *e, void *sh) 82157416Smarkm{ 82257416Smarkm u_int64_t offset; 82357416Smarkm u_int64_t entsize; 82457416Smarkm u_int64_t size; 82557416Smarkm u_int64_t name; 82657416Smarkm u_int64_t info; 82757416Smarkm void *r; 82857416Smarkm void *v; 82957416Smarkm int i; 83057416Smarkm 83157416Smarkm offset = elf_get_off(e, sh, SH_OFFSET); 83257416Smarkm entsize = elf_get_size(e, sh, SH_ENTSIZE); 83357416Smarkm size = elf_get_size(e, sh, SH_SIZE); 83457416Smarkm name = elf_get_word(e, sh, SH_NAME); 83557416Smarkm v = (char *)e + offset; 83657416Smarkm fprintf(out, "\nrelocation (%s):\n", shstrtab + name); 83757416Smarkm for (i = 0; (u_int64_t)i < size / entsize; i++) { 83857416Smarkm r = (char *)v + i * entsize; 83957416Smarkm offset = elf_get_addr(e, r, R_OFFSET); 84057416Smarkm info = elf_get_word(e, r, R_INFO); 84157416Smarkm fprintf(out, "\n"); 84257416Smarkm fprintf(out, "entry: %d\n", i); 84357416Smarkm fprintf(out, "\tr_offset: %#jx\n", offset); 84457416Smarkm fprintf(out, "\tr_info: %jd\n", (intmax_t)info); 84557416Smarkm } 84657416Smarkm} 84757416Smarkm 84857416Smarkmvoid 84957416Smarkmelf_print_interp(Elf32_Ehdr *e, void *p) 85057416Smarkm{ 85157416Smarkm u_int64_t offset; 85257416Smarkm char *s; 85357416Smarkm 85457416Smarkm offset = elf_get_off(e, p, P_OFFSET); 85557416Smarkm s = (char *)e + offset; 85657416Smarkm fprintf(out, "\ninterp:\n"); 85757416Smarkm fprintf(out, "\t%s\n", s); 85857416Smarkm} 85957416Smarkm 86057416Smarkmvoid 86157416Smarkmelf_print_got(Elf32_Ehdr *e, void *sh) 86257416Smarkm{ 86357416Smarkm u_int64_t offset; 86457416Smarkm u_int64_t addralign; 86557416Smarkm u_int64_t size; 86657416Smarkm u_int64_t addr; 86757416Smarkm void *v; 86857416Smarkm int i; 86957416Smarkm 87057416Smarkm offset = elf_get_off(e, sh, SH_OFFSET); 87157416Smarkm addralign = elf_get_size(e, sh, SH_ADDRALIGN); 87257416Smarkm size = elf_get_size(e, sh, SH_SIZE); 87357416Smarkm v = (char *)e + offset; 87457416Smarkm fprintf(out, "\nglobal offset table:\n"); 87557416Smarkm for (i = 0; (u_int64_t)i < size / addralign; i++) { 87657416Smarkm addr = elf_get_addr(e, (char *)v + i * addralign, 0); 87757416Smarkm fprintf(out, "\n"); 87857416Smarkm fprintf(out, "entry: %d\n", i); 87972445Sassar fprintf(out, "\t%#jx\n", addr); 880178825Sdfr } 88157416Smarkm} 882178825Sdfr 883178825Sdfrvoid 884178825Sdfrelf_print_hash(Elf32_Ehdr *e __unused, void *sh __unused) 885120945Snectar{ 886178825Sdfr} 88757416Smarkm 88857416Smarkmvoid 88957416Smarkmelf_print_note(Elf32_Ehdr *e, void *sh) 89057416Smarkm{ 89157416Smarkm u_int64_t offset; 89257416Smarkm u_int64_t size; 893178825Sdfr u_int64_t name; 894178825Sdfr u_int32_t namesz; 895178825Sdfr u_int32_t descsz; 896178825Sdfr u_int32_t type; 897178825Sdfr u_int32_t desc; 898178825Sdfr char *n, *s; 899178825Sdfr 900233294Sstas offset = elf_get_off(e, sh, SH_OFFSET); 901178825Sdfr size = elf_get_size(e, sh, SH_SIZE); 902178825Sdfr name = elf_get_word(e, sh, SH_NAME); 903178825Sdfr n = (char *)e + offset; 904178825Sdfr fprintf(out, "\nnote (%s):\n", shstrtab + name); 905178825Sdfr while (n < ((char *)e + offset + size)) { 906178825Sdfr namesz = elf_get_word(e, n, N_NAMESZ); 907178825Sdfr descsz = elf_get_word(e, n, N_DESCSZ); 908178825Sdfr type = elf_get_word(e, n, N_TYPE); 909178825Sdfr s = n + sizeof(Elf_Note); 910178825Sdfr desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0); 911178825Sdfr fprintf(out, "\t%s %d\n", s, desc); 912178825Sdfr n += sizeof(Elf_Note) + namesz + descsz; 913178825Sdfr } 91457416Smarkm} 91557416Smarkm 91657416Smarkmu_int64_t 917233294Sstaself_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member) 91857416Smarkm{ 91957416Smarkm u_int64_t val; 92057416Smarkm u_char *p; 921 922 val = 0; 923 switch (e->e_ident[EI_CLASS]) { 924 case ELFCLASS32: 925 p = (char *)base + elf32_offsets[member]; 926 val = *p; 927 break; 928 case ELFCLASS64: 929 p = (char *)base + elf64_offsets[member]; 930 val = *p; 931 break; 932 case ELFCLASSNONE: 933 errx(1, "invalid class"); 934 } 935 936 return val; 937} 938 939u_int64_t 940elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member) 941{ 942 u_int64_t val; 943 u_char *p; 944 945 val = 0; 946 switch (e->e_ident[EI_CLASS]) { 947 case ELFCLASS32: 948 p = (char *)base + elf32_offsets[member]; 949 switch (e->e_ident[EI_DATA]) { 950 case ELFDATA2MSB: 951 val = p[0] << 8 | p[1]; 952 break; 953 case ELFDATA2LSB: 954 val = p[1] << 8 | p[0]; 955 break; 956 case ELFDATANONE: 957 errx(1, "invalid data format"); 958 } 959 break; 960 case ELFCLASS64: 961 p = (char *)base + elf64_offsets[member]; 962 switch (e->e_ident[EI_DATA]) { 963 case ELFDATA2MSB: 964 val = p[0] << 8 | p[1]; 965 break; 966 case ELFDATA2LSB: 967 val = p[1] << 8 | p[0]; 968 break; 969 case ELFDATANONE: 970 errx(1, "invalid data format"); 971 } 972 break; 973 case ELFCLASSNONE: 974 errx(1, "invalid class"); 975 } 976 977 return val; 978} 979 980u_int64_t 981elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member) 982{ 983 u_int64_t val; 984 u_char *p; 985 986 val = 0; 987 switch (e->e_ident[EI_CLASS]) { 988 case ELFCLASS32: 989 p = (char *)base + elf32_offsets[member]; 990 switch (e->e_ident[EI_DATA]) { 991 case ELFDATA2MSB: 992 val = p[0] << 8 | p[1]; 993 break; 994 case ELFDATA2LSB: 995 val = p[1] << 8 | p[0]; 996 break; 997 case ELFDATANONE: 998 errx(1, "invalid data format"); 999 } 1000 break; 1001 case ELFCLASS64: 1002 p = (char *)base + elf64_offsets[member]; 1003 switch (e->e_ident[EI_DATA]) { 1004 case ELFDATA2MSB: 1005 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1006 break; 1007 case ELFDATA2LSB: 1008 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1009 break; 1010 case ELFDATANONE: 1011 errx(1, "invalid data format"); 1012 } 1013 break; 1014 case ELFCLASSNONE: 1015 errx(1, "invalid class"); 1016 } 1017 1018 return val; 1019} 1020 1021u_int64_t 1022elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member) 1023{ 1024 u_int64_t val; 1025 u_char *p; 1026 1027 val = 0; 1028 switch (e->e_ident[EI_CLASS]) { 1029 case ELFCLASS32: 1030 p = (char *)base + elf32_offsets[member]; 1031 switch (e->e_ident[EI_DATA]) { 1032 case ELFDATA2MSB: 1033 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1034 break; 1035 case ELFDATA2LSB: 1036 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1037 break; 1038 case ELFDATANONE: 1039 errx(1, "invalid data format"); 1040 } 1041 break; 1042 case ELFCLASS64: 1043 p = (char *)base + elf64_offsets[member]; 1044 switch (e->e_ident[EI_DATA]) { 1045 case ELFDATA2MSB: 1046 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1047 break; 1048 case ELFDATA2LSB: 1049 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1050 break; 1051 case ELFDATANONE: 1052 errx(1, "invalid data format"); 1053 } 1054 break; 1055 case ELFCLASSNONE: 1056 errx(1, "invalid class"); 1057 } 1058 1059 return val; 1060} 1061 1062u_int64_t 1063elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member) 1064{ 1065 u_int64_t high; 1066 u_int64_t low; 1067 u_int64_t val; 1068 u_char *p; 1069 1070 val = 0; 1071 switch (e->e_ident[EI_CLASS]) { 1072 case ELFCLASS32: 1073 p = (char *)base + elf32_offsets[member]; 1074 switch (e->e_ident[EI_DATA]) { 1075 case ELFDATA2MSB: 1076 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1077 break; 1078 case ELFDATA2LSB: 1079 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1080 break; 1081 case ELFDATANONE: 1082 errx(1, "invalid data format"); 1083 } 1084 break; 1085 case ELFCLASS64: 1086 p = (char *)base + elf64_offsets[member]; 1087 switch (e->e_ident[EI_DATA]) { 1088 case ELFDATA2MSB: 1089 high = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1090 low = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; 1091 val = high << 32 | low; 1092 break; 1093 case ELFDATA2LSB: 1094 high = p[7] << 24 | p[6] << 16 | p[5] << 8 | p[4]; 1095 low = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1096 val = high << 32 | low; 1097 break; 1098 case ELFDATANONE: 1099 errx(1, "invalid data format"); 1100 } 1101 break; 1102 case ELFCLASSNONE: 1103 errx(1, "invalid class"); 1104 } 1105 1106 return val; 1107} 1108 1109void 1110usage(void) 1111{ 1112 fprintf(stderr, "usage: elfdump [-acdeiGhnprs] [-w file] filename\n"); 1113 exit(1); 1114} 1115