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