1 /*- 2 * Copyright (c) 2003 David O'Brien. All rights reserved. 3 * Copyright (c) 2001 Jake Burkholder 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/types.h> 32 33 #include <sys/capsicum.h> 34 #include <sys/elf32.h> 35 #include <sys/elf64.h> 36 #include <sys/endian.h> 37 #include <sys/mman.h> 38 #include <sys/stat.h> 39 #include <err.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <inttypes.h> 43 #include <stddef.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #define ED_DYN (1<<0) 50 #define ED_EHDR (1<<1) 51 #define ED_GOT (1<<2) 52 #define ED_HASH (1<<3) 53 #define ED_INTERP (1<<4) 54 #define ED_NOTE (1<<5) 55 #define ED_PHDR (1<<6) 56 #define ED_REL (1<<7) 57 #define ED_SHDR (1<<8) 58 #define ED_SYMTAB (1<<9) 59 #define ED_ALL ((1<<10)-1) 60 61 #define elf_get_addr elf_get_quad 62 #define elf_get_off elf_get_quad 63 #define elf_get_size elf_get_quad 64 65 enum elf_member { 66 D_TAG = 1, D_PTR, D_VAL, 67 68 E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY, 69 E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE, 70 E_SHNUM, E_SHSTRNDX, 71 72 N_NAMESZ, N_DESCSZ, N_TYPE, 73 74 P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS, 75 P_ALIGN, 76 77 SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK, 78 SH_INFO, SH_ADDRALIGN, SH_ENTSIZE, 79 80 ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX, 81 82 R_OFFSET, R_INFO, 83 84 RA_OFFSET, RA_INFO, RA_ADDEND 85 }; 86 87 typedef enum elf_member elf_member_t; 88 89 static int elf32_offsets[] = { 90 0, 91 92 offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr), 93 offsetof(Elf32_Dyn, d_un.d_val), 94 95 offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 96 offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 97 offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 98 offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine), 99 offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry), 100 offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff), 101 offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize), 102 offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum), 103 offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum), 104 offsetof(Elf32_Ehdr, e_shstrndx), 105 106 offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 107 offsetof(Elf_Note, n_type), 108 109 offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset), 110 offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr), 111 offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz), 112 offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align), 113 114 offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type), 115 offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr), 116 offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size), 117 offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info), 118 offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize), 119 120 offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value), 121 offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info), 122 offsetof(Elf32_Sym, st_shndx), 123 124 offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info), 125 126 offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info), 127 offsetof(Elf32_Rela, r_addend) 128 }; 129 130 static int elf64_offsets[] = { 131 0, 132 133 offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr), 134 offsetof(Elf64_Dyn, d_un.d_val), 135 136 offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 137 offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 138 offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 139 offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine), 140 offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry), 141 offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff), 142 offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize), 143 offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum), 144 offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum), 145 offsetof(Elf64_Ehdr, e_shstrndx), 146 147 offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 148 offsetof(Elf_Note, n_type), 149 150 offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset), 151 offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr), 152 offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz), 153 offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align), 154 155 offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type), 156 offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr), 157 offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size), 158 offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info), 159 offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize), 160 161 offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value), 162 offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info), 163 offsetof(Elf64_Sym, st_shndx), 164 165 offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info), 166 167 offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info), 168 offsetof(Elf64_Rela, r_addend) 169 }; 170 171 /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 172 static const char * 173 d_tags(u_int64_t tag) 174 { 175 static char unknown_tag[48]; 176 177 switch (tag) { 178 case DT_NULL: return "DT_NULL"; 179 case DT_NEEDED: return "DT_NEEDED"; 180 case DT_PLTRELSZ: return "DT_PLTRELSZ"; 181 case DT_PLTGOT: return "DT_PLTGOT"; 182 case DT_HASH: return "DT_HASH"; 183 case DT_STRTAB: return "DT_STRTAB"; 184 case DT_SYMTAB: return "DT_SYMTAB"; 185 case DT_RELA: return "DT_RELA"; 186 case DT_RELASZ: return "DT_RELASZ"; 187 case DT_RELAENT: return "DT_RELAENT"; 188 case DT_STRSZ: return "DT_STRSZ"; 189 case DT_SYMENT: return "DT_SYMENT"; 190 case DT_INIT: return "DT_INIT"; 191 case DT_FINI: return "DT_FINI"; 192 case DT_SONAME: return "DT_SONAME"; 193 case DT_RPATH: return "DT_RPATH"; 194 case DT_SYMBOLIC: return "DT_SYMBOLIC"; 195 case DT_REL: return "DT_REL"; 196 case DT_RELSZ: return "DT_RELSZ"; 197 case DT_RELENT: return "DT_RELENT"; 198 case DT_PLTREL: return "DT_PLTREL"; 199 case DT_DEBUG: return "DT_DEBUG"; 200 case DT_TEXTREL: return "DT_TEXTREL"; 201 case DT_JMPREL: return "DT_JMPREL"; 202 case DT_BIND_NOW: return "DT_BIND_NOW"; 203 case DT_INIT_ARRAY: return "DT_INIT_ARRAY"; 204 case DT_FINI_ARRAY: return "DT_FINI_ARRAY"; 205 case DT_INIT_ARRAYSZ: return "DT_INIT_ARRAYSZ"; 206 case DT_FINI_ARRAYSZ: return "DT_FINI_ARRAYSZ"; 207 case DT_RUNPATH: return "DT_RUNPATH"; 208 case DT_FLAGS: return "DT_FLAGS"; 209 case DT_PREINIT_ARRAY: return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */ 210 case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ"; 211 /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 212 case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 213 case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 214 case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 215 case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 216 case DT_PLTPADSZ: return "DT_PLTPADSZ"; 217 case DT_MOVEENT: return "DT_MOVEENT"; 218 case DT_MOVESZ: return "DT_MOVESZ"; 219 case DT_FEATURE: return "DT_FEATURE"; 220 case DT_POSFLAG_1: return "DT_POSFLAG_1"; 221 case DT_SYMINSZ: return "DT_SYMINSZ"; 222 case DT_SYMINENT : return "DT_SYMINENT (DT_VALRNGHI)"; 223 case DT_ADDRRNGLO: return "DT_ADDRRNGLO"; 224 case DT_GNU_HASH: return "DT_GNU_HASH"; 225 case 0x6ffffef8: return "DT_GNU_CONFLICT"; 226 case 0x6ffffef9: return "DT_GNU_LIBLIST"; 227 case DT_CONFIG: return "DT_CONFIG"; 228 case DT_DEPAUDIT: return "DT_DEPAUDIT"; 229 case DT_AUDIT: return "DT_AUDIT"; 230 case DT_PLTPAD: return "DT_PLTPAD"; 231 case DT_MOVETAB: return "DT_MOVETAB"; 232 case DT_SYMINFO : return "DT_SYMINFO (DT_ADDRRNGHI)"; 233 case DT_RELACOUNT: return "DT_RELACOUNT"; 234 case DT_RELCOUNT: return "DT_RELCOUNT"; 235 case DT_FLAGS_1: return "DT_FLAGS_1"; 236 case DT_VERDEF: return "DT_VERDEF"; 237 case DT_VERDEFNUM: return "DT_VERDEFNUM"; 238 case DT_VERNEED: return "DT_VERNEED"; 239 case DT_VERNEEDNUM: return "DT_VERNEEDNUM"; 240 case 0x6ffffff0: return "DT_GNU_VERSYM"; 241 /* 0x70000000 - 0x7fffffff processor-specific semantics */ 242 case 0x70000000: return "DT_IA_64_PLT_RESERVE"; 243 case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; 244 case 0x7ffffffe: return "DT_SUNW_USED"; 245 case 0x7fffffff: return "DT_SUNW_FILTER"; 246 } 247 snprintf(unknown_tag, sizeof(unknown_tag), 248 "ERROR: TAG NOT DEFINED -- tag 0x%jx", (uintmax_t)tag); 249 return (unknown_tag); 250 } 251 252 static const char * 253 e_machines(u_int mach) 254 { 255 static char machdesc[64]; 256 257 switch (mach) { 258 case EM_NONE: return "EM_NONE"; 259 case EM_M32: return "EM_M32"; 260 case EM_SPARC: return "EM_SPARC"; 261 case EM_386: return "EM_386"; 262 case EM_68K: return "EM_68K"; 263 case EM_88K: return "EM_88K"; 264 case EM_860: return "EM_860"; 265 case EM_MIPS: return "EM_MIPS"; 266 case EM_PPC: return "EM_PPC"; 267 case EM_PPC64: return "EM_PPC64"; 268 case EM_ARM: return "EM_ARM"; 269 case EM_ALPHA: return "EM_ALPHA (legacy)"; 270 case EM_SPARCV9:return "EM_SPARCV9"; 271 case EM_IA_64: return "EM_IA_64"; 272 case EM_X86_64: return "EM_X86_64"; 273 case EM_AARCH64:return "EM_AARCH64"; 274 } 275 snprintf(machdesc, sizeof(machdesc), 276 "(unknown machine) -- type 0x%x", mach); 277 return (machdesc); 278 } 279 280 static const char *e_types[] = { 281 "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 282 }; 283 284 static const char *ei_versions[] = { 285 "EV_NONE", "EV_CURRENT" 286 }; 287 288 static const char *ei_classes[] = { 289 "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 290 }; 291 292 static const char *ei_data[] = { 293 "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 294 }; 295 296 static const char *ei_abis[256] = { 297 "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 298 "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX", 299 "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64", 300 "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD", 301 [255] = "ELFOSABI_STANDALONE" 302 }; 303 304 static const char *p_types[] = { 305 "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 306 "PT_SHLIB", "PT_PHDR", "PT_TLS" 307 }; 308 309 static const char *p_flags[] = { 310 "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 311 "PF_X|PF_W|PF_R" 312 }; 313 314 /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 315 static const char * 316 sh_types(uint64_t machine, uint64_t sht) { 317 static char unknown_buf[64]; 318 319 if (sht < 0x60000000) { 320 switch (sht) { 321 case SHT_NULL: return "SHT_NULL"; 322 case SHT_PROGBITS: return "SHT_PROGBITS"; 323 case SHT_SYMTAB: return "SHT_SYMTAB"; 324 case SHT_STRTAB: return "SHT_STRTAB"; 325 case SHT_RELA: return "SHT_RELA"; 326 case SHT_HASH: return "SHT_HASH"; 327 case SHT_DYNAMIC: return "SHT_DYNAMIC"; 328 case SHT_NOTE: return "SHT_NOTE"; 329 case SHT_NOBITS: return "SHT_NOBITS"; 330 case SHT_REL: return "SHT_REL"; 331 case SHT_SHLIB: return "SHT_SHLIB"; 332 case SHT_DYNSYM: return "SHT_DYNSYM"; 333 case SHT_INIT_ARRAY: return "SHT_INIT_ARRAY"; 334 case SHT_FINI_ARRAY: return "SHT_FINI_ARRAY"; 335 case SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY"; 336 case SHT_GROUP: return "SHT_GROUP"; 337 case SHT_SYMTAB_SHNDX: return "SHT_SYMTAB_SHNDX"; 338 } 339 snprintf(unknown_buf, sizeof(unknown_buf), 340 "ERROR: SHT %ju NOT DEFINED", (uintmax_t)sht); 341 return (unknown_buf); 342 } else if (sht < 0x70000000) { 343 /* 0x60000000-0x6fffffff operating system-specific semantics */ 344 switch (sht) { 345 case 0x6ffffff0: return "XXX:VERSYM"; 346 case SHT_SUNW_dof: return "SHT_SUNW_dof"; 347 case SHT_GNU_HASH: return "SHT_GNU_HASH"; 348 case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 349 case 0x6ffffffc: return "XXX:VERDEF"; 350 case SHT_SUNW_verdef: return "SHT_SUNW(GNU)_verdef"; 351 case SHT_SUNW_verneed: return "SHT_SUNW(GNU)_verneed"; 352 case SHT_SUNW_versym: return "SHT_SUNW(GNU)_versym"; 353 } 354 snprintf(unknown_buf, sizeof(unknown_buf), 355 "ERROR: OS-SPECIFIC SHT 0x%jx NOT DEFINED", 356 (uintmax_t)sht); 357 return (unknown_buf); 358 } else if (sht < 0x80000000) { 359 /* 0x70000000-0x7fffffff processor-specific semantics */ 360 switch (machine) { 361 case EM_ARM: 362 switch (sht) { 363 case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX"; 364 case SHT_ARM_PREEMPTMAP:return "SHT_ARM_PREEMPTMAP"; 365 case SHT_ARM_ATTRIBUTES:return "SHT_ARM_ATTRIBUTES"; 366 case SHT_ARM_DEBUGOVERLAY: 367 return "SHT_ARM_DEBUGOVERLAY"; 368 case SHT_ARM_OVERLAYSECTION: 369 return "SHT_ARM_OVERLAYSECTION"; 370 } 371 break; 372 case EM_IA_64: 373 switch (sht) { 374 case 0x70000000: return "SHT_IA_64_EXT"; 375 case 0x70000001: return "SHT_IA_64_UNWIND"; 376 } 377 break; 378 case EM_MIPS: 379 switch (sht) { 380 case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS"; 381 } 382 break; 383 } 384 switch (sht) { 385 case 0x7ffffffd: return "XXX:AUXILIARY"; 386 case 0x7fffffff: return "XXX:FILTER"; 387 } 388 snprintf(unknown_buf, sizeof(unknown_buf), 389 "ERROR: PROCESSOR-SPECIFIC SHT 0x%jx NOT DEFINED", 390 (uintmax_t)sht); 391 return (unknown_buf); 392 } else { 393 /* 0x80000000-0xffffffff application programs */ 394 snprintf(unknown_buf, sizeof(unknown_buf), 395 "ERROR: SHT 0x%jx NOT DEFINED", 396 (uintmax_t)sht); 397 return (unknown_buf); 398 } 399 } 400 401 static const char *sh_flags[] = { 402 "", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR", 403 "SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR", 404 "SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR" 405 }; 406 407 static const char *st_types[] = { 408 "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE" 409 }; 410 411 static const char *st_bindings[] = { 412 "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 413 }; 414 415 static char *dynstr; 416 static char *shstrtab; 417 static char *strtab; 418 static FILE *out; 419 420 static u_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member); 421 static u_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, 422 elf_member_t member); 423 #if 0 424 static u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member); 425 #endif 426 static u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member); 427 static u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member); 428 429 static void elf_print_ehdr(Elf32_Ehdr *e, void *sh); 430 static void elf_print_phdr(Elf32_Ehdr *e, void *p); 431 static void elf_print_shdr(Elf32_Ehdr *e, void *sh); 432 static void elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str); 433 static void elf_print_dynamic(Elf32_Ehdr *e, void *sh); 434 static void elf_print_rel(Elf32_Ehdr *e, void *r); 435 static void elf_print_rela(Elf32_Ehdr *e, void *ra); 436 static void elf_print_interp(Elf32_Ehdr *e, void *p); 437 static void elf_print_got(Elf32_Ehdr *e, void *sh); 438 static void elf_print_hash(Elf32_Ehdr *e, void *sh); 439 static void elf_print_note(Elf32_Ehdr *e, void *sh); 440 441 static void usage(void); 442 443 /* 444 * Helpers for ELF files with shnum or shstrndx values that don't fit in the 445 * ELF header. If the values are too large then an escape value is used to 446 * indicate that the actual value is found in one of section 0's fields. 447 */ 448 static uint64_t 449 elf_get_shnum(Elf32_Ehdr *e, void *sh) 450 { 451 uint64_t shnum; 452 453 shnum = elf_get_quarter(e, e, E_SHNUM); 454 if (shnum == 0) 455 shnum = elf_get_word(e, (char *)sh, SH_SIZE); 456 return shnum; 457 } 458 459 static uint64_t 460 elf_get_shstrndx(Elf32_Ehdr *e, void *sh) 461 { 462 uint64_t shstrndx; 463 464 shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 465 if (shstrndx == SHN_XINDEX) 466 shstrndx = elf_get_word(e, (char *)sh, SH_LINK); 467 return shstrndx; 468 } 469 470 int 471 main(int ac, char **av) 472 { 473 cap_rights_t rights; 474 u_int64_t phoff; 475 u_int64_t shoff; 476 u_int64_t phentsize; 477 u_int64_t phnum; 478 u_int64_t shentsize; 479 u_int64_t shnum; 480 u_int64_t shstrndx; 481 u_int64_t offset; 482 u_int64_t name; 483 u_int64_t type; 484 struct stat sb; 485 u_int flags; 486 Elf32_Ehdr *e; 487 void *p; 488 void *sh; 489 void *v; 490 int fd; 491 int ch; 492 int i; 493 494 out = stdout; 495 flags = 0; 496 while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1) 497 switch (ch) { 498 case 'a': 499 flags = ED_ALL; 500 break; 501 case 'c': 502 flags |= ED_SHDR; 503 break; 504 case 'd': 505 flags |= ED_DYN; 506 break; 507 case 'e': 508 flags |= ED_EHDR; 509 break; 510 case 'i': 511 flags |= ED_INTERP; 512 break; 513 case 'G': 514 flags |= ED_GOT; 515 break; 516 case 'h': 517 flags |= ED_HASH; 518 break; 519 case 'n': 520 flags |= ED_NOTE; 521 break; 522 case 'p': 523 flags |= ED_PHDR; 524 break; 525 case 'r': 526 flags |= ED_REL; 527 break; 528 case 's': 529 flags |= ED_SYMTAB; 530 break; 531 case 'w': 532 if ((out = fopen(optarg, "w")) == NULL) 533 err(1, "%s", optarg); 534 cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE); 535 if (cap_rights_limit(fileno(out), &rights) < 0 && errno != ENOSYS) 536 err(1, "unable to limit rights for %s", optarg); 537 break; 538 case '?': 539 default: 540 usage(); 541 } 542 ac -= optind; 543 av += optind; 544 if (ac == 0 || flags == 0) 545 usage(); 546 if ((fd = open(*av, O_RDONLY)) < 0 || 547 fstat(fd, &sb) < 0) 548 err(1, "%s", *av); 549 cap_rights_init(&rights, CAP_MMAP_R); 550 if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) 551 err(1, "unable to limit rights for %s", *av); 552 close(STDIN_FILENO); 553 cap_rights_init(&rights, CAP_WRITE); 554 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) 555 err(1, "unable to limit rights for stdout"); 556 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) 557 err(1, "unable to limit rights for stderr"); 558 if (cap_enter() < 0 && errno != ENOSYS) 559 err(1, "unable to enter capability mode"); 560 e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 561 if (e == MAP_FAILED) 562 err(1, NULL); 563 if (!IS_ELF(*(Elf32_Ehdr *)e)) 564 errx(1, "not an elf file"); 565 phoff = elf_get_off(e, e, E_PHOFF); 566 shoff = elf_get_off(e, e, E_SHOFF); 567 phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 568 phnum = elf_get_quarter(e, e, E_PHNUM); 569 shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 570 p = (char *)e + phoff; 571 if (shoff > 0) { 572 sh = (char *)e + shoff; 573 shnum = elf_get_shnum(e, sh); 574 shstrndx = elf_get_shstrndx(e, sh); 575 offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, 576 SH_OFFSET); 577 shstrtab = (char *)e + offset; 578 } else { 579 sh = NULL; 580 shnum = 0; 581 shstrndx = 0; 582 shstrtab = NULL; 583 } 584 for (i = 0; (u_int64_t)i < shnum; i++) { 585 name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME); 586 offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET); 587 if (strcmp(shstrtab + name, ".strtab") == 0) 588 strtab = (char *)e + offset; 589 if (strcmp(shstrtab + name, ".dynstr") == 0) 590 dynstr = (char *)e + offset; 591 } 592 if (flags & ED_EHDR) 593 elf_print_ehdr(e, sh); 594 if (flags & ED_PHDR) 595 elf_print_phdr(e, p); 596 if (flags & ED_SHDR) 597 elf_print_shdr(e, sh); 598 for (i = 0; (u_int64_t)i < phnum; i++) { 599 v = (char *)p + i * phentsize; 600 type = elf_get_word(e, v, P_TYPE); 601 switch (type) { 602 case PT_INTERP: 603 if (flags & ED_INTERP) 604 elf_print_interp(e, v); 605 break; 606 case PT_NULL: 607 case PT_LOAD: 608 case PT_DYNAMIC: 609 case PT_NOTE: 610 case PT_SHLIB: 611 case PT_PHDR: 612 break; 613 } 614 } 615 for (i = 0; (u_int64_t)i < shnum; i++) { 616 v = (char *)sh + i * shentsize; 617 type = elf_get_word(e, v, SH_TYPE); 618 switch (type) { 619 case SHT_SYMTAB: 620 if (flags & ED_SYMTAB) 621 elf_print_symtab(e, v, strtab); 622 break; 623 case SHT_DYNAMIC: 624 if (flags & ED_DYN) 625 elf_print_dynamic(e, v); 626 break; 627 case SHT_RELA: 628 if (flags & ED_REL) 629 elf_print_rela(e, v); 630 break; 631 case SHT_REL: 632 if (flags & ED_REL) 633 elf_print_rel(e, v); 634 break; 635 case SHT_NOTE: 636 name = elf_get_word(e, v, SH_NAME); 637 if (flags & ED_NOTE && 638 strcmp(shstrtab + name, ".note.ABI-tag") == 0) 639 elf_print_note(e, v); 640 break; 641 case SHT_DYNSYM: 642 if (flags & ED_SYMTAB) 643 elf_print_symtab(e, v, dynstr); 644 break; 645 case SHT_PROGBITS: 646 name = elf_get_word(e, v, SH_NAME); 647 if (flags & ED_GOT && 648 strcmp(shstrtab + name, ".got") == 0) 649 elf_print_got(e, v); 650 break; 651 case SHT_HASH: 652 if (flags & ED_HASH) 653 elf_print_hash(e, v); 654 break; 655 case SHT_NULL: 656 case SHT_STRTAB: 657 case SHT_NOBITS: 658 case SHT_SHLIB: 659 break; 660 } 661 } 662 663 return 0; 664 } 665 666 static void 667 elf_print_ehdr(Elf32_Ehdr *e, void *sh) 668 { 669 u_int64_t class; 670 u_int64_t data; 671 u_int64_t osabi; 672 u_int64_t type; 673 u_int64_t machine; 674 u_int64_t version; 675 u_int64_t entry; 676 u_int64_t phoff; 677 u_int64_t shoff; 678 u_int64_t flags; 679 u_int64_t ehsize; 680 u_int64_t phentsize; 681 u_int64_t phnum; 682 u_int64_t shentsize; 683 u_int64_t shnum; 684 u_int64_t shstrndx; 685 686 class = elf_get_byte(e, e, E_CLASS); 687 data = elf_get_byte(e, e, E_DATA); 688 osabi = elf_get_byte(e, e, E_OSABI); 689 type = elf_get_quarter(e, e, E_TYPE); 690 machine = elf_get_quarter(e, e, E_MACHINE); 691 version = elf_get_word(e, e, E_VERSION); 692 entry = elf_get_addr(e, e, E_ENTRY); 693 phoff = elf_get_off(e, e, E_PHOFF); 694 shoff = elf_get_off(e, e, E_SHOFF); 695 flags = elf_get_word(e, e, E_FLAGS); 696 ehsize = elf_get_quarter(e, e, E_EHSIZE); 697 phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 698 phnum = elf_get_quarter(e, e, E_PHNUM); 699 shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 700 fprintf(out, "\nelf header:\n"); 701 fprintf(out, "\n"); 702 fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data], 703 ei_abis[osabi]); 704 fprintf(out, "\te_type: %s\n", e_types[type]); 705 fprintf(out, "\te_machine: %s\n", e_machines(machine)); 706 fprintf(out, "\te_version: %s\n", ei_versions[version]); 707 fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry); 708 fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff); 709 fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff); 710 fprintf(out, "\te_flags: %jd\n", (intmax_t)flags); 711 fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize); 712 fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize); 713 fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum); 714 fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize); 715 if (sh != NULL) { 716 shnum = elf_get_shnum(e, sh); 717 shstrndx = elf_get_shstrndx(e, sh); 718 fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum); 719 fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx); 720 } 721 } 722 723 static void 724 elf_print_phdr(Elf32_Ehdr *e, void *p) 725 { 726 u_int64_t phentsize; 727 u_int64_t phnum; 728 u_int64_t type; 729 u_int64_t offset; 730 u_int64_t vaddr; 731 u_int64_t paddr; 732 u_int64_t filesz; 733 u_int64_t memsz; 734 u_int64_t flags; 735 u_int64_t align; 736 void *v; 737 int i; 738 739 phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 740 phnum = elf_get_quarter(e, e, E_PHNUM); 741 fprintf(out, "\nprogram header:\n"); 742 for (i = 0; (u_int64_t)i < phnum; i++) { 743 v = (char *)p + i * phentsize; 744 type = elf_get_word(e, v, P_TYPE); 745 offset = elf_get_off(e, v, P_OFFSET); 746 vaddr = elf_get_addr(e, v, P_VADDR); 747 paddr = elf_get_addr(e, v, P_PADDR); 748 filesz = elf_get_size(e, v, P_FILESZ); 749 memsz = elf_get_size(e, v, P_MEMSZ); 750 flags = elf_get_word(e, v, P_FLAGS); 751 align = elf_get_size(e, v, P_ALIGN); 752 fprintf(out, "\n"); 753 fprintf(out, "entry: %d\n", i); 754 fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]); 755 fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset); 756 fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr); 757 fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr); 758 fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz); 759 fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz); 760 fprintf(out, "\tp_flags: %s\n", p_flags[flags]); 761 fprintf(out, "\tp_align: %jd\n", (intmax_t)align); 762 } 763 } 764 765 static void 766 elf_print_shdr(Elf32_Ehdr *e, void *sh) 767 { 768 u_int64_t shentsize; 769 u_int64_t shnum; 770 u_int64_t name; 771 u_int64_t type; 772 u_int64_t flags; 773 u_int64_t addr; 774 u_int64_t offset; 775 u_int64_t size; 776 u_int64_t shlink; 777 u_int64_t info; 778 u_int64_t addralign; 779 u_int64_t entsize; 780 u_int64_t machine; 781 void *v; 782 int i; 783 784 if (sh == NULL) { 785 fprintf(out, "\nNo section headers\n"); 786 return; 787 } 788 789 machine = elf_get_quarter(e, e, E_MACHINE); 790 shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 791 shnum = elf_get_shnum(e, sh); 792 fprintf(out, "\nsection header:\n"); 793 for (i = 0; (u_int64_t)i < shnum; i++) { 794 v = (char *)sh + i * shentsize; 795 name = elf_get_word(e, v, SH_NAME); 796 type = elf_get_word(e, v, SH_TYPE); 797 flags = elf_get_word(e, v, SH_FLAGS); 798 addr = elf_get_addr(e, v, SH_ADDR); 799 offset = elf_get_off(e, v, SH_OFFSET); 800 size = elf_get_size(e, v, SH_SIZE); 801 shlink = elf_get_word(e, v, SH_LINK); 802 info = elf_get_word(e, v, SH_INFO); 803 addralign = elf_get_size(e, v, SH_ADDRALIGN); 804 entsize = elf_get_size(e, v, SH_ENTSIZE); 805 fprintf(out, "\n"); 806 fprintf(out, "entry: %d\n", i); 807 fprintf(out, "\tsh_name: %s\n", shstrtab + name); 808 fprintf(out, "\tsh_type: %s\n", sh_types(machine, type)); 809 fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]); 810 fprintf(out, "\tsh_addr: %#jx\n", addr); 811 fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset); 812 fprintf(out, "\tsh_size: %jd\n", (intmax_t)size); 813 fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink); 814 fprintf(out, "\tsh_info: %jd\n", (intmax_t)info); 815 fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign); 816 fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize); 817 } 818 } 819 820 static void 821 elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str) 822 { 823 u_int64_t offset; 824 u_int64_t entsize; 825 u_int64_t size; 826 u_int64_t name; 827 u_int64_t value; 828 u_int64_t info; 829 u_int64_t shndx; 830 void *st; 831 int len; 832 int i; 833 834 offset = elf_get_off(e, sh, SH_OFFSET); 835 entsize = elf_get_size(e, sh, SH_ENTSIZE); 836 size = elf_get_size(e, sh, SH_SIZE); 837 name = elf_get_word(e, sh, SH_NAME); 838 len = size / entsize; 839 fprintf(out, "\nsymbol table (%s):\n", shstrtab + name); 840 for (i = 0; i < len; i++) { 841 st = (char *)e + offset + i * entsize; 842 name = elf_get_word(e, st, ST_NAME); 843 value = elf_get_addr(e, st, ST_VALUE); 844 size = elf_get_size(e, st, ST_SIZE); 845 info = elf_get_byte(e, st, ST_INFO); 846 shndx = elf_get_quarter(e, st, ST_SHNDX); 847 fprintf(out, "\n"); 848 fprintf(out, "entry: %d\n", i); 849 fprintf(out, "\tst_name: %s\n", str + name); 850 fprintf(out, "\tst_value: %#jx\n", value); 851 fprintf(out, "\tst_size: %jd\n", (intmax_t)size); 852 fprintf(out, "\tst_info: %s %s\n", 853 st_types[ELF32_ST_TYPE(info)], 854 st_bindings[ELF32_ST_BIND(info)]); 855 fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx); 856 } 857 } 858 859 static void 860 elf_print_dynamic(Elf32_Ehdr *e, void *sh) 861 { 862 u_int64_t offset; 863 u_int64_t entsize; 864 u_int64_t size; 865 int64_t tag; 866 u_int64_t ptr; 867 u_int64_t val; 868 void *d; 869 int i; 870 871 offset = elf_get_off(e, sh, SH_OFFSET); 872 entsize = elf_get_size(e, sh, SH_ENTSIZE); 873 size = elf_get_size(e, sh, SH_SIZE); 874 fprintf(out, "\ndynamic:\n"); 875 for (i = 0; (u_int64_t)i < size / entsize; i++) { 876 d = (char *)e + offset + i * entsize; 877 tag = elf_get_size(e, d, D_TAG); 878 ptr = elf_get_size(e, d, D_PTR); 879 val = elf_get_addr(e, d, D_VAL); 880 fprintf(out, "\n"); 881 fprintf(out, "entry: %d\n", i); 882 fprintf(out, "\td_tag: %s\n", d_tags(tag)); 883 switch (tag) { 884 case DT_NEEDED: 885 case DT_SONAME: 886 case DT_RPATH: 887 fprintf(out, "\td_val: %s\n", dynstr + val); 888 break; 889 case DT_PLTRELSZ: 890 case DT_RELA: 891 case DT_RELASZ: 892 case DT_RELAENT: 893 case DT_STRSZ: 894 case DT_SYMENT: 895 case DT_RELSZ: 896 case DT_RELENT: 897 case DT_PLTREL: 898 fprintf(out, "\td_val: %jd\n", (intmax_t)val); 899 break; 900 case DT_PLTGOT: 901 case DT_HASH: 902 case DT_STRTAB: 903 case DT_SYMTAB: 904 case DT_INIT: 905 case DT_FINI: 906 case DT_REL: 907 case DT_JMPREL: 908 fprintf(out, "\td_ptr: %#jx\n", ptr); 909 break; 910 case DT_NULL: 911 case DT_SYMBOLIC: 912 case DT_DEBUG: 913 case DT_TEXTREL: 914 break; 915 } 916 } 917 } 918 919 static void 920 elf_print_rela(Elf32_Ehdr *e, void *sh) 921 { 922 u_int64_t offset; 923 u_int64_t entsize; 924 u_int64_t size; 925 u_int64_t name; 926 u_int64_t info; 927 int64_t addend; 928 void *ra; 929 void *v; 930 int i; 931 932 offset = elf_get_off(e, sh, SH_OFFSET); 933 entsize = elf_get_size(e, sh, SH_ENTSIZE); 934 size = elf_get_size(e, sh, SH_SIZE); 935 name = elf_get_word(e, sh, SH_NAME); 936 v = (char *)e + offset; 937 fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name); 938 for (i = 0; (u_int64_t)i < size / entsize; i++) { 939 ra = (char *)v + i * entsize; 940 offset = elf_get_addr(e, ra, RA_OFFSET); 941 info = elf_get_word(e, ra, RA_INFO); 942 addend = elf_get_off(e, ra, RA_ADDEND); 943 fprintf(out, "\n"); 944 fprintf(out, "entry: %d\n", i); 945 fprintf(out, "\tr_offset: %#jx\n", offset); 946 fprintf(out, "\tr_info: %jd\n", (intmax_t)info); 947 fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend); 948 } 949 } 950 951 static void 952 elf_print_rel(Elf32_Ehdr *e, void *sh) 953 { 954 u_int64_t offset; 955 u_int64_t entsize; 956 u_int64_t size; 957 u_int64_t name; 958 u_int64_t info; 959 void *r; 960 void *v; 961 int i; 962 963 offset = elf_get_off(e, sh, SH_OFFSET); 964 entsize = elf_get_size(e, sh, SH_ENTSIZE); 965 size = elf_get_size(e, sh, SH_SIZE); 966 name = elf_get_word(e, sh, SH_NAME); 967 v = (char *)e + offset; 968 fprintf(out, "\nrelocation (%s):\n", shstrtab + name); 969 for (i = 0; (u_int64_t)i < size / entsize; i++) { 970 r = (char *)v + i * entsize; 971 offset = elf_get_addr(e, r, R_OFFSET); 972 info = elf_get_word(e, r, R_INFO); 973 fprintf(out, "\n"); 974 fprintf(out, "entry: %d\n", i); 975 fprintf(out, "\tr_offset: %#jx\n", offset); 976 fprintf(out, "\tr_info: %jd\n", (intmax_t)info); 977 } 978 } 979 980 static void 981 elf_print_interp(Elf32_Ehdr *e, void *p) 982 { 983 u_int64_t offset; 984 char *s; 985 986 offset = elf_get_off(e, p, P_OFFSET); 987 s = (char *)e + offset; 988 fprintf(out, "\ninterp:\n"); 989 fprintf(out, "\t%s\n", s); 990 } 991 992 static void 993 elf_print_got(Elf32_Ehdr *e, void *sh) 994 { 995 u_int64_t offset; 996 u_int64_t addralign; 997 u_int64_t size; 998 u_int64_t addr; 999 void *v; 1000 int i; 1001 1002 offset = elf_get_off(e, sh, SH_OFFSET); 1003 addralign = elf_get_size(e, sh, SH_ADDRALIGN); 1004 size = elf_get_size(e, sh, SH_SIZE); 1005 v = (char *)e + offset; 1006 fprintf(out, "\nglobal offset table:\n"); 1007 for (i = 0; (u_int64_t)i < size / addralign; i++) { 1008 addr = elf_get_addr(e, (char *)v + i * addralign, 0); 1009 fprintf(out, "\n"); 1010 fprintf(out, "entry: %d\n", i); 1011 fprintf(out, "\t%#jx\n", addr); 1012 } 1013 } 1014 1015 static void 1016 elf_print_hash(Elf32_Ehdr *e __unused, void *sh __unused) 1017 { 1018 } 1019 1020 static void 1021 elf_print_note(Elf32_Ehdr *e, void *sh) 1022 { 1023 u_int64_t offset; 1024 u_int64_t size; 1025 u_int64_t name; 1026 u_int32_t namesz; 1027 u_int32_t descsz; 1028 u_int32_t desc; 1029 char *n, *s; 1030 1031 offset = elf_get_off(e, sh, SH_OFFSET); 1032 size = elf_get_size(e, sh, SH_SIZE); 1033 name = elf_get_word(e, sh, SH_NAME); 1034 n = (char *)e + offset; 1035 fprintf(out, "\nnote (%s):\n", shstrtab + name); 1036 while (n < ((char *)e + offset + size)) { 1037 namesz = elf_get_word(e, n, N_NAMESZ); 1038 descsz = elf_get_word(e, n, N_DESCSZ); 1039 s = n + sizeof(Elf_Note); 1040 desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0); 1041 fprintf(out, "\t%s %d\n", s, desc); 1042 n += sizeof(Elf_Note) + namesz + descsz; 1043 } 1044 } 1045 1046 static u_int64_t 1047 elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member) 1048 { 1049 u_int64_t val; 1050 1051 val = 0; 1052 switch (e->e_ident[EI_CLASS]) { 1053 case ELFCLASS32: 1054 val = ((uint8_t *)base)[elf32_offsets[member]]; 1055 break; 1056 case ELFCLASS64: 1057 val = ((uint8_t *)base)[elf64_offsets[member]]; 1058 break; 1059 case ELFCLASSNONE: 1060 errx(1, "invalid class"); 1061 } 1062 1063 return val; 1064 } 1065 1066 static u_int64_t 1067 elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member) 1068 { 1069 u_int64_t val; 1070 1071 val = 0; 1072 switch (e->e_ident[EI_CLASS]) { 1073 case ELFCLASS32: 1074 base = (char *)base + elf32_offsets[member]; 1075 switch (e->e_ident[EI_DATA]) { 1076 case ELFDATA2MSB: 1077 val = be16dec(base); 1078 break; 1079 case ELFDATA2LSB: 1080 val = le16dec(base); 1081 break; 1082 case ELFDATANONE: 1083 errx(1, "invalid data format"); 1084 } 1085 break; 1086 case ELFCLASS64: 1087 base = (char *)base + elf64_offsets[member]; 1088 switch (e->e_ident[EI_DATA]) { 1089 case ELFDATA2MSB: 1090 val = be16dec(base); 1091 break; 1092 case ELFDATA2LSB: 1093 val = le16dec(base); 1094 break; 1095 case ELFDATANONE: 1096 errx(1, "invalid data format"); 1097 } 1098 break; 1099 case ELFCLASSNONE: 1100 errx(1, "invalid class"); 1101 } 1102 1103 return val; 1104 } 1105 1106 #if 0 1107 static u_int64_t 1108 elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member) 1109 { 1110 u_int64_t val; 1111 1112 val = 0; 1113 switch (e->e_ident[EI_CLASS]) { 1114 case ELFCLASS32: 1115 base = (char *)base + elf32_offsets[member]; 1116 switch (e->e_ident[EI_DATA]) { 1117 case ELFDATA2MSB: 1118 val = be16dec(base); 1119 break; 1120 case ELFDATA2LSB: 1121 val = le16dec(base); 1122 break; 1123 case ELFDATANONE: 1124 errx(1, "invalid data format"); 1125 } 1126 break; 1127 case ELFCLASS64: 1128 base = (char *)base + elf64_offsets[member]; 1129 switch (e->e_ident[EI_DATA]) { 1130 case ELFDATA2MSB: 1131 val = be32dec(base); 1132 break; 1133 case ELFDATA2LSB: 1134 val = le32dec(base); 1135 break; 1136 case ELFDATANONE: 1137 errx(1, "invalid data format"); 1138 } 1139 break; 1140 case ELFCLASSNONE: 1141 errx(1, "invalid class"); 1142 } 1143 1144 return val; 1145 } 1146 #endif 1147 1148 static u_int64_t 1149 elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member) 1150 { 1151 u_int64_t val; 1152 1153 val = 0; 1154 switch (e->e_ident[EI_CLASS]) { 1155 case ELFCLASS32: 1156 base = (char *)base + elf32_offsets[member]; 1157 switch (e->e_ident[EI_DATA]) { 1158 case ELFDATA2MSB: 1159 val = be32dec(base); 1160 break; 1161 case ELFDATA2LSB: 1162 val = le32dec(base); 1163 break; 1164 case ELFDATANONE: 1165 errx(1, "invalid data format"); 1166 } 1167 break; 1168 case ELFCLASS64: 1169 base = (char *)base + elf64_offsets[member]; 1170 switch (e->e_ident[EI_DATA]) { 1171 case ELFDATA2MSB: 1172 val = be32dec(base); 1173 break; 1174 case ELFDATA2LSB: 1175 val = le32dec(base); 1176 break; 1177 case ELFDATANONE: 1178 errx(1, "invalid data format"); 1179 } 1180 break; 1181 case ELFCLASSNONE: 1182 errx(1, "invalid class"); 1183 } 1184 1185 return val; 1186 } 1187 1188 static u_int64_t 1189 elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member) 1190 { 1191 u_int64_t val; 1192 1193 val = 0; 1194 switch (e->e_ident[EI_CLASS]) { 1195 case ELFCLASS32: 1196 base = (char *)base + elf32_offsets[member]; 1197 switch (e->e_ident[EI_DATA]) { 1198 case ELFDATA2MSB: 1199 val = be32dec(base); 1200 break; 1201 case ELFDATA2LSB: 1202 val = le32dec(base); 1203 break; 1204 case ELFDATANONE: 1205 errx(1, "invalid data format"); 1206 } 1207 break; 1208 case ELFCLASS64: 1209 base = (char *)base + elf64_offsets[member]; 1210 switch (e->e_ident[EI_DATA]) { 1211 case ELFDATA2MSB: 1212 val = be64dec(base); 1213 break; 1214 case ELFDATA2LSB: 1215 val = le64dec(base); 1216 break; 1217 case ELFDATANONE: 1218 errx(1, "invalid data format"); 1219 } 1220 break; 1221 case ELFCLASSNONE: 1222 errx(1, "invalid class"); 1223 } 1224 1225 return val; 1226 } 1227 1228 static void 1229 usage(void) 1230 { 1231 fprintf(stderr, "usage: elfdump -a | -cdeGhinprs [-w file] file\n"); 1232 exit(1); 1233 } 1234