1 /*- 2 * Copyright (c) 2001 Jake Burkholder 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/types.h> 31 #include <sys/elf32.h> 32 #include <sys/elf64.h> 33 #include <sys/mman.h> 34 #include <sys/stat.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <stddef.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #define ED_DYN (1<<0) 44 #define ED_EHDR (1<<1) 45 #define ED_GOT (1<<2) 46 #define ED_HASH (1<<3) 47 #define ED_INTERP (1<<4) 48 #define ED_NOTE (1<<5) 49 #define ED_PHDR (1<<6) 50 #define ED_REL (1<<7) 51 #define ED_SHDR (1<<8) 52 #define ED_SYMTAB (1<<9) 53 #define ED_ALL ((1<<10)-1) 54 55 #define elf_get_addr elf_get_quad 56 #define elf_get_off elf_get_quad 57 #define elf_get_size elf_get_quad 58 59 enum elf_member { 60 D_TAG = 1, D_PTR, D_VAL, 61 62 E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY, 63 E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE, 64 E_SHNUM, E_SHSTRNDX, 65 66 N_NAMESZ, N_DESCSZ, N_TYPE, 67 68 P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS, 69 P_ALIGN, 70 71 SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK, 72 SH_INFO, SH_ADDRALIGN, SH_ENTSIZE, 73 74 ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX, 75 76 R_OFFSET, R_INFO, 77 78 RA_OFFSET, RA_INFO, RA_ADDEND 79 }; 80 81 typedef enum elf_member elf_member_t; 82 83 int elf32_offsets[] = { 84 0, 85 86 offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr), 87 offsetof(Elf32_Dyn, d_un.d_val), 88 89 offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 90 offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 91 offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 92 offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine), 93 offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry), 94 offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff), 95 offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize), 96 offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum), 97 offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum), 98 offsetof(Elf32_Ehdr, e_shstrndx), 99 100 offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 101 offsetof(Elf_Note, n_type), 102 103 offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset), 104 offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr), 105 offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz), 106 offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align), 107 108 offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type), 109 offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr), 110 offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size), 111 offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info), 112 offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize), 113 114 offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value), 115 offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info), 116 offsetof(Elf32_Sym, st_shndx), 117 118 offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info), 119 120 offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info), 121 offsetof(Elf32_Rela, r_addend) 122 }; 123 124 int elf64_offsets[] = { 125 0, 126 127 offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr), 128 offsetof(Elf64_Dyn, d_un.d_val), 129 130 offsetof(Elf32_Ehdr, e_ident[EI_CLASS]), 131 offsetof(Elf32_Ehdr, e_ident[EI_DATA]), 132 offsetof(Elf32_Ehdr, e_ident[EI_OSABI]), 133 offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine), 134 offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry), 135 offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff), 136 offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize), 137 offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum), 138 offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum), 139 offsetof(Elf64_Ehdr, e_shstrndx), 140 141 offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz), 142 offsetof(Elf_Note, n_type), 143 144 offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset), 145 offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr), 146 offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz), 147 offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align), 148 149 offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type), 150 offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr), 151 offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size), 152 offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info), 153 offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize), 154 155 offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value), 156 offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info), 157 offsetof(Elf64_Sym, st_shndx), 158 159 offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info), 160 161 offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info), 162 offsetof(Elf64_Rela, r_addend) 163 }; 164 165 char *d_tags[] = { 166 "DT_NULL", "DT_NEEDED", "DT_PLTRELSZ", "DT_PLTGOT", "DT_HASH", 167 "DT_STRTAB", "DT_SYMTAB", "DT_RELA", "DT_RELASZ", "DT_RELAENT", 168 "DT_STRSZ", "DT_SYMENT", "DT_INIT", "DT_FINI", "DT_SONAME", 169 "DT_RPATH", "DT_SYMBOLIC", "DT_REL", "DT_RELSZ", "DT_RELENT", 170 "DT_PLTREL", "DT_DEBUG", "DT_TEXTREL", "DT_JMPREL" 171 }; 172 173 char *e_machines[] = { 174 "EM_NONE", "EM_M32", "EM_SPARC", "EM_386", "EM_68K", "EM_88K", 175 "EM_486", "EM_860", "EM_MIPS" 176 }; 177 178 char *e_types[] = { 179 "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 180 }; 181 182 char *ei_versions[] = { 183 "EV_NONE", "EV_CURRENT" 184 }; 185 186 char *ei_classes[] = { 187 "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 188 }; 189 190 char *ei_data[] = { 191 "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 192 }; 193 194 char *ei_abis[] = { 195 "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 196 "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", 197 "ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", 198 "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD" 199 }; 200 201 char *p_types[] = { 202 "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 203 "PT_SHLIB", "PT_PHDR" 204 }; 205 206 char *p_flags[] = { 207 "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 208 "PF_X|PF_W|PF_R" 209 }; 210 211 char *sh_types[] = { 212 "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB", 213 "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE", "SHT_NOBITS", 214 "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM" 215 }; 216 217 char *sh_flags[] = { 218 "", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR", 219 "SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR", 220 "SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR" 221 }; 222 223 char *st_types[] = { 224 "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE" 225 }; 226 227 char *st_bindings[] = { 228 "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 229 }; 230 231 char *dynstr; 232 char *shstrtab; 233 char *strtab; 234 FILE *out; 235 236 u_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member); 237 u_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member); 238 u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member); 239 u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member); 240 u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member); 241 242 void elf_print_ehdr(void *e); 243 void elf_print_phdr(void *e, void *p); 244 void elf_print_shdr(void *e, void *sh); 245 void elf_print_symtab(void *e, void *sh, char *str); 246 void elf_print_dynamic(void *e, void *sh); 247 void elf_print_rel(void *e, void *r); 248 void elf_print_rela(void *e, void *ra); 249 void elf_print_interp(void *e, void *p); 250 void elf_print_got(void *e, void *sh); 251 void elf_print_hash(void *e, void *sh); 252 void elf_print_note(void *e, void *sh); 253 254 void usage(void); 255 256 int 257 main(int ac, char **av) 258 { 259 u_int64_t phoff; 260 u_int64_t shoff; 261 u_int64_t phentsize; 262 u_int64_t phnum; 263 u_int64_t shentsize; 264 u_int64_t shnum; 265 u_int64_t shstrndx; 266 u_int64_t offset; 267 u_int64_t name; 268 u_int64_t type; 269 struct stat sb; 270 u_int flags; 271 void *e; 272 void *p; 273 void *sh; 274 void *v; 275 int fd; 276 int ch; 277 int i; 278 279 out = stdout; 280 flags = 0; 281 while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1) 282 switch (ch) { 283 case 'a': 284 flags = ED_ALL; 285 break; 286 case 'c': 287 flags |= ED_SHDR; 288 break; 289 case 'd': 290 flags |= ED_DYN; 291 break; 292 case 'e': 293 flags |= ED_EHDR; 294 break; 295 case 'i': 296 flags |= ED_INTERP; 297 break; 298 case 'G': 299 flags |= ED_GOT; 300 break; 301 case 'h': 302 flags |= ED_HASH; 303 break; 304 case 'n': 305 flags |= ED_NOTE; 306 break; 307 case 'p': 308 flags |= ED_PHDR; 309 break; 310 case 'r': 311 flags |= ED_REL; 312 break; 313 case 's': 314 flags |= ED_SYMTAB; 315 break; 316 case 'w': 317 if ((out = fopen(optarg, "w")) == NULL) 318 err(1, "%s", optarg); 319 break; 320 case '?': 321 default: 322 usage(); 323 } 324 ac -= optind; 325 av += optind; 326 if (ac == 0 || flags == 0) 327 usage(); 328 if ((fd = open(*av, O_RDONLY)) < 0 || 329 fstat(fd, &sb) < 0) 330 err(1, NULL); 331 e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 332 if (e == MAP_FAILED) 333 err(1, NULL); 334 if (!IS_ELF(*(Elf32_Ehdr *)e)) 335 errx(1, "not an elf file"); 336 phoff = elf_get_off(e, e, E_PHOFF); 337 shoff = elf_get_off(e, e, E_SHOFF); 338 phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 339 phnum = elf_get_quarter(e, e, E_PHNUM); 340 shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 341 shnum = elf_get_quarter(e, e, E_SHNUM); 342 shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 343 p = e + phoff; 344 sh = e + shoff; 345 offset = elf_get_off(e, sh + shstrndx * shentsize, SH_OFFSET); 346 shstrtab = e + offset; 347 for (i = 0; i < shnum; i++) { 348 name = elf_get_word(e, sh + i * shentsize, SH_NAME); 349 offset = elf_get_off(e, sh + i * shentsize, SH_OFFSET); 350 if (strcmp(shstrtab + name, ".strtab") == 0) 351 strtab = e + offset; 352 if (strcmp(shstrtab + name, ".dynstr") == 0) 353 dynstr = e + offset; 354 } 355 if (flags & ED_EHDR) 356 elf_print_ehdr(e); 357 if (flags & ED_PHDR) 358 elf_print_phdr(e, p); 359 if (flags & ED_SHDR) 360 elf_print_shdr(e, sh); 361 for (i = 0; i < phnum; i++) { 362 v = p + i * phentsize; 363 type = elf_get_word(e, v, P_TYPE); 364 switch (type) { 365 case PT_INTERP: 366 if (flags & ED_INTERP) 367 elf_print_interp(e, v); 368 break; 369 case PT_NULL: 370 case PT_LOAD: 371 case PT_DYNAMIC: 372 case PT_NOTE: 373 case PT_SHLIB: 374 case PT_PHDR: 375 break; 376 } 377 } 378 for (i = 0; i < shnum; i++) { 379 v = sh + i * shentsize; 380 type = elf_get_word(e, v, SH_TYPE); 381 switch (type) { 382 case SHT_SYMTAB: 383 if (flags & ED_SYMTAB) 384 elf_print_symtab(e, v, strtab); 385 break; 386 case SHT_DYNAMIC: 387 if (flags & ED_DYN) 388 elf_print_dynamic(e, v); 389 break; 390 case SHT_RELA: 391 if (flags & ED_REL) 392 elf_print_rela(e, v); 393 break; 394 case SHT_REL: 395 if (flags & ED_REL) 396 elf_print_rel(e, v); 397 break; 398 case SHT_NOTE: 399 name = elf_get_word(e, v, SH_NAME); 400 if (flags & ED_NOTE && 401 strcmp(shstrtab + name, ".note.ABI-tag") == 0) 402 elf_print_note(e, v); 403 break; 404 case SHT_DYNSYM: 405 if (flags & ED_SYMTAB) 406 elf_print_symtab(e, v, dynstr); 407 break; 408 case SHT_PROGBITS: 409 name = elf_get_word(e, v, SH_NAME); 410 if (flags & ED_GOT && 411 strcmp(shstrtab + name, ".got") == 0) 412 elf_print_got(e, v); 413 break; 414 case SHT_HASH: 415 if (flags & ED_HASH) 416 elf_print_hash(e, v); 417 break; 418 case SHT_NULL: 419 case SHT_STRTAB: 420 case SHT_NOBITS: 421 case SHT_SHLIB: 422 break; 423 } 424 } 425 426 return 0; 427 } 428 429 void 430 elf_print_ehdr(void *e) 431 { 432 u_int64_t class; 433 u_int64_t data; 434 u_int64_t osabi; 435 u_int64_t type; 436 u_int64_t machine; 437 u_int64_t version; 438 u_int64_t entry; 439 u_int64_t phoff; 440 u_int64_t shoff; 441 u_int64_t flags; 442 u_int64_t ehsize; 443 u_int64_t phentsize; 444 u_int64_t phnum; 445 u_int64_t shentsize; 446 u_int64_t shnum; 447 u_int64_t shstrndx; 448 449 class = elf_get_byte(e, e, E_CLASS); 450 data = elf_get_byte(e, e, E_DATA); 451 osabi = elf_get_byte(e, e, E_OSABI); 452 type = elf_get_quarter(e, e, E_TYPE); 453 machine = elf_get_quarter(e, e, E_MACHINE); 454 version = elf_get_word(e, e, E_VERSION); 455 entry = elf_get_addr(e, e, E_ENTRY); 456 phoff = elf_get_off(e, e, E_PHOFF); 457 shoff = elf_get_off(e, e, E_SHOFF); 458 flags = elf_get_word(e, e, E_FLAGS); 459 ehsize = elf_get_quarter(e, e, E_EHSIZE); 460 phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 461 phnum = elf_get_quarter(e, e, E_PHNUM); 462 shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 463 shnum = elf_get_quarter(e, e, E_SHNUM); 464 shstrndx = elf_get_quarter(e, e, E_SHSTRNDX); 465 fprintf(out, "\nelf header:\n"); 466 fprintf(out, "\n"); 467 fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data], 468 ei_abis[osabi]); 469 fprintf(out, "\te_type: %s\n", e_types[type]); 470 if (machine < sizeof e_machines / sizeof *e_machines) 471 fprintf(out, "\te_machine: %s\n", e_machines[machine]); 472 else 473 fprintf(out, "\te_machine: %lld\n", machine); 474 fprintf(out, "\te_version: %s\n", ei_versions[version]); 475 fprintf(out, "\te_entry: %#llx\n", entry); 476 fprintf(out, "\te_phoff: %lld\n", phoff); 477 fprintf(out, "\te_shoff: %lld\n", shoff); 478 fprintf(out, "\te_flags: %lld\n", flags); 479 fprintf(out, "\te_ehsize: %lld\n", ehsize); 480 fprintf(out, "\te_phentsize: %lld\n", phentsize); 481 fprintf(out, "\te_phnum: %lld\n", phnum); 482 fprintf(out, "\te_shentsize: %lld\n", shentsize); 483 fprintf(out, "\te_shnum: %lld\n", shnum); 484 fprintf(out, "\te_shstrndx: %lld\n", shstrndx); 485 } 486 487 void 488 elf_print_phdr(void *e, void *p) 489 { 490 u_int64_t phentsize; 491 u_int64_t phnum; 492 u_int64_t type; 493 u_int64_t offset; 494 u_int64_t vaddr; 495 u_int64_t paddr; 496 u_int64_t filesz; 497 u_int64_t memsz; 498 u_int64_t flags; 499 u_int64_t align; 500 void *v; 501 int i; 502 503 phentsize = elf_get_quarter(e, e, E_PHENTSIZE); 504 phnum = elf_get_quarter(e, e, E_PHNUM); 505 fprintf(out, "\nprogram header:\n"); 506 for (i = 0; i < phnum; i++) { 507 v = p + i * phentsize; 508 type = elf_get_word(e, v, P_TYPE); 509 offset = elf_get_off(e, v, P_OFFSET); 510 vaddr = elf_get_addr(e, v, P_VADDR); 511 paddr = elf_get_addr(e, v, P_PADDR); 512 filesz = elf_get_size(e, v, P_FILESZ); 513 memsz = elf_get_size(e, v, P_MEMSZ); 514 flags = elf_get_word(e, v, P_FLAGS); 515 align = elf_get_size(e, v, P_ALIGN); 516 fprintf(out, "\n"); 517 fprintf(out, "entry: %d\n", i); 518 fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]); 519 fprintf(out, "\tp_offset: %lld\n", offset); 520 fprintf(out, "\tp_vaddr: %#llx\n", vaddr); 521 fprintf(out, "\tp_paddr: %#llx\n", paddr); 522 fprintf(out, "\tp_filesz: %lld\n", filesz); 523 fprintf(out, "\tp_memsz: %lld\n", memsz); 524 fprintf(out, "\tp_flags: %s\n", p_flags[flags]); 525 fprintf(out, "\tp_align: %lld\n", align); 526 } 527 } 528 529 void 530 elf_print_shdr(void *e, void *sh) 531 { 532 u_int64_t shentsize; 533 u_int64_t shnum; 534 u_int64_t name; 535 u_int64_t type; 536 u_int64_t flags; 537 u_int64_t addr; 538 u_int64_t offset; 539 u_int64_t size; 540 u_int64_t link; 541 u_int64_t info; 542 u_int64_t addralign; 543 u_int64_t entsize; 544 void *v; 545 int i; 546 547 shentsize = elf_get_quarter(e, e, E_SHENTSIZE); 548 shnum = elf_get_quarter(e, e, E_SHNUM); 549 fprintf(out, "\nsection header:\n"); 550 for (i = 0; i < shnum; i++) { 551 v = sh + i * shentsize; 552 name = elf_get_word(e, v, SH_NAME); 553 type = elf_get_word(e, v, SH_TYPE); 554 flags = elf_get_word(e, v, SH_FLAGS); 555 addr = elf_get_addr(e, v, SH_ADDR); 556 offset = elf_get_off(e, v, SH_OFFSET); 557 size = elf_get_size(e, v, SH_SIZE); 558 link = elf_get_word(e, v, SH_LINK); 559 info = elf_get_word(e, v, SH_INFO); 560 addralign = elf_get_size(e, v, SH_ADDRALIGN); 561 entsize = elf_get_size(e, v, SH_ENTSIZE); 562 fprintf(out, "\n"); 563 fprintf(out, "entry: %d\n", i); 564 fprintf(out, "\tsh_name: %s\n", shstrtab + name); 565 fprintf(out, "\tsh_type: %s\n", sh_types[type]); 566 fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]); 567 fprintf(out, "\tsh_addr: %#llx\n", addr); 568 fprintf(out, "\tsh_offset: %lld\n", offset); 569 fprintf(out, "\tsh_size: %lld\n", size); 570 fprintf(out, "\tsh_link: %lld\n", link); 571 fprintf(out, "\tsh_info: %lld\n", info); 572 fprintf(out, "\tsh_addralign: %lld\n", addralign); 573 fprintf(out, "\tsh_entsize: %lld\n", entsize); 574 } 575 } 576 577 void 578 elf_print_symtab(void *e, void *sh, char *str) 579 { 580 u_int64_t offset; 581 u_int64_t entsize; 582 u_int64_t size; 583 u_int64_t name; 584 u_int64_t value; 585 u_int64_t info; 586 u_int64_t shndx; 587 void *st; 588 int len; 589 int i; 590 591 offset = elf_get_off(e, sh, SH_OFFSET); 592 entsize = elf_get_size(e, sh, SH_ENTSIZE); 593 size = elf_get_size(e, sh, SH_SIZE); 594 name = elf_get_word(e, sh, SH_NAME); 595 len = size / entsize; 596 fprintf(out, "\nsymbol table (%s):\n", shstrtab + name); 597 for (i = 0; i < len; i++) { 598 st = e + offset + i * entsize; 599 name = elf_get_word(e, st, ST_NAME); 600 value = elf_get_addr(e, st, ST_VALUE); 601 size = elf_get_size(e, st, ST_SIZE); 602 info = elf_get_byte(e, st, ST_INFO); 603 shndx = elf_get_quarter(e, st, ST_SHNDX); 604 fprintf(out, "\n"); 605 fprintf(out, "entry: %d\n", i); 606 fprintf(out, "\tst_name: %s\n", str + name); 607 fprintf(out, "\tst_value: %#llx\n", value); 608 fprintf(out, "\tst_size: %lld\n", size); 609 fprintf(out, "\tst_info: %s %s\n", 610 st_types[ELF32_ST_TYPE(info)], 611 st_bindings[ELF32_ST_BIND(info)]); 612 fprintf(out, "\tst_shndx: %lld\n", shndx); 613 } 614 } 615 616 void 617 elf_print_dynamic(void *e, void *sh) 618 { 619 u_int64_t offset; 620 u_int64_t entsize; 621 u_int64_t size; 622 int64_t tag; 623 u_int64_t ptr; 624 u_int64_t val; 625 void *d; 626 int i; 627 628 offset = elf_get_off(e, sh, SH_OFFSET); 629 entsize = elf_get_size(e, sh, SH_ENTSIZE); 630 size = elf_get_size(e, sh, SH_SIZE); 631 fprintf(out, "\ndynamic:\n"); 632 for (i = 0; i < size / entsize; i++) { 633 d = e + offset + i * entsize; 634 tag = elf_get_size(e, d, D_TAG); 635 ptr = elf_get_size(e, d, D_PTR); 636 val = elf_get_addr(e, d, D_VAL); 637 fprintf(out, "\n"); 638 fprintf(out, "entry: %d\n", i); 639 fprintf(out, "\td_tag: %s\n", d_tags[tag]); 640 switch (tag) { 641 case DT_NEEDED: 642 case DT_SONAME: 643 case DT_RPATH: 644 fprintf(out, "\td_val: %s\n", dynstr + val); 645 break; 646 case DT_PLTRELSZ: 647 case DT_RELA: 648 case DT_RELASZ: 649 case DT_RELAENT: 650 case DT_STRSZ: 651 case DT_SYMENT: 652 case DT_RELSZ: 653 case DT_RELENT: 654 case DT_PLTREL: 655 fprintf(out, "\td_val: %lld\n", val); 656 break; 657 case DT_PLTGOT: 658 case DT_HASH: 659 case DT_STRTAB: 660 case DT_SYMTAB: 661 case DT_INIT: 662 case DT_FINI: 663 case DT_REL: 664 case DT_JMPREL: 665 fprintf(out, "\td_ptr: %#llx\n", ptr); 666 break; 667 case DT_NULL: 668 case DT_SYMBOLIC: 669 case DT_DEBUG: 670 case DT_TEXTREL: 671 break; 672 } 673 } 674 } 675 676 void 677 elf_print_rela(void *e, void *sh) 678 { 679 u_int64_t offset; 680 u_int64_t entsize; 681 u_int64_t size; 682 u_int64_t name; 683 u_int64_t info; 684 int64_t addend; 685 void *ra; 686 void *v; 687 int i; 688 689 offset = elf_get_off(e, sh, SH_OFFSET); 690 entsize = elf_get_size(e, sh, SH_ENTSIZE); 691 size = elf_get_size(e, sh, SH_SIZE); 692 name = elf_get_word(e, sh, SH_NAME); 693 v = e + offset; 694 fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name); 695 for (i = 0; i < size / entsize; i++) { 696 ra = v + i * entsize; 697 offset = elf_get_addr(e, ra, RA_OFFSET); 698 info = elf_get_word(e, ra, RA_INFO); 699 addend = elf_get_off(e, ra, RA_ADDEND); 700 fprintf(out, "\n"); 701 fprintf(out, "entry: %d\n", i); 702 fprintf(out, "\tr_offset: %#llx\n", offset); 703 fprintf(out, "\tr_info: %lld\n", info); 704 fprintf(out, "\tr_addend: %lld\n", addend); 705 } 706 } 707 708 void 709 elf_print_rel(void *e, void *sh) 710 { 711 u_int64_t offset; 712 u_int64_t entsize; 713 u_int64_t size; 714 u_int64_t name; 715 u_int64_t info; 716 void *r; 717 void *v; 718 int i; 719 720 offset = elf_get_off(e, sh, SH_OFFSET); 721 entsize = elf_get_size(e, sh, SH_ENTSIZE); 722 size = elf_get_size(e, sh, SH_SIZE); 723 name = elf_get_word(e, sh, SH_NAME); 724 v = e + offset; 725 fprintf(out, "\nrelocation (%s):\n", shstrtab + name); 726 for (i = 0; i < size / entsize; i++) { 727 r = v + i * entsize; 728 offset = elf_get_addr(e, r, R_OFFSET); 729 info = elf_get_word(e, r, R_INFO); 730 fprintf(out, "\n"); 731 fprintf(out, "entry: %d\n", i); 732 fprintf(out, "\tr_offset: %#llx\n", offset); 733 fprintf(out, "\tr_info: %lld\n", info); 734 } 735 } 736 737 void 738 elf_print_interp(void *e, void *p) 739 { 740 u_int64_t offset; 741 char *s; 742 743 offset = elf_get_off(e, p, P_OFFSET); 744 s = e + offset; 745 fprintf(out, "\ninterp:\n"); 746 fprintf(out, "\t%s\n", s); 747 } 748 749 void 750 elf_print_got(void *e, void *sh) 751 { 752 u_int64_t offset; 753 u_int64_t addralign; 754 u_int64_t size; 755 u_int64_t addr; 756 void *v; 757 int i; 758 759 offset = elf_get_off(e, sh, SH_OFFSET); 760 addralign = elf_get_size(e, sh, SH_ADDRALIGN); 761 size = elf_get_size(e, sh, SH_SIZE); 762 v = e + offset; 763 fprintf(out, "\nglobal offset table:\n"); 764 for (i = 0; i < size / addralign; i++) { 765 addr = elf_get_addr(e, v + i * addralign, 0); 766 fprintf(out, "\n"); 767 fprintf(out, "entry: %d\n", i); 768 fprintf(out, "\t%#llx\n", addr); 769 } 770 } 771 772 void 773 elf_print_hash(void *e, void *sh) 774 { 775 } 776 777 void 778 elf_print_note(void *e, void *sh) 779 { 780 u_int64_t offset; 781 u_int64_t size; 782 u_int64_t name; 783 u_int32_t namesz; 784 u_int32_t descsz; 785 u_int32_t type; 786 u_int32_t desc; 787 char *s; 788 void *n; 789 790 offset = elf_get_off(e, sh, SH_OFFSET); 791 size = elf_get_size(e, sh, SH_SIZE); 792 name = elf_get_word(e, sh, SH_NAME); 793 n = e + offset; 794 fprintf(out, "\nnote (%s):\n", shstrtab + name); 795 while (n < e + offset + size) { 796 namesz = elf_get_word(e, n, N_NAMESZ); 797 descsz = elf_get_word(e, n, N_DESCSZ); 798 type = elf_get_word(e, n, N_TYPE); 799 s = n + sizeof(Elf_Note); 800 desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0); 801 fprintf(out, "\t%s %d\n", s, desc); 802 n += sizeof(Elf_Note) + namesz + descsz; 803 } 804 } 805 806 u_int64_t 807 elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member) 808 { 809 u_int64_t val; 810 u_char *p; 811 812 val = 0; 813 switch (e->e_ident[EI_CLASS]) { 814 case ELFCLASS32: 815 p = base + elf32_offsets[member]; 816 val = *p; 817 break; 818 case ELFCLASS64: 819 p = base + elf64_offsets[member]; 820 val = *p; 821 break; 822 case ELFCLASSNONE: 823 errx(1, "invalid class"); 824 } 825 826 return val; 827 } 828 829 u_int64_t 830 elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member) 831 { 832 u_int64_t val; 833 u_char *p; 834 835 val = 0; 836 switch (e->e_ident[EI_CLASS]) { 837 case ELFCLASS32: 838 p = base + elf32_offsets[member]; 839 switch (e->e_ident[EI_DATA]) { 840 case ELFDATA2MSB: 841 val = p[0] << 8 | p[1]; 842 break; 843 case ELFDATA2LSB: 844 val = p[1] << 8 | p[0]; 845 break; 846 case ELFDATANONE: 847 errx(1, "invalid data format"); 848 } 849 break; 850 case ELFCLASS64: 851 p = base + elf64_offsets[member]; 852 switch (e->e_ident[EI_DATA]) { 853 case ELFDATA2MSB: 854 val = p[0] << 8 | p[1]; 855 break; 856 case ELFDATA2LSB: 857 val = p[1] << 8 | p[0]; 858 break; 859 case ELFDATANONE: 860 errx(1, "invalid data format"); 861 } 862 break; 863 case ELFCLASSNONE: 864 errx(1, "invalid class"); 865 } 866 867 return val; 868 } 869 870 u_int64_t 871 elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member) 872 { 873 u_int64_t val; 874 u_char *p; 875 876 val = 0; 877 switch (e->e_ident[EI_CLASS]) { 878 case ELFCLASS32: 879 p = base + elf32_offsets[member]; 880 switch (e->e_ident[EI_DATA]) { 881 case ELFDATA2MSB: 882 val = p[0] << 8 | p[1]; 883 break; 884 case ELFDATA2LSB: 885 val = p[1] << 8 | p[0]; 886 break; 887 case ELFDATANONE: 888 errx(1, "invalid data format"); 889 } 890 break; 891 case ELFCLASS64: 892 p = base + elf64_offsets[member]; 893 switch (e->e_ident[EI_DATA]) { 894 case ELFDATA2MSB: 895 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 896 break; 897 case ELFDATA2LSB: 898 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 899 break; 900 case ELFDATANONE: 901 errx(1, "invalid data format"); 902 } 903 break; 904 case ELFCLASSNONE: 905 errx(1, "invalid class"); 906 } 907 908 return val; 909 } 910 911 u_int64_t 912 elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member) 913 { 914 u_int64_t val; 915 u_char *p; 916 917 val = 0; 918 switch (e->e_ident[EI_CLASS]) { 919 case ELFCLASS32: 920 p = base + elf32_offsets[member]; 921 switch (e->e_ident[EI_DATA]) { 922 case ELFDATA2MSB: 923 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 924 break; 925 case ELFDATA2LSB: 926 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 927 break; 928 case ELFDATANONE: 929 errx(1, "invalid data format"); 930 } 931 break; 932 case ELFCLASS64: 933 p = base + elf64_offsets[member]; 934 switch (e->e_ident[EI_DATA]) { 935 case ELFDATA2MSB: 936 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 937 break; 938 case ELFDATA2LSB: 939 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 940 break; 941 case ELFDATANONE: 942 errx(1, "invalid data format"); 943 } 944 break; 945 case ELFCLASSNONE: 946 errx(1, "invalid class"); 947 } 948 949 return val; 950 } 951 952 u_int64_t 953 elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member) 954 { 955 u_int64_t high; 956 u_int64_t low; 957 u_int64_t val; 958 u_char *p; 959 960 val = 0; 961 switch (e->e_ident[EI_CLASS]) { 962 case ELFCLASS32: 963 p = base + elf32_offsets[member]; 964 switch (e->e_ident[EI_DATA]) { 965 case ELFDATA2MSB: 966 val = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 967 break; 968 case ELFDATA2LSB: 969 val = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 970 break; 971 case ELFDATANONE: 972 errx(1, "invalid data format"); 973 } 974 break; 975 case ELFCLASS64: 976 p = base + elf64_offsets[member]; 977 switch (e->e_ident[EI_DATA]) { 978 case ELFDATA2MSB: 979 high = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; 980 low = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; 981 val = high << 32 | low; 982 break; 983 case ELFDATA2LSB: 984 high = p[7] << 24 | p[6] << 16 | p[5] << 8 | p[4]; 985 low = p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; 986 val = high << 32 | low; 987 break; 988 case ELFDATANONE: 989 errx(1, "invalid data format"); 990 } 991 break; 992 case ELFCLASSNONE: 993 errx(1, "invalid class"); 994 } 995 996 return val; 997 } 998 999 void 1000 usage(void) 1001 { 1002 fprintf(stderr, "usage: elfdump [-acdeiGhnprs] [-w file] filename\n"); 1003 exit(1); 1004 } 1005