elfdump.c revision 109332
1109313Sobrien/*- 2109313Sobrien * Copyright (c) 2001 Jake Burkholder 3109313Sobrien * All rights reserved. 4109313Sobrien * 5109313Sobrien * Redistribution and use in source and binary forms, with or without 6109313Sobrien * modification, are permitted provided that the following conditions 7109313Sobrien * are met: 8109313Sobrien * 1. Redistributions of source code must retain the above copyright 9109313Sobrien * notice, this list of conditions and the following disclaimer. 10109313Sobrien * 2. Redistributions in binary form must reproduce the above copyright 11109313Sobrien * notice, this list of conditions and the following disclaimer in the 12109313Sobrien * documentation and/or other materials provided with the distribution. 13109313Sobrien * 14109313Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15109313Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16109313Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17109313Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18109313Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19109313Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20109313Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21109313Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22109313Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23109313Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24109313Sobrien * SUCH DAMAGE. 25109313Sobrien */ 26109313Sobrien 27109313Sobrien#include <sys/cdefs.h> 28109313Sobrien__FBSDID("$FreeBSD: head/usr.bin/elfdump/elfdump.c 109332 2003-01-15 21:24:05Z obrien $"); 29109313Sobrien 30109313Sobrien#include <sys/types.h> 31109313Sobrien#include <sys/elf32.h> 32109313Sobrien#include <sys/elf64.h> 33109313Sobrien#include <sys/mman.h> 34109313Sobrien#include <sys/stat.h> 35109313Sobrien#include <err.h> 36109313Sobrien#include <fcntl.h> 37109313Sobrien#include <stddef.h> 38109313Sobrien#include <stdio.h> 39109313Sobrien#include <stdlib.h> 40109313Sobrien#include <string.h> 41109313Sobrien#include <unistd.h> 42109313Sobrien 43109313Sobrien#define ED_DYN (1<<0) 44109313Sobrien#define ED_EHDR (1<<1) 45109313Sobrien#define ED_GOT (1<<2) 46109313Sobrien#define ED_HASH (1<<3) 47109313Sobrien#define ED_INTERP (1<<4) 48109313Sobrien#define ED_NOTE (1<<5) 49109313Sobrien#define ED_PHDR (1<<6) 50109313Sobrien#define ED_REL (1<<7) 51109313Sobrien#define ED_SHDR (1<<8) 52109313Sobrien#define ED_SYMTAB (1<<9) 53109313Sobrien#define ED_ALL ((1<<10)-1) 54109313Sobrien 55109313Sobrien#define elf_get_addr elf_get_quad 56109313Sobrien#define elf_get_off elf_get_quad 57109313Sobrien#define elf_get_size elf_get_quad 58109313Sobrien 59109313Sobrienenum elf_member { 60109313Sobrien D_TAG = 1, D_PTR, D_VAL, 61109313Sobrien 62109313Sobrien E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY, 63109313Sobrien E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE, 64109313Sobrien E_SHNUM, E_SHSTRNDX, 65109313Sobrien 66109313Sobrien N_NAMESZ, N_DESCSZ, N_TYPE, 67109313Sobrien 68109313Sobrien P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS, 69109313Sobrien P_ALIGN, 70109313Sobrien 71109313Sobrien SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK, 72109313Sobrien SH_INFO, SH_ADDRALIGN, SH_ENTSIZE, 73109313Sobrien 74109313Sobrien ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX, 75109313Sobrien 76109313Sobrien R_OFFSET, R_INFO, 77109313Sobrien 78109313Sobrien RA_OFFSET, RA_INFO, RA_ADDEND 79109313Sobrien}; 80109313Sobrien 81109313Sobrientypedef enum elf_member elf_member_t; 82109313Sobrien 83109313Sobrienint elf32_offsets[] = { 84109313Sobrien 0, 85109313Sobrien 86109313Sobrien offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr), 87109313Sobrien offsetof(Elf32_Dyn, d_un.d_val), 88109313Sobrien 89109313Sobrien offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 90109313Sobrien offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 91109313Sobrien offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 92109313Sobrien offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine), 93109313Sobrien offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry), 94109313Sobrien offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff), 95109313Sobrien offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize), 96109313Sobrien offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum), 97109313Sobrien offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum), 98109313Sobrien offsetof(Elf32_Ehdr, e_shstrndx), 99109313Sobrien 100109313Sobrien offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 101109313Sobrien offsetof(Elf_Note, n_type), 102109313Sobrien 103109313Sobrien offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset), 104109313Sobrien offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr), 105109313Sobrien offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz), 106109313Sobrien offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align), 107109313Sobrien 108109313Sobrien offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type), 109109313Sobrien offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr), 110109313Sobrien offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size), 111109313Sobrien offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info), 112109313Sobrien offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize), 113109313Sobrien 114109313Sobrien offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value), 115109313Sobrien offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info), 116109313Sobrien offsetof(Elf32_Sym, st_shndx), 117109313Sobrien 118109313Sobrien offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info), 119109313Sobrien 120109313Sobrien offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info), 121109313Sobrien offsetof(Elf32_Rela, r_addend) 122109313Sobrien}; 123109313Sobrien 124109313Sobrienint elf64_offsets[] = { 125109313Sobrien 0, 126109313Sobrien 127109313Sobrien offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr), 128109313Sobrien offsetof(Elf64_Dyn, d_un.d_val), 129109313Sobrien 130109313Sobrien offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 131109313Sobrien offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 132109313Sobrien offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 133109313Sobrien offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine), 134109313Sobrien offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry), 135109313Sobrien offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff), 136109313Sobrien offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize), 137109313Sobrien offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum), 138109313Sobrien offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum), 139109313Sobrien offsetof(Elf64_Ehdr, e_shstrndx), 140109313Sobrien 141109313Sobrien offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 142109313Sobrien offsetof(Elf_Note, n_type), 143109313Sobrien 144109313Sobrien offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset), 145109313Sobrien offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr), 146109313Sobrien offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz), 147109313Sobrien offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align), 148109313Sobrien 149109313Sobrien offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type), 150109313Sobrien offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr), 151109313Sobrien offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size), 152109313Sobrien offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info), 153109313Sobrien offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize), 154109313Sobrien 155109313Sobrien offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value), 156109313Sobrien offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info), 157109313Sobrien offsetof(Elf64_Sym, st_shndx), 158109313Sobrien 159109313Sobrien offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info), 160109313Sobrien 161109313Sobrien offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info), 162109313Sobrien offsetof(Elf64_Rela, r_addend) 163109313Sobrien}; 164109313Sobrien 165109332Sobrien/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 166109332Sobrienconst char * 167109332Sobriend_tags(u_int64_t tag) { 168109332Sobrien switch (tag) { 169109332Sobrien case 0: return "DT_NULL"; 170109332Sobrien case 1: return "DT_NEEDED"; 171109332Sobrien case 2: return "DT_PLTRELSZ"; 172109332Sobrien case 3: return "DT_PLTGOT"; 173109332Sobrien case 4: return "DT_HASH"; 174109332Sobrien case 5: return "DT_STRTAB"; 175109332Sobrien case 6: return "DT_SYMTAB"; 176109332Sobrien case 7: return "DT_RELA"; 177109332Sobrien case 8: return "DT_RELASZ"; 178109332Sobrien case 9: return "DT_RELAENT"; 179109332Sobrien case 10: return "DT_STRSZ"; 180109332Sobrien case 11: return "DT_SYMENT"; 181109332Sobrien case 12: return "DT_INIT"; 182109332Sobrien case 13: return "DT_FINI"; 183109332Sobrien case 14: return "DT_SONAME"; 184109332Sobrien case 15: return "DT_RPATH"; 185109332Sobrien case 16: return "DT_SYMBOLIC"; 186109332Sobrien case 17: return "DT_REL"; 187109332Sobrien case 18: return "DT_RELSZ"; 188109332Sobrien case 19: return "DT_RELENT"; 189109332Sobrien case 20: return "DT_PLTREL"; 190109332Sobrien case 21: return "DT_DEBUG"; 191109332Sobrien case 22: return "DT_TEXTREL"; 192109332Sobrien case 23: return "DT_JMPREL"; 193109332Sobrien case 24: return "DT_BIND_NOW"; 194109332Sobrien case 25: return "DT_INIT_ARRAY"; 195109332Sobrien case 26: return "DT_FINI_ARRAY"; 196109332Sobrien case 27: return "DT_INIT_ARRAYSZ"; 197109332Sobrien case 28: return "DT_FINI_ARRAYSZ"; 198109332Sobrien case 29: return "DT_RUNPATH"; 199109332Sobrien case 30: return "DT_FLAGS"; 200109332Sobrien case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ 201109332Sobrien case 33: return "DT_PREINIT_ARRAYSZ"; 202109332Sobrien /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 203109332Sobrien case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 204109332Sobrien case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 205109332Sobrien case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 206109332Sobrien case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 207109332Sobrien case 0x6ffffdf9: return "DT_PLTPADSZ"; 208109332Sobrien case 0x6ffffdfa: return "DT_MOVEENT"; 209109332Sobrien case 0x6ffffdfb: return "DT_MOVESZ"; 210109332Sobrien case 0x6ffffdfc: return "DT_FEATURE"; 211109332Sobrien case 0x6ffffdfd: return "DT_POSFLAG_1"; 212109332Sobrien case 0x6ffffdfe: return "DT_SYMINSZ"; 213109332Sobrien case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; 214109332Sobrien case 0x6ffffe00: return "DT_ADDRRNGLO"; 215109332Sobrien case 0x6ffffef8: return "DT_GNU_CONFLICT"; 216109332Sobrien case 0x6ffffef9: return "DT_GNU_LIBLIST"; 217109332Sobrien case 0x6ffffefa: return "DT_SUNW_CONFIG"; 218109332Sobrien case 0x6ffffefb: return "DT_SUNW_DEPAUDIT"; 219109332Sobrien case 0x6ffffefc: return "DT_SUNW_AUDIT"; 220109332Sobrien case 0x6ffffefd: return "DT_SUNW_PLTPAD"; 221109332Sobrien case 0x6ffffefe: return "DT_SUNW_MOVETAB"; 222109332Sobrien case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; 223109332Sobrien case 0x6ffffff9: return "DT_RELACOUNT"; 224109332Sobrien case 0x6ffffffa: return "DT_RELCOUNT"; 225109332Sobrien case 0x6ffffffb: return "DT_FLAGS_1"; 226109332Sobrien case 0x6ffffffc: return "DT_VERDEF"; 227109332Sobrien case 0x6ffffffd: return "DT_VERDEFNUM"; 228109332Sobrien case 0x6ffffffe: return "DT_VERNEED"; 229109332Sobrien case 0x6fffffff: return "DT_VERNEEDNUM"; 230109332Sobrien case 0x6ffffff0: return "DT_GNU_VERSYM"; 231109332Sobrien /* 0x70000000 - 0x7fffffff processor-specific semantics */ 232109332Sobrien case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; 233109332Sobrien case 0x7ffffffe: return "DT_SUNW_USED"; 234109332Sobrien case 0x7fffffff: return "DT_SUNW_FILTER"; 235109332Sobrien default: return "ERROR: TAG NOT DEFINED"; 236109332Sobrien } 237109313Sobrien}; 238109313Sobrien 239109313Sobrienchar *e_machines[] = { 240109313Sobrien "EM_NONE", "EM_M32", "EM_SPARC", "EM_386", "EM_68K", "EM_88K", 241109313Sobrien "EM_486", "EM_860", "EM_MIPS" 242109313Sobrien}; 243109313Sobrien 244109313Sobrienchar *e_types[] = { 245109313Sobrien "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 246109313Sobrien}; 247109313Sobrien 248109313Sobrienchar *ei_versions[] = { 249109313Sobrien "EV_NONE", "EV_CURRENT" 250109313Sobrien}; 251109313Sobrien 252109313Sobrienchar *ei_classes[] = { 253109313Sobrien "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 254109313Sobrien}; 255109313Sobrien 256109313Sobrienchar *ei_data[] = { 257109313Sobrien "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 258109313Sobrien}; 259109313Sobrien 260109313Sobrienchar *ei_abis[] = { 261109313Sobrien "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 262109313Sobrien "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", 263109313Sobrien "ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", 264109313Sobrien "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD" 265109313Sobrien}; 266109313Sobrien 267109313Sobrienchar *p_types[] = { 268109313Sobrien "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 269109313Sobrien "PT_SHLIB", "PT_PHDR" 270109313Sobrien}; 271109313Sobrien 272109313Sobrienchar *p_flags[] = { 273109313Sobrien "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 274109313Sobrien "PF_X|PF_W|PF_R" 275109313Sobrien}; 276109313Sobrien 277109329Sobrien/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 278109332Sobrienconst char * 279109332Sobriensh_types(u_int64_t sht) { 280109329Sobrien switch (sht) { 281109329Sobrien case 0: return "SHT_NULL"; 282109329Sobrien case 1: return "SHT_PROGBITS"; 283109329Sobrien case 2: return "SHT_SYMTAB"; 284109329Sobrien case 3: return "SHT_STRTAB"; 285109329Sobrien case 4: return "SHT_RELA"; 286109329Sobrien case 5: return "SHT_HASH"; 287109329Sobrien case 6: return "SHT_DYNAMIC"; 288109329Sobrien case 7: return "SHT_NOTE"; 289109329Sobrien case 8: return "SHT_NOBITS"; 290109329Sobrien case 9: return "SHT_REL"; 291109329Sobrien case 10: return "SHT_SHLIB"; 292109329Sobrien case 11: return "SHT_DYNSYM"; 293109329Sobrien case 14: return "SHT_INIT_ARRAY"; 294109329Sobrien case 15: return "SHT_FINI_ARRAY"; 295109329Sobrien case 16: return "SHT_PREINIT_ARRAY"; 296109329Sobrien case 17: return "SHT_GROUP"; 297109329Sobrien case 18: return "SHT_SYMTAB_SHNDX"; 298109332Sobrien /* 0x60000000 - 0x6fffffff operating system-specific semantics */ 299109329Sobrien case 0x6ffffff0: return "XXX:VERSYM"; 300109329Sobrien case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 301109329Sobrien case 0x6ffffffc: return "XXX:VERDEF"; 302109329Sobrien case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; 303109329Sobrien case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; 304109329Sobrien case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; 305109332Sobrien /* 0x70000000 - 0x7fffffff processor-specific semantics */ 306109329Sobrien case 0x7ffffffd: return "XXX:AUXILIARY"; 307109329Sobrien case 0x7fffffff: return "XXX:FILTER"; 308109332Sobrien /* 0x80000000 - 0xffffffff application programs */ 309109329Sobrien default: return "ERROR: SHT NOT DEFINED"; 310109329Sobrien } 311109313Sobrien}; 312109313Sobrien 313109313Sobrienchar *sh_flags[] = { 314109313Sobrien "", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR", 315109313Sobrien "SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR", 316109313Sobrien "SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR" 317109313Sobrien}; 318109313Sobrien 319109313Sobrienchar *st_types[] = { 320109313Sobrien "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE" 321109313Sobrien}; 322109313Sobrien 323109313Sobrienchar *st_bindings[] = { 324109313Sobrien "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 325109313Sobrien}; 326109313Sobrien 327109313Sobrienchar *dynstr; 328109313Sobrienchar *shstrtab; 329109313Sobrienchar *strtab; 330109313SobrienFILE *out; 331109313Sobrien 332109313Sobrienu_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member); 333109313Sobrienu_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member); 334109313Sobrienu_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member); 335109313Sobrienu_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member); 336109313Sobrienu_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member); 337109313Sobrien 338109313Sobrienvoid elf_print_ehdr(void *e); 339109313Sobrienvoid elf_print_phdr(void *e, void *p); 340109313Sobrienvoid elf_print_shdr(void *e, void *sh); 341109313Sobrienvoid elf_print_symtab(void *e, void *sh, char *str); 342109313Sobrienvoid elf_print_dynamic(void *e, void *sh); 343109313Sobrienvoid elf_print_rel(void *e, void *r); 344109313Sobrienvoid elf_print_rela(void *e, void *ra); 345109313Sobrienvoid elf_print_interp(void *e, void *p); 346109313Sobrienvoid elf_print_got(void *e, void *sh); 347109313Sobrienvoid elf_print_hash(void *e, void *sh); 348109313Sobrienvoid elf_print_note(void *e, void *sh); 349109313Sobrien 350109313Sobrienvoid usage(void); 351109313Sobrien 352109313Sobrienint 353109313Sobrienmain(int ac, char **av) 354109313Sobrien{ 355109313Sobrien u_int64_t phoff; 356109313Sobrien u_int64_t shoff; 357109313Sobrien u_int64_t phentsize; 358109313Sobrien u_int64_t phnum; 359109313Sobrien u_int64_t shentsize; 360109313Sobrien u_int64_t shnum; 361109313Sobrien u_int64_t shstrndx; 362109313Sobrien u_int64_t offset; 363109313Sobrien u_int64_t name; 364109313Sobrien u_int64_t type; 365109313Sobrien struct stat sb; 366109313Sobrien u_int flags; 367109313Sobrien void *e; 368109313Sobrien void *p; 369109313Sobrien void *sh; 370109313Sobrien void *v; 371109313Sobrien int fd; 372109313Sobrien int ch; 373109313Sobrien int i; 374109313Sobrien 375109313Sobrien out = stdout; 376109313Sobrien flags = 0; 377109313Sobrien while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1) 378109313Sobrien switch (ch) { 379109313Sobrien case 'a': 380109313Sobrien flags = ED_ALL; 381109313Sobrien break; 382109313Sobrien case 'c': 383109313Sobrien flags |= ED_SHDR; 384109313Sobrien break; 385109313Sobrien case 'd': 386109313Sobrien flags |= ED_DYN; 387109313Sobrien break; 388109313Sobrien case 'e': 389109313Sobrien flags |= ED_EHDR; 390109313Sobrien break; 391109313Sobrien case 'i': 392109313Sobrien flags |= ED_INTERP; 393109313Sobrien break; 394109313Sobrien case 'G': 395109313Sobrien flags |= ED_GOT; 396109313Sobrien break; 397109313Sobrien case 'h': 398109313Sobrien flags |= ED_HASH; 399109313Sobrien break; 400109313Sobrien case 'n': 401109313Sobrien flags |= ED_NOTE; 402109313Sobrien break; 403109313Sobrien case 'p': 404109313Sobrien flags |= ED_PHDR; 405109313Sobrien break; 406109313Sobrien case 'r': 407109313Sobrien flags |= ED_REL; 408109313Sobrien break; 409109313Sobrien case 's': 410109313Sobrien flags |= ED_SYMTAB; 411109313Sobrien break; 412109313Sobrien case 'w': 413109313Sobrien if ((out = fopen(optarg, "w")) == NULL) 414109313Sobrien err(1, "%s", optarg); 415109313Sobrien break; 416109313Sobrien case '?': 417109313Sobrien default: 418109313Sobrien usage(); 419109313Sobrien } 420109313Sobrien ac -= optind; 421109313Sobrien av += optind; 422109313Sobrien if (ac == 0 || flags == 0) 423109313Sobrien usage(); 424109313Sobrien if ((fd = open(*av, O_RDONLY)) < 0 || 425109313Sobrien fstat(fd, &sb) < 0) 426109313Sobrien err(1, NULL); 427109313Sobrien e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 428109313Sobrien if (e == MAP_FAILED) 429109313Sobrien err(1, NULL); 430109313Sobrien if (!IS_ELF(*(Elf32_Ehdr *)e)) 431109313Sobrien errx(1, "not an elf file"); 432109313Sobrien phoff = elf_get_off(e, e, E_PHOFF); 433109313Sobrien shoff = elf_get_off(e, e, E_SHOFF); 434109313Sobrien phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 435109313Sobrien phnum = elf_get_quarter(e, e, E_PHNUM); 436109313Sobrien shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 437109313Sobrien shnum = elf_get_quarter(e, e, E_SHNUM); 438109313Sobrien shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 439109313Sobrien p = e + phoff; 440109313Sobrien sh = e + shoff; 441109313Sobrien offset = elf_get_off(e, sh + shstrndx * shentsize, SH_OFFSET); 442109313Sobrien shstrtab = e + offset; 443109313Sobrien for (i = 0; i < shnum; i++) { 444109313Sobrien name = elf_get_word(e, sh + i * shentsize, SH_NAME); 445109313Sobrien offset = elf_get_off(e, sh + i * shentsize, SH_OFFSET); 446109313Sobrien if (strcmp(shstrtab + name, ".strtab") == 0) 447109313Sobrien strtab = e + offset; 448109313Sobrien if (strcmp(shstrtab + name, ".dynstr") == 0) 449109313Sobrien dynstr = e + offset; 450109313Sobrien } 451109313Sobrien if (flags & ED_EHDR) 452109313Sobrien elf_print_ehdr(e); 453109313Sobrien if (flags & ED_PHDR) 454109313Sobrien elf_print_phdr(e, p); 455109313Sobrien if (flags & ED_SHDR) 456109313Sobrien elf_print_shdr(e, sh); 457109313Sobrien for (i = 0; i < phnum; i++) { 458109313Sobrien v = p + i * phentsize; 459109313Sobrien type = elf_get_word(e, v, P_TYPE); 460109313Sobrien switch (type) { 461109313Sobrien case PT_INTERP: 462109313Sobrien if (flags & ED_INTERP) 463109313Sobrien elf_print_interp(e, v); 464109313Sobrien break; 465109313Sobrien case PT_NULL: 466109313Sobrien case PT_LOAD: 467109313Sobrien case PT_DYNAMIC: 468109313Sobrien case PT_NOTE: 469109313Sobrien case PT_SHLIB: 470109313Sobrien case PT_PHDR: 471109313Sobrien break; 472109313Sobrien } 473109313Sobrien } 474109313Sobrien for (i = 0; i < shnum; i++) { 475109313Sobrien v = sh + i * shentsize; 476109313Sobrien type = elf_get_word(e, v, SH_TYPE); 477109313Sobrien switch (type) { 478109313Sobrien case SHT_SYMTAB: 479109313Sobrien if (flags & ED_SYMTAB) 480109313Sobrien elf_print_symtab(e, v, strtab); 481109313Sobrien break; 482109313Sobrien case SHT_DYNAMIC: 483109313Sobrien if (flags & ED_DYN) 484109313Sobrien elf_print_dynamic(e, v); 485109313Sobrien break; 486109313Sobrien case SHT_RELA: 487109313Sobrien if (flags & ED_REL) 488109313Sobrien elf_print_rela(e, v); 489109313Sobrien break; 490109313Sobrien case SHT_REL: 491109313Sobrien if (flags & ED_REL) 492109313Sobrien elf_print_rel(e, v); 493109313Sobrien break; 494109313Sobrien case SHT_NOTE: 495109313Sobrien name = elf_get_word(e, v, SH_NAME); 496109313Sobrien if (flags & ED_NOTE && 497109313Sobrien strcmp(shstrtab + name, ".note.ABI-tag") == 0) 498109313Sobrien elf_print_note(e, v); 499109313Sobrien break; 500109313Sobrien case SHT_DYNSYM: 501109313Sobrien if (flags & ED_SYMTAB) 502109313Sobrien elf_print_symtab(e, v, dynstr); 503109313Sobrien break; 504109313Sobrien case SHT_PROGBITS: 505109313Sobrien name = elf_get_word(e, v, SH_NAME); 506109313Sobrien if (flags & ED_GOT && 507109313Sobrien strcmp(shstrtab + name, ".got") == 0) 508109313Sobrien elf_print_got(e, v); 509109313Sobrien break; 510109313Sobrien case SHT_HASH: 511109313Sobrien if (flags & ED_HASH) 512109313Sobrien elf_print_hash(e, v); 513109313Sobrien break; 514109313Sobrien case SHT_NULL: 515109313Sobrien case SHT_STRTAB: 516109313Sobrien case SHT_NOBITS: 517109313Sobrien case SHT_SHLIB: 518109313Sobrien break; 519109313Sobrien } 520109313Sobrien } 521109313Sobrien 522109313Sobrien return 0; 523109313Sobrien} 524109313Sobrien 525109313Sobrienvoid 526109313Sobrienelf_print_ehdr(void *e) 527109313Sobrien{ 528109313Sobrien u_int64_t class; 529109313Sobrien u_int64_t data; 530109313Sobrien u_int64_t osabi; 531109313Sobrien u_int64_t type; 532109313Sobrien u_int64_t machine; 533109313Sobrien u_int64_t version; 534109313Sobrien u_int64_t entry; 535109313Sobrien u_int64_t phoff; 536109313Sobrien u_int64_t shoff; 537109313Sobrien u_int64_t flags; 538109313Sobrien u_int64_t ehsize; 539109313Sobrien u_int64_t phentsize; 540109313Sobrien u_int64_t phnum; 541109313Sobrien u_int64_t shentsize; 542109313Sobrien u_int64_t shnum; 543109313Sobrien u_int64_t shstrndx; 544109313Sobrien 545109313Sobrien class = elf_get_byte(e, e, E_CLASS); 546109313Sobrien data = elf_get_byte(e, e, E_DATA); 547109313Sobrien osabi = elf_get_byte(e, e, E_OSABI); 548109313Sobrien type = elf_get_quarter(e, e, E_TYPE); 549109313Sobrien machine = elf_get_quarter(e, e, E_MACHINE); 550109313Sobrien version = elf_get_word(e, e, E_VERSION); 551109313Sobrien entry = elf_get_addr(e, e, E_ENTRY); 552109313Sobrien phoff = elf_get_off(e, e, E_PHOFF); 553109313Sobrien shoff = elf_get_off(e, e, E_SHOFF); 554109313Sobrien flags = elf_get_word(e, e, E_FLAGS); 555109313Sobrien ehsize = elf_get_quarter(e, e, E_EHSIZE); 556109313Sobrien phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 557109313Sobrien phnum = elf_get_quarter(e, e, E_PHNUM); 558109313Sobrien shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 559109313Sobrien shnum = elf_get_quarter(e, e, E_SHNUM); 560109313Sobrien shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 561109313Sobrien fprintf(out, "\nelf header:\n"); 562109313Sobrien fprintf(out, "\n"); 563109313Sobrien fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data], 564109313Sobrien ei_abis[osabi]); 565109313Sobrien fprintf(out, "\te_type: %s\n", e_types[type]); 566109313Sobrien if (machine < sizeof e_machines / sizeof *e_machines) 567109313Sobrien fprintf(out, "\te_machine: %s\n", e_machines[machine]); 568109313Sobrien else 569109313Sobrien fprintf(out, "\te_machine: %lld\n", machine); 570109313Sobrien fprintf(out, "\te_version: %s\n", ei_versions[version]); 571109313Sobrien fprintf(out, "\te_entry: %#llx\n", entry); 572109313Sobrien fprintf(out, "\te_phoff: %lld\n", phoff); 573109313Sobrien fprintf(out, "\te_shoff: %lld\n", shoff); 574109313Sobrien fprintf(out, "\te_flags: %lld\n", flags); 575109313Sobrien fprintf(out, "\te_ehsize: %lld\n", ehsize); 576109313Sobrien fprintf(out, "\te_phentsize: %lld\n", phentsize); 577109313Sobrien fprintf(out, "\te_phnum: %lld\n", phnum); 578109313Sobrien fprintf(out, "\te_shentsize: %lld\n", shentsize); 579109313Sobrien fprintf(out, "\te_shnum: %lld\n", shnum); 580109313Sobrien fprintf(out, "\te_shstrndx: %lld\n", shstrndx); 581109313Sobrien} 582109313Sobrien 583109313Sobrienvoid 584109313Sobrienelf_print_phdr(void *e, void *p) 585109313Sobrien{ 586109313Sobrien u_int64_t phentsize; 587109313Sobrien u_int64_t phnum; 588109313Sobrien u_int64_t type; 589109313Sobrien u_int64_t offset; 590109313Sobrien u_int64_t vaddr; 591109313Sobrien u_int64_t paddr; 592109313Sobrien u_int64_t filesz; 593109313Sobrien u_int64_t memsz; 594109313Sobrien u_int64_t flags; 595109313Sobrien u_int64_t align; 596109313Sobrien void *v; 597109313Sobrien int i; 598109313Sobrien 599109313Sobrien phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 600109313Sobrien phnum = elf_get_quarter(e, e, E_PHNUM); 601109313Sobrien fprintf(out, "\nprogram header:\n"); 602109313Sobrien for (i = 0; i < phnum; i++) { 603109313Sobrien v = p + i * phentsize; 604109313Sobrien type = elf_get_word(e, v, P_TYPE); 605109313Sobrien offset = elf_get_off(e, v, P_OFFSET); 606109313Sobrien vaddr = elf_get_addr(e, v, P_VADDR); 607109313Sobrien paddr = elf_get_addr(e, v, P_PADDR); 608109313Sobrien filesz = elf_get_size(e, v, P_FILESZ); 609109313Sobrien memsz = elf_get_size(e, v, P_MEMSZ); 610109313Sobrien flags = elf_get_word(e, v, P_FLAGS); 611109313Sobrien align = elf_get_size(e, v, P_ALIGN); 612109313Sobrien fprintf(out, "\n"); 613109313Sobrien fprintf(out, "entry: %d\n", i); 614109313Sobrien fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]); 615109313Sobrien fprintf(out, "\tp_offset: %lld\n", offset); 616109313Sobrien fprintf(out, "\tp_vaddr: %#llx\n", vaddr); 617109313Sobrien fprintf(out, "\tp_paddr: %#llx\n", paddr); 618109313Sobrien fprintf(out, "\tp_filesz: %lld\n", filesz); 619109313Sobrien fprintf(out, "\tp_memsz: %lld\n", memsz); 620109313Sobrien fprintf(out, "\tp_flags: %s\n", p_flags[flags]); 621109313Sobrien fprintf(out, "\tp_align: %lld\n", align); 622109313Sobrien } 623109313Sobrien} 624109313Sobrien 625109313Sobrienvoid 626109313Sobrienelf_print_shdr(void *e, void *sh) 627109313Sobrien{ 628109313Sobrien u_int64_t shentsize; 629109313Sobrien u_int64_t shnum; 630109313Sobrien u_int64_t name; 631109313Sobrien u_int64_t type; 632109313Sobrien u_int64_t flags; 633109313Sobrien u_int64_t addr; 634109313Sobrien u_int64_t offset; 635109313Sobrien u_int64_t size; 636109313Sobrien u_int64_t link; 637109313Sobrien u_int64_t info; 638109313Sobrien u_int64_t addralign; 639109313Sobrien u_int64_t entsize; 640109313Sobrien void *v; 641109313Sobrien int i; 642109313Sobrien 643109313Sobrien shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 644109313Sobrien shnum = elf_get_quarter(e, e, E_SHNUM); 645109313Sobrien fprintf(out, "\nsection header:\n"); 646109313Sobrien for (i = 0; i < shnum; i++) { 647109313Sobrien v = sh + i * shentsize; 648109313Sobrien name = elf_get_word(e, v, SH_NAME); 649109313Sobrien type = elf_get_word(e, v, SH_TYPE); 650109313Sobrien flags = elf_get_word(e, v, SH_FLAGS); 651109313Sobrien addr = elf_get_addr(e, v, SH_ADDR); 652109313Sobrien offset = elf_get_off(e, v, SH_OFFSET); 653109313Sobrien size = elf_get_size(e, v, SH_SIZE); 654109313Sobrien link = elf_get_word(e, v, SH_LINK); 655109313Sobrien info = elf_get_word(e, v, SH_INFO); 656109313Sobrien addralign = elf_get_size(e, v, SH_ADDRALIGN); 657109313Sobrien entsize = elf_get_size(e, v, SH_ENTSIZE); 658109313Sobrien fprintf(out, "\n"); 659109313Sobrien fprintf(out, "entry: %d\n", i); 660109313Sobrien fprintf(out, "\tsh_name: %s\n", shstrtab + name); 661109329Sobrien fprintf(out, "\tsh_type: %s\n", sh_types(type)); 662109313Sobrien fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]); 663109313Sobrien fprintf(out, "\tsh_addr: %#llx\n", addr); 664109313Sobrien fprintf(out, "\tsh_offset: %lld\n", offset); 665109313Sobrien fprintf(out, "\tsh_size: %lld\n", size); 666109313Sobrien fprintf(out, "\tsh_link: %lld\n", link); 667109313Sobrien fprintf(out, "\tsh_info: %lld\n", info); 668109313Sobrien fprintf(out, "\tsh_addralign: %lld\n", addralign); 669109313Sobrien fprintf(out, "\tsh_entsize: %lld\n", entsize); 670109313Sobrien } 671109313Sobrien} 672109313Sobrien 673109313Sobrienvoid 674109313Sobrienelf_print_symtab(void *e, void *sh, char *str) 675109313Sobrien{ 676109313Sobrien u_int64_t offset; 677109313Sobrien u_int64_t entsize; 678109313Sobrien u_int64_t size; 679109313Sobrien u_int64_t name; 680109313Sobrien u_int64_t value; 681109313Sobrien u_int64_t info; 682109313Sobrien u_int64_t shndx; 683109313Sobrien void *st; 684109313Sobrien int len; 685109313Sobrien int i; 686109313Sobrien 687109313Sobrien offset = elf_get_off(e, sh, SH_OFFSET); 688109313Sobrien entsize = elf_get_size(e, sh, SH_ENTSIZE); 689109313Sobrien size = elf_get_size(e, sh, SH_SIZE); 690109313Sobrien name = elf_get_word(e, sh, SH_NAME); 691109313Sobrien len = size / entsize; 692109313Sobrien fprintf(out, "\nsymbol table (%s):\n", shstrtab + name); 693109313Sobrien for (i = 0; i < len; i++) { 694109313Sobrien st = e + offset + i * entsize; 695109313Sobrien name = elf_get_word(e, st, ST_NAME); 696109313Sobrien value = elf_get_addr(e, st, ST_VALUE); 697109313Sobrien size = elf_get_size(e, st, ST_SIZE); 698109313Sobrien info = elf_get_byte(e, st, ST_INFO); 699109313Sobrien shndx = elf_get_quarter(e, st, ST_SHNDX); 700109313Sobrien fprintf(out, "\n"); 701109313Sobrien fprintf(out, "entry: %d\n", i); 702109313Sobrien fprintf(out, "\tst_name: %s\n", str + name); 703109313Sobrien fprintf(out, "\tst_value: %#llx\n", value); 704109313Sobrien fprintf(out, "\tst_size: %lld\n", size); 705109313Sobrien fprintf(out, "\tst_info: %s %s\n", 706109313Sobrien st_types[ELF32_ST_TYPE(info)], 707109313Sobrien st_bindings[ELF32_ST_BIND(info)]); 708109313Sobrien fprintf(out, "\tst_shndx: %lld\n", shndx); 709109313Sobrien } 710109313Sobrien} 711109313Sobrien 712109313Sobrienvoid 713109313Sobrienelf_print_dynamic(void *e, void *sh) 714109313Sobrien{ 715109313Sobrien u_int64_t offset; 716109313Sobrien u_int64_t entsize; 717109313Sobrien u_int64_t size; 718109313Sobrien int64_t tag; 719109313Sobrien u_int64_t ptr; 720109313Sobrien u_int64_t val; 721109313Sobrien void *d; 722109313Sobrien int i; 723109313Sobrien 724109313Sobrien offset = elf_get_off(e, sh, SH_OFFSET); 725109313Sobrien entsize = elf_get_size(e, sh, SH_ENTSIZE); 726109313Sobrien size = elf_get_size(e, sh, SH_SIZE); 727109313Sobrien fprintf(out, "\ndynamic:\n"); 728109313Sobrien for (i = 0; i < size / entsize; i++) { 729109313Sobrien d = e + offset + i * entsize; 730109313Sobrien tag = elf_get_size(e, d, D_TAG); 731109313Sobrien ptr = elf_get_size(e, d, D_PTR); 732109313Sobrien val = elf_get_addr(e, d, D_VAL); 733109313Sobrien fprintf(out, "\n"); 734109313Sobrien fprintf(out, "entry: %d\n", i); 735109332Sobrien fprintf(out, "\td_tag: %s\n", d_tags(tag)); 736109313Sobrien switch (tag) { 737109313Sobrien case DT_NEEDED: 738109313Sobrien case DT_SONAME: 739109313Sobrien case DT_RPATH: 740109313Sobrien fprintf(out, "\td_val: %s\n", dynstr + val); 741109313Sobrien break; 742109313Sobrien case DT_PLTRELSZ: 743109313Sobrien case DT_RELA: 744109313Sobrien case DT_RELASZ: 745109313Sobrien case DT_RELAENT: 746109313Sobrien case DT_STRSZ: 747109313Sobrien case DT_SYMENT: 748109313Sobrien case DT_RELSZ: 749109313Sobrien case DT_RELENT: 750109313Sobrien case DT_PLTREL: 751109313Sobrien fprintf(out, "\td_val: %lld\n", val); 752109313Sobrien break; 753109313Sobrien case DT_PLTGOT: 754109313Sobrien case DT_HASH: 755109313Sobrien case DT_STRTAB: 756109313Sobrien case DT_SYMTAB: 757109313Sobrien case DT_INIT: 758109313Sobrien case DT_FINI: 759109313Sobrien case DT_REL: 760109313Sobrien case DT_JMPREL: 761109313Sobrien fprintf(out, "\td_ptr: %#llx\n", ptr); 762109313Sobrien break; 763109313Sobrien case DT_NULL: 764109313Sobrien case DT_SYMBOLIC: 765109313Sobrien case DT_DEBUG: 766109313Sobrien case DT_TEXTREL: 767109313Sobrien break; 768109313Sobrien } 769109313Sobrien } 770109313Sobrien} 771109313Sobrien 772109313Sobrienvoid 773109313Sobrienelf_print_rela(void *e, void *sh) 774109313Sobrien{ 775109313Sobrien u_int64_t offset; 776109313Sobrien u_int64_t entsize; 777109313Sobrien u_int64_t size; 778109313Sobrien u_int64_t name; 779109313Sobrien u_int64_t info; 780109313Sobrien int64_t addend; 781109313Sobrien void *ra; 782109313Sobrien void *v; 783109313Sobrien int i; 784109313Sobrien 785109313Sobrien offset = elf_get_off(e, sh, SH_OFFSET); 786109313Sobrien entsize = elf_get_size(e, sh, SH_ENTSIZE); 787109313Sobrien size = elf_get_size(e, sh, SH_SIZE); 788109313Sobrien name = elf_get_word(e, sh, SH_NAME); 789109313Sobrien v = e + offset; 790109313Sobrien fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name); 791109313Sobrien for (i = 0; i < size / entsize; i++) { 792109313Sobrien ra = v + i * entsize; 793109313Sobrien offset = elf_get_addr(e, ra, RA_OFFSET); 794109313Sobrien info = elf_get_word(e, ra, RA_INFO); 795109313Sobrien addend = elf_get_off(e, ra, RA_ADDEND); 796109313Sobrien fprintf(out, "\n"); 797109313Sobrien fprintf(out, "entry: %d\n", i); 798109313Sobrien fprintf(out, "\tr_offset: %#llx\n", offset); 799109313Sobrien fprintf(out, "\tr_info: %lld\n", info); 800109313Sobrien fprintf(out, "\tr_addend: %lld\n", addend); 801109313Sobrien } 802109313Sobrien} 803109313Sobrien 804109313Sobrienvoid 805109313Sobrienelf_print_rel(void *e, void *sh) 806109313Sobrien{ 807109313Sobrien u_int64_t offset; 808109313Sobrien u_int64_t entsize; 809109313Sobrien u_int64_t size; 810109313Sobrien u_int64_t name; 811109313Sobrien u_int64_t info; 812109313Sobrien void *r; 813109313Sobrien void *v; 814109313Sobrien int i; 815109313Sobrien 816109313Sobrien offset = elf_get_off(e, sh, SH_OFFSET); 817109313Sobrien entsize = elf_get_size(e, sh, SH_ENTSIZE); 818109313Sobrien size = elf_get_size(e, sh, SH_SIZE); 819109313Sobrien name = elf_get_word(e, sh, SH_NAME); 820109313Sobrien v = e + offset; 821109313Sobrien fprintf(out, "\nrelocation (%s):\n", shstrtab + name); 822109313Sobrien for (i = 0; i < size / entsize; i++) { 823109313Sobrien r = v + i * entsize; 824109313Sobrien offset = elf_get_addr(e, r, R_OFFSET); 825109313Sobrien info = elf_get_word(e, r, R_INFO); 826109313Sobrien fprintf(out, "\n"); 827109313Sobrien fprintf(out, "entry: %d\n", i); 828109313Sobrien fprintf(out, "\tr_offset: %#llx\n", offset); 829109313Sobrien fprintf(out, "\tr_info: %lld\n", info); 830109313Sobrien } 831109313Sobrien} 832109313Sobrien 833109313Sobrienvoid 834109313Sobrienelf_print_interp(void *e, void *p) 835109313Sobrien{ 836109313Sobrien u_int64_t offset; 837109313Sobrien char *s; 838109313Sobrien 839109313Sobrien offset = elf_get_off(e, p, P_OFFSET); 840109313Sobrien s = e + offset; 841109313Sobrien fprintf(out, "\ninterp:\n"); 842109313Sobrien fprintf(out, "\t%s\n", s); 843109313Sobrien} 844109313Sobrien 845109313Sobrienvoid 846109313Sobrienelf_print_got(void *e, void *sh) 847109313Sobrien{ 848109313Sobrien u_int64_t offset; 849109313Sobrien u_int64_t addralign; 850109313Sobrien u_int64_t size; 851109313Sobrien u_int64_t addr; 852109313Sobrien void *v; 853109313Sobrien int i; 854109313Sobrien 855109313Sobrien offset = elf_get_off(e, sh, SH_OFFSET); 856109313Sobrien addralign = elf_get_size(e, sh, SH_ADDRALIGN); 857109313Sobrien size = elf_get_size(e, sh, SH_SIZE); 858109313Sobrien v = e + offset; 859109313Sobrien fprintf(out, "\nglobal offset table:\n"); 860109313Sobrien for (i = 0; i < size / addralign; i++) { 861109313Sobrien addr = elf_get_addr(e, v + i * addralign, 0); 862109313Sobrien fprintf(out, "\n"); 863109313Sobrien fprintf(out, "entry: %d\n", i); 864109313Sobrien fprintf(out, "\t%#llx\n", addr); 865109313Sobrien } 866109313Sobrien} 867109313Sobrien 868109313Sobrienvoid 869109313Sobrienelf_print_hash(void *e, void *sh) 870109313Sobrien{ 871109313Sobrien} 872109313Sobrien 873109313Sobrienvoid 874109313Sobrienelf_print_note(void *e, void *sh) 875109313Sobrien{ 876109313Sobrien u_int64_t offset; 877109313Sobrien u_int64_t size; 878109313Sobrien u_int64_t name; 879109313Sobrien u_int32_t namesz; 880109313Sobrien u_int32_t descsz; 881109313Sobrien u_int32_t type; 882109313Sobrien u_int32_t desc; 883109313Sobrien char *s; 884109313Sobrien void *n; 885109313Sobrien 886109313Sobrien offset = elf_get_off(e, sh, SH_OFFSET); 887109313Sobrien size = elf_get_size(e, sh, SH_SIZE); 888109313Sobrien name = elf_get_word(e, sh, SH_NAME); 889109313Sobrien n = e + offset; 890109313Sobrien fprintf(out, "\nnote (%s):\n", shstrtab + name); 891109313Sobrien while (n < e + offset + size) { 892109313Sobrien namesz = elf_get_word(e, n, N_NAMESZ); 893109313Sobrien descsz = elf_get_word(e, n, N_DESCSZ); 894109313Sobrien type = elf_get_word(e, n, N_TYPE); 895109313Sobrien s = n + sizeof(Elf_Note); 896109313Sobrien desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0); 897109313Sobrien fprintf(out, "\t%s %d\n", s, desc); 898109313Sobrien n += sizeof(Elf_Note) + namesz + descsz; 899109313Sobrien } 900109313Sobrien} 901109313Sobrien 902109313Sobrienu_int64_t 903109313Sobrienelf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member) 904109313Sobrien{ 905109313Sobrien u_int64_t val; 906109313Sobrien u_char *p; 907109313Sobrien 908109313Sobrien val = 0; 909109313Sobrien switch (e->e_ident[EI_CLASS]) { 910109313Sobrien case ELFCLASS32: 911109313Sobrien p = base + elf32_offsets[member]; 912109313Sobrien val = *p; 913109313Sobrien break; 914109313Sobrien case ELFCLASS64: 915109313Sobrien p = base + elf64_offsets[member]; 916109313Sobrien val = *p; 917109313Sobrien break; 918109313Sobrien case ELFCLASSNONE: 919109313Sobrien errx(1, "invalid class"); 920109313Sobrien } 921109313Sobrien 922109313Sobrien return val; 923109313Sobrien} 924109313Sobrien 925109313Sobrienu_int64_t 926109313Sobrienelf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member) 927109313Sobrien{ 928109313Sobrien u_int64_t val; 929109313Sobrien u_char *p; 930109313Sobrien 931109313Sobrien val = 0; 932109313Sobrien switch (e->e_ident[EI_CLASS]) { 933109313Sobrien case ELFCLASS32: 934109313Sobrien p = base + elf32_offsets[member]; 935109313Sobrien switch (e->e_ident[EI_DATA]) { 936109313Sobrien case ELFDATA2MSB: 937109313Sobrien val = p[0] << 8 | p[1]; 938109313Sobrien break; 939109313Sobrien case ELFDATA2LSB: 940109313Sobrien val = p[1] << 8 | p[0]; 941109313Sobrien break; 942109313Sobrien case ELFDATANONE: 943109313Sobrien errx(1, "invalid data format"); 944109313Sobrien } 945109313Sobrien break; 946109313Sobrien case ELFCLASS64: 947109313Sobrien p = base + elf64_offsets[member]; 948109313Sobrien switch (e->e_ident[EI_DATA]) { 949109313Sobrien case ELFDATA2MSB: 950109313Sobrien val = p[0] << 8 | p[1]; 951109313Sobrien break; 952109313Sobrien case ELFDATA2LSB: 953109313Sobrien val = p[1] << 8 | p[0]; 954109313Sobrien break; 955109313Sobrien case ELFDATANONE: 956109313Sobrien errx(1, "invalid data format"); 957109313Sobrien } 958109313Sobrien break; 959109313Sobrien case ELFCLASSNONE: 960109313Sobrien errx(1, "invalid class"); 961109313Sobrien } 962109313Sobrien 963109313Sobrien return val; 964109313Sobrien} 965109313Sobrien 966109313Sobrienu_int64_t 967109313Sobrienelf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member) 968109313Sobrien{ 969109313Sobrien u_int64_t val; 970109313Sobrien u_char *p; 971109313Sobrien 972109313Sobrien val = 0; 973109313Sobrien switch (e->e_ident[EI_CLASS]) { 974109313Sobrien case ELFCLASS32: 975109313Sobrien p = base + elf32_offsets[member]; 976109313Sobrien switch (e->e_ident[EI_DATA]) { 977109313Sobrien case ELFDATA2MSB: 978109313Sobrien val = p[0] << 8 | p[1]; 979109313Sobrien break; 980109313Sobrien case ELFDATA2LSB: 981109313Sobrien val = p[1] << 8 | p[0]; 982109313Sobrien break; 983109313Sobrien case ELFDATANONE: 984109313Sobrien errx(1, "invalid data format"); 985109313Sobrien } 986109313Sobrien break; 987109313Sobrien case ELFCLASS64: 988109313Sobrien p = base + elf64_offsets[member]; 989109313Sobrien switch (e->e_ident[EI_DATA]) { 990109313Sobrien case ELFDATA2MSB: 991109313Sobrien val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 992109313Sobrien break; 993109313Sobrien case ELFDATA2LSB: 994109313Sobrien val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 995109313Sobrien break; 996109313Sobrien case ELFDATANONE: 997109313Sobrien errx(1, "invalid data format"); 998109313Sobrien } 999109313Sobrien break; 1000109313Sobrien case ELFCLASSNONE: 1001109313Sobrien errx(1, "invalid class"); 1002109313Sobrien } 1003109313Sobrien 1004109313Sobrien return val; 1005109313Sobrien} 1006109313Sobrien 1007109313Sobrienu_int64_t 1008109313Sobrienelf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member) 1009109313Sobrien{ 1010109313Sobrien u_int64_t val; 1011109313Sobrien u_char *p; 1012109313Sobrien 1013109313Sobrien val = 0; 1014109313Sobrien switch (e->e_ident[EI_CLASS]) { 1015109313Sobrien case ELFCLASS32: 1016109313Sobrien p = base + elf32_offsets[member]; 1017109313Sobrien switch (e->e_ident[EI_DATA]) { 1018109313Sobrien case ELFDATA2MSB: 1019109313Sobrien val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1020109313Sobrien break; 1021109313Sobrien case ELFDATA2LSB: 1022109313Sobrien val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1023109313Sobrien break; 1024109313Sobrien case ELFDATANONE: 1025109313Sobrien errx(1, "invalid data format"); 1026109313Sobrien } 1027109313Sobrien break; 1028109313Sobrien case ELFCLASS64: 1029109313Sobrien p = base + elf64_offsets[member]; 1030109313Sobrien switch (e->e_ident[EI_DATA]) { 1031109313Sobrien case ELFDATA2MSB: 1032109313Sobrien val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1033109313Sobrien break; 1034109313Sobrien case ELFDATA2LSB: 1035109313Sobrien val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1036109313Sobrien break; 1037109313Sobrien case ELFDATANONE: 1038109313Sobrien errx(1, "invalid data format"); 1039109313Sobrien } 1040109313Sobrien break; 1041109313Sobrien case ELFCLASSNONE: 1042109313Sobrien errx(1, "invalid class"); 1043109313Sobrien } 1044109313Sobrien 1045109313Sobrien return val; 1046109313Sobrien} 1047109313Sobrien 1048109313Sobrienu_int64_t 1049109313Sobrienelf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member) 1050109313Sobrien{ 1051109313Sobrien u_int64_t high; 1052109313Sobrien u_int64_t low; 1053109313Sobrien u_int64_t val; 1054109313Sobrien u_char *p; 1055109313Sobrien 1056109313Sobrien val = 0; 1057109313Sobrien switch (e->e_ident[EI_CLASS]) { 1058109313Sobrien case ELFCLASS32: 1059109313Sobrien p = base + elf32_offsets[member]; 1060109313Sobrien switch (e->e_ident[EI_DATA]) { 1061109313Sobrien case ELFDATA2MSB: 1062109313Sobrien val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1063109313Sobrien break; 1064109313Sobrien case ELFDATA2LSB: 1065109313Sobrien val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1066109313Sobrien break; 1067109313Sobrien case ELFDATANONE: 1068109313Sobrien errx(1, "invalid data format"); 1069109313Sobrien } 1070109313Sobrien break; 1071109313Sobrien case ELFCLASS64: 1072109313Sobrien p = base + elf64_offsets[member]; 1073109313Sobrien switch (e->e_ident[EI_DATA]) { 1074109313Sobrien case ELFDATA2MSB: 1075109313Sobrien high = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 1076109313Sobrien low = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; 1077109313Sobrien val = high << 32 | low; 1078109313Sobrien break; 1079109313Sobrien case ELFDATA2LSB: 1080109313Sobrien high = p[7] << 24 | p[6] << 16 | p[5] << 8 | p[4]; 1081109313Sobrien low = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 1082109313Sobrien val = high << 32 | low; 1083109313Sobrien break; 1084109313Sobrien case ELFDATANONE: 1085109313Sobrien errx(1, "invalid data format"); 1086109313Sobrien } 1087109313Sobrien break; 1088109313Sobrien case ELFCLASSNONE: 1089109313Sobrien errx(1, "invalid class"); 1090109313Sobrien } 1091109313Sobrien 1092109313Sobrien return val; 1093109313Sobrien} 1094109313Sobrien 1095109313Sobrienvoid 1096109313Sobrienusage(void) 1097109313Sobrien{ 1098109313Sobrien fprintf(stderr, "usage: elfdump [-acdeiGhnprs] [-w file] filename\n"); 1099109313Sobrien exit(1); 1100109313Sobrien} 1101