1 /*- 2 * Copyright (c) 2007-2012 Kai Wang 3 * Copyright (c) 2003 David O'Brien. All rights reserved. 4 * Copyright (c) 2001 Jake Burkholder 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/queue.h> 31 #include <sys/stat.h> 32 33 #include <ar.h> 34 #include <assert.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <gelf.h> 38 #include <getopt.h> 39 #include <libelftc.h> 40 #include <inttypes.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #ifdef USE_LIBARCHIVE_AR 47 #include <archive.h> 48 #include <archive_entry.h> 49 #endif 50 51 #include "_elftc.h" 52 53 ELFTC_VCSID("$Id: elfdump.c 3198 2015-05-14 18:36:19Z emaste $"); 54 55 #if defined(ELFTC_NEED_ELF_NOTE_DEFINITION) 56 #include "native-elf-format.h" 57 #if ELFTC_CLASS == ELFCLASS32 58 typedef Elf32_Nhdr Elf_Note; 59 #else 60 typedef Elf64_Nhdr Elf_Note; 61 #endif 62 #endif 63 64 /* elfdump(1) options. */ 65 #define ED_DYN (1<<0) 66 #define ED_EHDR (1<<1) 67 #define ED_GOT (1<<2) 68 #define ED_HASH (1<<3) 69 #define ED_INTERP (1<<4) 70 #define ED_NOTE (1<<5) 71 #define ED_PHDR (1<<6) 72 #define ED_REL (1<<7) 73 #define ED_SHDR (1<<8) 74 #define ED_SYMTAB (1<<9) 75 #define ED_SYMVER (1<<10) 76 #define ED_CHECKSUM (1<<11) 77 #define ED_ALL ((1<<12)-1) 78 79 /* elfdump(1) run control flags. */ 80 #define SOLARIS_FMT (1<<0) 81 #define PRINT_FILENAME (1<<1) 82 #define PRINT_ARSYM (1<<2) 83 #define ONLY_ARSYM (1<<3) 84 85 /* Convenient print macro. */ 86 #define PRT(...) fprintf(ed->out, __VA_ARGS__) 87 88 /* Internal data structure for sections. */ 89 struct section { 90 const char *name; /* section name */ 91 Elf_Scn *scn; /* section scn */ 92 uint64_t off; /* section offset */ 93 uint64_t sz; /* section size */ 94 uint64_t entsize; /* section entsize */ 95 uint64_t align; /* section alignment */ 96 uint64_t type; /* section type */ 97 uint64_t flags; /* section flags */ 98 uint64_t addr; /* section virtual addr */ 99 uint32_t link; /* section link ndx */ 100 uint32_t info; /* section info ndx */ 101 }; 102 103 struct spec_name { 104 const char *name; 105 STAILQ_ENTRY(spec_name) sn_list; 106 }; 107 108 /* Structure encapsulates the global data for readelf(1). */ 109 struct elfdump { 110 FILE *out; /* output redirection. */ 111 const char *filename; /* current processing file. */ 112 const char *archive; /* archive name */ 113 int options; /* command line options. */ 114 int flags; /* run control flags. */ 115 Elf *elf; /* underlying ELF descriptor. */ 116 #ifndef USE_LIBARCHIVE_AR 117 Elf *ar; /* ar(1) archive descriptor. */ 118 #endif 119 GElf_Ehdr ehdr; /* ELF header. */ 120 int ec; /* ELF class. */ 121 size_t shnum; /* #sections. */ 122 struct section *sl; /* list of sections. */ 123 STAILQ_HEAD(, spec_name) snl; /* list of names specified by -N. */ 124 }; 125 126 /* Relocation entry. */ 127 struct rel_entry { 128 union { 129 GElf_Rel rel; 130 GElf_Rela rela; 131 } u_r; 132 const char *symn; 133 uint32_t type; 134 }; 135 136 #if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS) 137 static __inline uint32_t 138 be32dec(const void *pp) 139 { 140 unsigned char const *p = (unsigned char const *)pp; 141 142 return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); 143 } 144 145 static __inline uint32_t 146 le32dec(const void *pp) 147 { 148 unsigned char const *p = (unsigned char const *)pp; 149 150 return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); 151 } 152 #endif 153 154 /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */ 155 static const char * 156 d_tags(uint64_t tag) 157 { 158 switch (tag) { 159 case 0: return "DT_NULL"; 160 case 1: return "DT_NEEDED"; 161 case 2: return "DT_PLTRELSZ"; 162 case 3: return "DT_PLTGOT"; 163 case 4: return "DT_HASH"; 164 case 5: return "DT_STRTAB"; 165 case 6: return "DT_SYMTAB"; 166 case 7: return "DT_RELA"; 167 case 8: return "DT_RELASZ"; 168 case 9: return "DT_RELAENT"; 169 case 10: return "DT_STRSZ"; 170 case 11: return "DT_SYMENT"; 171 case 12: return "DT_INIT"; 172 case 13: return "DT_FINI"; 173 case 14: return "DT_SONAME"; 174 case 15: return "DT_RPATH"; 175 case 16: return "DT_SYMBOLIC"; 176 case 17: return "DT_REL"; 177 case 18: return "DT_RELSZ"; 178 case 19: return "DT_RELENT"; 179 case 20: return "DT_PLTREL"; 180 case 21: return "DT_DEBUG"; 181 case 22: return "DT_TEXTREL"; 182 case 23: return "DT_JMPREL"; 183 case 24: return "DT_BIND_NOW"; 184 case 25: return "DT_INIT_ARRAY"; 185 case 26: return "DT_FINI_ARRAY"; 186 case 27: return "DT_INIT_ARRAYSZ"; 187 case 28: return "DT_FINI_ARRAYSZ"; 188 case 29: return "DT_RUNPATH"; 189 case 30: return "DT_FLAGS"; 190 case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */ 191 case 33: return "DT_PREINIT_ARRAYSZ"; 192 /* 0x6000000D - 0x6ffff000 operating system-specific semantics */ 193 case 0x6ffffdf5: return "DT_GNU_PRELINKED"; 194 case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ"; 195 case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ"; 196 case 0x6ffffdf8: return "DT_SUNW_CHECKSUM"; 197 case 0x6ffffdf9: return "DT_PLTPADSZ"; 198 case 0x6ffffdfa: return "DT_MOVEENT"; 199 case 0x6ffffdfb: return "DT_MOVESZ"; 200 case 0x6ffffdfc: return "DT_FEATURE"; 201 case 0x6ffffdfd: return "DT_POSFLAG_1"; 202 case 0x6ffffdfe: return "DT_SYMINSZ"; 203 case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)"; 204 case 0x6ffffe00: return "DT_ADDRRNGLO"; 205 case 0x6ffffef5: return "DT_GNU_HASH"; 206 case 0x6ffffef8: return "DT_GNU_CONFLICT"; 207 case 0x6ffffef9: return "DT_GNU_LIBLIST"; 208 case 0x6ffffefa: return "DT_SUNW_CONFIG"; 209 case 0x6ffffefb: return "DT_SUNW_DEPAUDIT"; 210 case 0x6ffffefc: return "DT_SUNW_AUDIT"; 211 case 0x6ffffefd: return "DT_SUNW_PLTPAD"; 212 case 0x6ffffefe: return "DT_SUNW_MOVETAB"; 213 case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)"; 214 case 0x6ffffff9: return "DT_RELACOUNT"; 215 case 0x6ffffffa: return "DT_RELCOUNT"; 216 case 0x6ffffffb: return "DT_FLAGS_1"; 217 case 0x6ffffffc: return "DT_VERDEF"; 218 case 0x6ffffffd: return "DT_VERDEFNUM"; 219 case 0x6ffffffe: return "DT_VERNEED"; 220 case 0x6fffffff: return "DT_VERNEEDNUM"; 221 case 0x6ffffff0: return "DT_GNU_VERSYM"; 222 /* 0x70000000 - 0x7fffffff processor-specific semantics */ 223 case 0x70000000: return "DT_IA_64_PLT_RESERVE"; 224 case 0x7ffffffd: return "DT_SUNW_AUXILIARY"; 225 case 0x7ffffffe: return "DT_SUNW_USED"; 226 case 0x7fffffff: return "DT_SUNW_FILTER"; 227 default: return "ERROR: TAG NOT DEFINED"; 228 } 229 } 230 231 static const char * 232 e_machines(unsigned int mach) 233 { 234 static char machdesc[64]; 235 236 switch (mach) { 237 case EM_NONE: return "EM_NONE"; 238 case EM_M32: return "EM_M32"; 239 case EM_SPARC: return "EM_SPARC"; 240 case EM_386: return "EM_386"; 241 case EM_68K: return "EM_68K"; 242 case EM_88K: return "EM_88K"; 243 case EM_IAMCU: return "EM_IAMCU"; 244 case EM_860: return "EM_860"; 245 case EM_MIPS: return "EM_MIPS"; 246 case EM_PPC: return "EM_PPC"; 247 case EM_ARM: return "EM_ARM"; 248 case EM_ALPHA: return "EM_ALPHA (legacy)"; 249 case EM_SPARCV9:return "EM_SPARCV9"; 250 case EM_IA_64: return "EM_IA_64"; 251 case EM_X86_64: return "EM_X86_64"; 252 } 253 snprintf(machdesc, sizeof(machdesc), 254 "(unknown machine) -- type 0x%x", mach); 255 return (machdesc); 256 } 257 258 static const char *e_types[] = { 259 "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE" 260 }; 261 262 static const char *ei_versions[] = { 263 "EV_NONE", "EV_CURRENT" 264 }; 265 266 static const char *ei_classes[] = { 267 "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64" 268 }; 269 270 static const char *ei_data[] = { 271 "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB" 272 }; 273 274 static const char *ei_abis[] = { 275 "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX", 276 "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", 277 "ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", 278 "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD" 279 }; 280 281 static const char *p_types[] = { 282 "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE", 283 "PT_SHLIB", "PT_PHDR", "PT_TLS" 284 }; 285 286 static const char *p_flags[] = { 287 "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R", 288 "PF_X|PF_W|PF_R" 289 }; 290 291 static const char * 292 sh_name(struct elfdump *ed, int ndx) 293 { 294 static char num[10]; 295 296 switch (ndx) { 297 case SHN_UNDEF: return "UNDEF"; 298 case SHN_ABS: return "ABS"; 299 case SHN_COMMON: return "COMMON"; 300 default: 301 if ((uint64_t)ndx < ed->shnum) 302 return (ed->sl[ndx].name); 303 else { 304 snprintf(num, sizeof(num), "%d", ndx); 305 return (num); 306 } 307 } 308 } 309 310 /* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */ 311 static const char * 312 sh_types(u_int64_t sht) { 313 switch (sht) { 314 case 0: return "SHT_NULL"; 315 case 1: return "SHT_PROGBITS"; 316 case 2: return "SHT_SYMTAB"; 317 case 3: return "SHT_STRTAB"; 318 case 4: return "SHT_RELA"; 319 case 5: return "SHT_HASH"; 320 case 6: return "SHT_DYNAMIC"; 321 case 7: return "SHT_NOTE"; 322 case 8: return "SHT_NOBITS"; 323 case 9: return "SHT_REL"; 324 case 10: return "SHT_SHLIB"; 325 case 11: return "SHT_DYNSYM"; 326 case 14: return "SHT_INIT_ARRAY"; 327 case 15: return "SHT_FINI_ARRAY"; 328 case 16: return "SHT_PREINIT_ARRAY"; 329 case 17: return "SHT_GROUP"; 330 case 18: return "SHT_SYMTAB_SHNDX"; 331 /* 0x60000000 - 0x6fffffff operating system-specific semantics */ 332 case 0x6ffffff0: return "XXX:VERSYM"; 333 case 0x6ffffff6: return "SHT_GNU_HASH"; 334 case 0x6ffffff7: return "SHT_GNU_LIBLIST"; 335 case 0x6ffffffc: return "XXX:VERDEF"; 336 case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef"; 337 case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed"; 338 case 0x6fffffff: return "SHT_SUNW(GNU)_versym"; 339 /* 0x70000000 - 0x7fffffff processor-specific semantics */ 340 case 0x70000000: return "SHT_IA_64_EXT"; 341 case 0x70000001: return "SHT_IA_64_UNWIND"; 342 case 0x7ffffffd: return "XXX:AUXILIARY"; 343 case 0x7fffffff: return "XXX:FILTER"; 344 /* 0x80000000 - 0xffffffff application programs */ 345 default: return "ERROR: SHT NOT DEFINED"; 346 } 347 } 348 349 /* 350 * Define known section flags. These flags are defined in the order 351 * they are to be printed out. 352 */ 353 #define DEFINE_SHFLAGS() \ 354 DEFINE_SHF(WRITE) \ 355 DEFINE_SHF(ALLOC) \ 356 DEFINE_SHF(EXECINSTR) \ 357 DEFINE_SHF(MERGE) \ 358 DEFINE_SHF(STRINGS) \ 359 DEFINE_SHF(INFO_LINK) \ 360 DEFINE_SHF(LINK_ORDER) \ 361 DEFINE_SHF(OS_NONCONFORMING) \ 362 DEFINE_SHF(GROUP) \ 363 DEFINE_SHF(TLS) 364 365 #undef DEFINE_SHF 366 #define DEFINE_SHF(F) "SHF_" #F "|" 367 #define ALLSHFLAGS DEFINE_SHFLAGS() 368 369 static const char * 370 sh_flags(uint64_t shf) 371 { 372 static char flg[sizeof(ALLSHFLAGS)+1]; 373 374 flg[0] = '\0'; 375 376 #undef DEFINE_SHF 377 #define DEFINE_SHF(N) \ 378 if (shf & SHF_##N) \ 379 strcat(flg, "SHF_" #N "|"); \ 380 381 DEFINE_SHFLAGS() 382 383 flg[strlen(flg) - 1] = '\0'; /* Remove the trailing "|". */ 384 385 return (flg); 386 } 387 388 static const char *st_types[] = { 389 "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE", 390 "STT_COMMON", "STT_TLS" 391 }; 392 393 static const char *st_types_S[] = { 394 "NOTY", "OBJT", "FUNC", "SECT", "FILE" 395 }; 396 397 static const char *st_bindings[] = { 398 "STB_LOCAL", "STB_GLOBAL", "STB_WEAK" 399 }; 400 401 static const char *st_bindings_S[] = { 402 "LOCL", "GLOB", "WEAK" 403 }; 404 405 static unsigned char st_others[] = { 406 'D', 'I', 'H', 'P' 407 }; 408 409 static const char * 410 r_type(unsigned int mach, unsigned int type) 411 { 412 switch(mach) { 413 case EM_NONE: return ""; 414 case EM_386: 415 case EM_IAMCU: 416 switch(type) { 417 case 0: return "R_386_NONE"; 418 case 1: return "R_386_32"; 419 case 2: return "R_386_PC32"; 420 case 3: return "R_386_GOT32"; 421 case 4: return "R_386_PLT32"; 422 case 5: return "R_386_COPY"; 423 case 6: return "R_386_GLOB_DAT"; 424 case 7: return "R_386_JMP_SLOT"; 425 case 8: return "R_386_RELATIVE"; 426 case 9: return "R_386_GOTOFF"; 427 case 10: return "R_386_GOTPC"; 428 case 14: return "R_386_TLS_TPOFF"; 429 case 15: return "R_386_TLS_IE"; 430 case 16: return "R_386_TLS_GOTIE"; 431 case 17: return "R_386_TLS_LE"; 432 case 18: return "R_386_TLS_GD"; 433 case 19: return "R_386_TLS_LDM"; 434 case 24: return "R_386_TLS_GD_32"; 435 case 25: return "R_386_TLS_GD_PUSH"; 436 case 26: return "R_386_TLS_GD_CALL"; 437 case 27: return "R_386_TLS_GD_POP"; 438 case 28: return "R_386_TLS_LDM_32"; 439 case 29: return "R_386_TLS_LDM_PUSH"; 440 case 30: return "R_386_TLS_LDM_CALL"; 441 case 31: return "R_386_TLS_LDM_POP"; 442 case 32: return "R_386_TLS_LDO_32"; 443 case 33: return "R_386_TLS_IE_32"; 444 case 34: return "R_386_TLS_LE_32"; 445 case 35: return "R_386_TLS_DTPMOD32"; 446 case 36: return "R_386_TLS_DTPOFF32"; 447 case 37: return "R_386_TLS_TPOFF32"; 448 default: return ""; 449 } 450 case EM_ARM: 451 switch(type) { 452 case 0: return "R_ARM_NONE"; 453 case 1: return "R_ARM_PC24"; 454 case 2: return "R_ARM_ABS32"; 455 case 3: return "R_ARM_REL32"; 456 case 4: return "R_ARM_PC13"; 457 case 5: return "R_ARM_ABS16"; 458 case 6: return "R_ARM_ABS12"; 459 case 7: return "R_ARM_THM_ABS5"; 460 case 8: return "R_ARM_ABS8"; 461 case 9: return "R_ARM_SBREL32"; 462 case 10: return "R_ARM_THM_PC22"; 463 case 11: return "R_ARM_THM_PC8"; 464 case 12: return "R_ARM_AMP_VCALL9"; 465 case 13: return "R_ARM_SWI24"; 466 case 14: return "R_ARM_THM_SWI8"; 467 case 15: return "R_ARM_XPC25"; 468 case 16: return "R_ARM_THM_XPC22"; 469 case 20: return "R_ARM_COPY"; 470 case 21: return "R_ARM_GLOB_DAT"; 471 case 22: return "R_ARM_JUMP_SLOT"; 472 case 23: return "R_ARM_RELATIVE"; 473 case 24: return "R_ARM_GOTOFF"; 474 case 25: return "R_ARM_GOTPC"; 475 case 26: return "R_ARM_GOT32"; 476 case 27: return "R_ARM_PLT32"; 477 case 100: return "R_ARM_GNU_VTENTRY"; 478 case 101: return "R_ARM_GNU_VTINHERIT"; 479 case 250: return "R_ARM_RSBREL32"; 480 case 251: return "R_ARM_THM_RPC22"; 481 case 252: return "R_ARM_RREL32"; 482 case 253: return "R_ARM_RABS32"; 483 case 254: return "R_ARM_RPC24"; 484 case 255: return "R_ARM_RBASE"; 485 default: return ""; 486 } 487 case EM_IA_64: 488 switch(type) { 489 case 0: return "R_IA_64_NONE"; 490 case 33: return "R_IA_64_IMM14"; 491 case 34: return "R_IA_64_IMM22"; 492 case 35: return "R_IA_64_IMM64"; 493 case 36: return "R_IA_64_DIR32MSB"; 494 case 37: return "R_IA_64_DIR32LSB"; 495 case 38: return "R_IA_64_DIR64MSB"; 496 case 39: return "R_IA_64_DIR64LSB"; 497 case 42: return "R_IA_64_GPREL22"; 498 case 43: return "R_IA_64_GPREL64I"; 499 case 44: return "R_IA_64_GPREL32MSB"; 500 case 45: return "R_IA_64_GPREL32LSB"; 501 case 46: return "R_IA_64_GPREL64MSB"; 502 case 47: return "R_IA_64_GPREL64LSB"; 503 case 50: return "R_IA_64_LTOFF22"; 504 case 51: return "R_IA_64_LTOFF64I"; 505 case 58: return "R_IA_64_PLTOFF22"; 506 case 59: return "R_IA_64_PLTOFF64I"; 507 case 62: return "R_IA_64_PLTOFF64MSB"; 508 case 63: return "R_IA_64_PLTOFF64LSB"; 509 case 67: return "R_IA_64_FPTR64I"; 510 case 68: return "R_IA_64_FPTR32MSB"; 511 case 69: return "R_IA_64_FPTR32LSB"; 512 case 70: return "R_IA_64_FPTR64MSB"; 513 case 71: return "R_IA_64_FPTR64LSB"; 514 case 72: return "R_IA_64_PCREL60B"; 515 case 73: return "R_IA_64_PCREL21B"; 516 case 74: return "R_IA_64_PCREL21M"; 517 case 75: return "R_IA_64_PCREL21F"; 518 case 76: return "R_IA_64_PCREL32MSB"; 519 case 77: return "R_IA_64_PCREL32LSB"; 520 case 78: return "R_IA_64_PCREL64MSB"; 521 case 79: return "R_IA_64_PCREL64LSB"; 522 case 82: return "R_IA_64_LTOFF_FPTR22"; 523 case 83: return "R_IA_64_LTOFF_FPTR64I"; 524 case 84: return "R_IA_64_LTOFF_FPTR32MSB"; 525 case 85: return "R_IA_64_LTOFF_FPTR32LSB"; 526 case 86: return "R_IA_64_LTOFF_FPTR64MSB"; 527 case 87: return "R_IA_64_LTOFF_FPTR64LSB"; 528 case 92: return "R_IA_64_SEGREL32MSB"; 529 case 93: return "R_IA_64_SEGREL32LSB"; 530 case 94: return "R_IA_64_SEGREL64MSB"; 531 case 95: return "R_IA_64_SEGREL64LSB"; 532 case 100: return "R_IA_64_SECREL32MSB"; 533 case 101: return "R_IA_64_SECREL32LSB"; 534 case 102: return "R_IA_64_SECREL64MSB"; 535 case 103: return "R_IA_64_SECREL64LSB"; 536 case 108: return "R_IA_64_REL32MSB"; 537 case 109: return "R_IA_64_REL32LSB"; 538 case 110: return "R_IA_64_REL64MSB"; 539 case 111: return "R_IA_64_REL64LSB"; 540 case 116: return "R_IA_64_LTV32MSB"; 541 case 117: return "R_IA_64_LTV32LSB"; 542 case 118: return "R_IA_64_LTV64MSB"; 543 case 119: return "R_IA_64_LTV64LSB"; 544 case 121: return "R_IA_64_PCREL21BI"; 545 case 122: return "R_IA_64_PCREL22"; 546 case 123: return "R_IA_64_PCREL64I"; 547 case 128: return "R_IA_64_IPLTMSB"; 548 case 129: return "R_IA_64_IPLTLSB"; 549 case 133: return "R_IA_64_SUB"; 550 case 134: return "R_IA_64_LTOFF22X"; 551 case 135: return "R_IA_64_LDXMOV"; 552 case 145: return "R_IA_64_TPREL14"; 553 case 146: return "R_IA_64_TPREL22"; 554 case 147: return "R_IA_64_TPREL64I"; 555 case 150: return "R_IA_64_TPREL64MSB"; 556 case 151: return "R_IA_64_TPREL64LSB"; 557 case 154: return "R_IA_64_LTOFF_TPREL22"; 558 case 166: return "R_IA_64_DTPMOD64MSB"; 559 case 167: return "R_IA_64_DTPMOD64LSB"; 560 case 170: return "R_IA_64_LTOFF_DTPMOD22"; 561 case 177: return "R_IA_64_DTPREL14"; 562 case 178: return "R_IA_64_DTPREL22"; 563 case 179: return "R_IA_64_DTPREL64I"; 564 case 180: return "R_IA_64_DTPREL32MSB"; 565 case 181: return "R_IA_64_DTPREL32LSB"; 566 case 182: return "R_IA_64_DTPREL64MSB"; 567 case 183: return "R_IA_64_DTPREL64LSB"; 568 case 186: return "R_IA_64_LTOFF_DTPREL22"; 569 default: return ""; 570 } 571 case EM_MIPS: 572 switch(type) { 573 case 0: return "R_MIPS_NONE"; 574 case 1: return "R_MIPS_16"; 575 case 2: return "R_MIPS_32"; 576 case 3: return "R_MIPS_REL32"; 577 case 4: return "R_MIPS_26"; 578 case 5: return "R_MIPS_HI16"; 579 case 6: return "R_MIPS_LO16"; 580 case 7: return "R_MIPS_GPREL16"; 581 case 8: return "R_MIPS_LITERAL"; 582 case 9: return "R_MIPS_GOT16"; 583 case 10: return "R_MIPS_PC16"; 584 case 11: return "R_MIPS_CALL16"; 585 case 12: return "R_MIPS_GPREL32"; 586 case 21: return "R_MIPS_GOTHI16"; 587 case 22: return "R_MIPS_GOTLO16"; 588 case 30: return "R_MIPS_CALLHI16"; 589 case 31: return "R_MIPS_CALLLO16"; 590 default: return ""; 591 } 592 case EM_PPC: 593 switch(type) { 594 case 0: return "R_PPC_NONE"; 595 case 1: return "R_PPC_ADDR32"; 596 case 2: return "R_PPC_ADDR24"; 597 case 3: return "R_PPC_ADDR16"; 598 case 4: return "R_PPC_ADDR16_LO"; 599 case 5: return "R_PPC_ADDR16_HI"; 600 case 6: return "R_PPC_ADDR16_HA"; 601 case 7: return "R_PPC_ADDR14"; 602 case 8: return "R_PPC_ADDR14_BRTAKEN"; 603 case 9: return "R_PPC_ADDR14_BRNTAKEN"; 604 case 10: return "R_PPC_REL24"; 605 case 11: return "R_PPC_REL14"; 606 case 12: return "R_PPC_REL14_BRTAKEN"; 607 case 13: return "R_PPC_REL14_BRNTAKEN"; 608 case 14: return "R_PPC_GOT16"; 609 case 15: return "R_PPC_GOT16_LO"; 610 case 16: return "R_PPC_GOT16_HI"; 611 case 17: return "R_PPC_GOT16_HA"; 612 case 18: return "R_PPC_PLTREL24"; 613 case 19: return "R_PPC_COPY"; 614 case 20: return "R_PPC_GLOB_DAT"; 615 case 21: return "R_PPC_JMP_SLOT"; 616 case 22: return "R_PPC_RELATIVE"; 617 case 23: return "R_PPC_LOCAL24PC"; 618 case 24: return "R_PPC_UADDR32"; 619 case 25: return "R_PPC_UADDR16"; 620 case 26: return "R_PPC_REL32"; 621 case 27: return "R_PPC_PLT32"; 622 case 28: return "R_PPC_PLTREL32"; 623 case 29: return "R_PPC_PLT16_LO"; 624 case 30: return "R_PPC_PLT16_HI"; 625 case 31: return "R_PPC_PLT16_HA"; 626 case 32: return "R_PPC_SDAREL16"; 627 case 33: return "R_PPC_SECTOFF"; 628 case 34: return "R_PPC_SECTOFF_LO"; 629 case 35: return "R_PPC_SECTOFF_HI"; 630 case 36: return "R_PPC_SECTOFF_HA"; 631 case 67: return "R_PPC_TLS"; 632 case 68: return "R_PPC_DTPMOD32"; 633 case 69: return "R_PPC_TPREL16"; 634 case 70: return "R_PPC_TPREL16_LO"; 635 case 71: return "R_PPC_TPREL16_HI"; 636 case 72: return "R_PPC_TPREL16_HA"; 637 case 73: return "R_PPC_TPREL32"; 638 case 74: return "R_PPC_DTPREL16"; 639 case 75: return "R_PPC_DTPREL16_LO"; 640 case 76: return "R_PPC_DTPREL16_HI"; 641 case 77: return "R_PPC_DTPREL16_HA"; 642 case 78: return "R_PPC_DTPREL32"; 643 case 79: return "R_PPC_GOT_TLSGD16"; 644 case 80: return "R_PPC_GOT_TLSGD16_LO"; 645 case 81: return "R_PPC_GOT_TLSGD16_HI"; 646 case 82: return "R_PPC_GOT_TLSGD16_HA"; 647 case 83: return "R_PPC_GOT_TLSLD16"; 648 case 84: return "R_PPC_GOT_TLSLD16_LO"; 649 case 85: return "R_PPC_GOT_TLSLD16_HI"; 650 case 86: return "R_PPC_GOT_TLSLD16_HA"; 651 case 87: return "R_PPC_GOT_TPREL16"; 652 case 88: return "R_PPC_GOT_TPREL16_LO"; 653 case 89: return "R_PPC_GOT_TPREL16_HI"; 654 case 90: return "R_PPC_GOT_TPREL16_HA"; 655 case 101: return "R_PPC_EMB_NADDR32"; 656 case 102: return "R_PPC_EMB_NADDR16"; 657 case 103: return "R_PPC_EMB_NADDR16_LO"; 658 case 104: return "R_PPC_EMB_NADDR16_HI"; 659 case 105: return "R_PPC_EMB_NADDR16_HA"; 660 case 106: return "R_PPC_EMB_SDAI16"; 661 case 107: return "R_PPC_EMB_SDA2I16"; 662 case 108: return "R_PPC_EMB_SDA2REL"; 663 case 109: return "R_PPC_EMB_SDA21"; 664 case 110: return "R_PPC_EMB_MRKREF"; 665 case 111: return "R_PPC_EMB_RELSEC16"; 666 case 112: return "R_PPC_EMB_RELST_LO"; 667 case 113: return "R_PPC_EMB_RELST_HI"; 668 case 114: return "R_PPC_EMB_RELST_HA"; 669 case 115: return "R_PPC_EMB_BIT_FLD"; 670 case 116: return "R_PPC_EMB_RELSDA"; 671 default: return ""; 672 } 673 case EM_SPARC: 674 case EM_SPARCV9: 675 switch(type) { 676 case 0: return "R_SPARC_NONE"; 677 case 1: return "R_SPARC_8"; 678 case 2: return "R_SPARC_16"; 679 case 3: return "R_SPARC_32"; 680 case 4: return "R_SPARC_DISP8"; 681 case 5: return "R_SPARC_DISP16"; 682 case 6: return "R_SPARC_DISP32"; 683 case 7: return "R_SPARC_WDISP30"; 684 case 8: return "R_SPARC_WDISP22"; 685 case 9: return "R_SPARC_HI22"; 686 case 10: return "R_SPARC_22"; 687 case 11: return "R_SPARC_13"; 688 case 12: return "R_SPARC_LO10"; 689 case 13: return "R_SPARC_GOT10"; 690 case 14: return "R_SPARC_GOT13"; 691 case 15: return "R_SPARC_GOT22"; 692 case 16: return "R_SPARC_PC10"; 693 case 17: return "R_SPARC_PC22"; 694 case 18: return "R_SPARC_WPLT30"; 695 case 19: return "R_SPARC_COPY"; 696 case 20: return "R_SPARC_GLOB_DAT"; 697 case 21: return "R_SPARC_JMP_SLOT"; 698 case 22: return "R_SPARC_RELATIVE"; 699 case 23: return "R_SPARC_UA32"; 700 case 24: return "R_SPARC_PLT32"; 701 case 25: return "R_SPARC_HIPLT22"; 702 case 26: return "R_SPARC_LOPLT10"; 703 case 27: return "R_SPARC_PCPLT32"; 704 case 28: return "R_SPARC_PCPLT22"; 705 case 29: return "R_SPARC_PCPLT10"; 706 case 30: return "R_SPARC_10"; 707 case 31: return "R_SPARC_11"; 708 case 32: return "R_SPARC_64"; 709 case 33: return "R_SPARC_OLO10"; 710 case 34: return "R_SPARC_HH22"; 711 case 35: return "R_SPARC_HM10"; 712 case 36: return "R_SPARC_LM22"; 713 case 37: return "R_SPARC_PC_HH22"; 714 case 38: return "R_SPARC_PC_HM10"; 715 case 39: return "R_SPARC_PC_LM22"; 716 case 40: return "R_SPARC_WDISP16"; 717 case 41: return "R_SPARC_WDISP19"; 718 case 42: return "R_SPARC_GLOB_JMP"; 719 case 43: return "R_SPARC_7"; 720 case 44: return "R_SPARC_5"; 721 case 45: return "R_SPARC_6"; 722 case 46: return "R_SPARC_DISP64"; 723 case 47: return "R_SPARC_PLT64"; 724 case 48: return "R_SPARC_HIX22"; 725 case 49: return "R_SPARC_LOX10"; 726 case 50: return "R_SPARC_H44"; 727 case 51: return "R_SPARC_M44"; 728 case 52: return "R_SPARC_L44"; 729 case 53: return "R_SPARC_REGISTER"; 730 case 54: return "R_SPARC_UA64"; 731 case 55: return "R_SPARC_UA16"; 732 case 56: return "R_SPARC_TLS_GD_HI22"; 733 case 57: return "R_SPARC_TLS_GD_LO10"; 734 case 58: return "R_SPARC_TLS_GD_ADD"; 735 case 59: return "R_SPARC_TLS_GD_CALL"; 736 case 60: return "R_SPARC_TLS_LDM_HI22"; 737 case 61: return "R_SPARC_TLS_LDM_LO10"; 738 case 62: return "R_SPARC_TLS_LDM_ADD"; 739 case 63: return "R_SPARC_TLS_LDM_CALL"; 740 case 64: return "R_SPARC_TLS_LDO_HIX22"; 741 case 65: return "R_SPARC_TLS_LDO_LOX10"; 742 case 66: return "R_SPARC_TLS_LDO_ADD"; 743 case 67: return "R_SPARC_TLS_IE_HI22"; 744 case 68: return "R_SPARC_TLS_IE_LO10"; 745 case 69: return "R_SPARC_TLS_IE_LD"; 746 case 70: return "R_SPARC_TLS_IE_LDX"; 747 case 71: return "R_SPARC_TLS_IE_ADD"; 748 case 72: return "R_SPARC_TLS_LE_HIX22"; 749 case 73: return "R_SPARC_TLS_LE_LOX10"; 750 case 74: return "R_SPARC_TLS_DTPMOD32"; 751 case 75: return "R_SPARC_TLS_DTPMOD64"; 752 case 76: return "R_SPARC_TLS_DTPOFF32"; 753 case 77: return "R_SPARC_TLS_DTPOFF64"; 754 case 78: return "R_SPARC_TLS_TPOFF32"; 755 case 79: return "R_SPARC_TLS_TPOFF64"; 756 default: return ""; 757 } 758 case EM_X86_64: 759 switch(type) { 760 case 0: return "R_X86_64_NONE"; 761 case 1: return "R_X86_64_64"; 762 case 2: return "R_X86_64_PC32"; 763 case 3: return "R_X86_64_GOT32"; 764 case 4: return "R_X86_64_PLT32"; 765 case 5: return "R_X86_64_COPY"; 766 case 6: return "R_X86_64_GLOB_DAT"; 767 case 7: return "R_X86_64_JMP_SLOT"; 768 case 8: return "R_X86_64_RELATIVE"; 769 case 9: return "R_X86_64_GOTPCREL"; 770 case 10: return "R_X86_64_32"; 771 case 11: return "R_X86_64_32S"; 772 case 12: return "R_X86_64_16"; 773 case 13: return "R_X86_64_PC16"; 774 case 14: return "R_X86_64_8"; 775 case 15: return "R_X86_64_PC8"; 776 case 16: return "R_X86_64_DTPMOD64"; 777 case 17: return "R_X86_64_DTPOFF64"; 778 case 18: return "R_X86_64_TPOFF64"; 779 case 19: return "R_X86_64_TLSGD"; 780 case 20: return "R_X86_64_TLSLD"; 781 case 21: return "R_X86_64_DTPOFF32"; 782 case 22: return "R_X86_64_GOTTPOFF"; 783 case 23: return "R_X86_64_TPOFF32"; 784 default: return ""; 785 } 786 default: return ""; 787 } 788 } 789 790 static void add_name(struct elfdump *ed, const char *name); 791 static void elf_print_object(struct elfdump *ed); 792 static void elf_print_elf(struct elfdump *ed); 793 static void elf_print_ehdr(struct elfdump *ed); 794 static void elf_print_phdr(struct elfdump *ed); 795 static void elf_print_shdr(struct elfdump *ed); 796 static void elf_print_symtab(struct elfdump *ed, int i); 797 static void elf_print_symtabs(struct elfdump *ed); 798 static void elf_print_symver(struct elfdump *ed); 799 static void elf_print_verdef(struct elfdump *ed, struct section *s); 800 static void elf_print_verneed(struct elfdump *ed, struct section *s); 801 static void elf_print_interp(struct elfdump *ed); 802 static void elf_print_dynamic(struct elfdump *ed); 803 static void elf_print_rel_entry(struct elfdump *ed, struct section *s, 804 int j, struct rel_entry *r); 805 static void elf_print_rela(struct elfdump *ed, struct section *s, 806 Elf_Data *data); 807 static void elf_print_rel(struct elfdump *ed, struct section *s, 808 Elf_Data *data); 809 static void elf_print_reloc(struct elfdump *ed); 810 static void elf_print_got(struct elfdump *ed); 811 static void elf_print_got_section(struct elfdump *ed, struct section *s); 812 static void elf_print_note(struct elfdump *ed); 813 static void elf_print_svr4_hash(struct elfdump *ed, struct section *s); 814 static void elf_print_svr4_hash64(struct elfdump *ed, struct section *s); 815 static void elf_print_gnu_hash(struct elfdump *ed, struct section *s); 816 static void elf_print_hash(struct elfdump *ed); 817 static void elf_print_checksum(struct elfdump *ed); 818 static void find_gotrel(struct elfdump *ed, struct section *gs, 819 struct rel_entry *got); 820 static struct spec_name *find_name(struct elfdump *ed, const char *name); 821 static const char *get_symbol_name(struct elfdump *ed, int symtab, int i); 822 static const char *get_string(struct elfdump *ed, int strtab, size_t off); 823 static void get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs); 824 static void load_sections(struct elfdump *ed); 825 static void unload_sections(struct elfdump *ed); 826 static void usage(void); 827 #ifdef USE_LIBARCHIVE_AR 828 static int ac_detect_ar(int fd); 829 static void ac_print_ar(struct elfdump *ed, int fd); 830 #else 831 static void elf_print_ar(struct elfdump *ed, int fd); 832 #endif /* USE_LIBARCHIVE_AR */ 833 834 static struct option elfdump_longopts[] = 835 { 836 { "help", no_argument, NULL, 'H' }, 837 { "version", no_argument, NULL, 'V' }, 838 { NULL, 0, NULL, 0 } 839 }; 840 841 int 842 main(int ac, char **av) 843 { 844 struct elfdump *ed, ed_storage; 845 struct spec_name *sn; 846 int ch, i; 847 848 ed = &ed_storage; 849 memset(ed, 0, sizeof(*ed)); 850 STAILQ_INIT(&ed->snl); 851 ed->out = stdout; 852 while ((ch = getopt_long(ac, av, "acdeiGHhknN:prsSvVw:", 853 elfdump_longopts, NULL)) != -1) 854 switch (ch) { 855 case 'a': 856 ed->options = ED_ALL; 857 break; 858 case 'c': 859 ed->options |= ED_SHDR; 860 break; 861 case 'd': 862 ed->options |= ED_DYN; 863 break; 864 case 'e': 865 ed->options |= ED_EHDR; 866 break; 867 case 'i': 868 ed->options |= ED_INTERP; 869 break; 870 case 'G': 871 ed->options |= ED_GOT; 872 break; 873 case 'h': 874 ed->options |= ED_HASH; 875 break; 876 case 'k': 877 ed->options |= ED_CHECKSUM; 878 break; 879 case 'n': 880 ed->options |= ED_NOTE; 881 break; 882 case 'N': 883 add_name(ed, optarg); 884 break; 885 case 'p': 886 ed->options |= ED_PHDR; 887 break; 888 case 'r': 889 ed->options |= ED_REL; 890 break; 891 case 's': 892 ed->options |= ED_SYMTAB; 893 break; 894 case 'S': 895 ed->flags |= SOLARIS_FMT; 896 break; 897 case 'v': 898 ed->options |= ED_SYMVER; 899 break; 900 case 'V': 901 (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), 902 elftc_version()); 903 exit(EXIT_SUCCESS); 904 break; 905 case 'w': 906 if ((ed->out = fopen(optarg, "w")) == NULL) 907 err(EXIT_FAILURE, "%s", optarg); 908 break; 909 case '?': 910 case 'H': 911 default: 912 usage(); 913 } 914 915 ac -= optind; 916 av += optind; 917 918 if (ed->options == 0) 919 ed->options = ED_ALL; 920 sn = NULL; 921 if (ed->options & ED_SYMTAB && 922 (STAILQ_EMPTY(&ed->snl) || (sn = find_name(ed, "ARSYM")) != NULL)) { 923 ed->flags |= PRINT_ARSYM; 924 if (sn != NULL) { 925 STAILQ_REMOVE(&ed->snl, sn, spec_name, sn_list); 926 if (STAILQ_EMPTY(&ed->snl)) 927 ed->flags |= ONLY_ARSYM; 928 } 929 } 930 if (ac == 0) 931 usage(); 932 if (ac > 1) 933 ed->flags |= PRINT_FILENAME; 934 if (elf_version(EV_CURRENT) == EV_NONE) 935 errx(EXIT_FAILURE, "ELF library initialization failed: %s", 936 elf_errmsg(-1)); 937 938 for (i = 0; i < ac; i++) { 939 ed->filename = av[i]; 940 ed->archive = NULL; 941 elf_print_object(ed); 942 } 943 944 exit(EXIT_SUCCESS); 945 } 946 947 #ifdef USE_LIBARCHIVE_AR 948 949 /* Archive symbol table entry. */ 950 struct arsym_entry { 951 char *sym_name; 952 size_t off; 953 }; 954 955 /* 956 * Convenient wrapper for general libarchive error handling. 957 */ 958 #define AC(CALL) do { \ 959 if ((CALL)) { \ 960 warnx("%s", archive_error_string(a)); \ 961 return; \ 962 } \ 963 } while (0) 964 965 /* 966 * Detect an ar(1) archive using libarchive(3). 967 */ 968 static int 969 ac_detect_ar(int fd) 970 { 971 struct archive *a; 972 struct archive_entry *entry; 973 int r; 974 975 r = -1; 976 if ((a = archive_read_new()) == NULL) 977 return (0); 978 archive_read_support_format_ar(a); 979 if (archive_read_open_fd(a, fd, 10240) == ARCHIVE_OK) 980 r = archive_read_next_header(a, &entry); 981 archive_read_close(a); 982 archive_read_free(a); 983 984 return (r == ARCHIVE_OK); 985 } 986 987 /* 988 * Dump an ar(1) archive using libarchive(3). 989 */ 990 static void 991 ac_print_ar(struct elfdump *ed, int fd) 992 { 993 struct archive *a; 994 struct archive_entry *entry; 995 struct arsym_entry *arsym; 996 const char *name; 997 char idx[10], *b; 998 void *buff; 999 size_t size; 1000 uint32_t cnt; 1001 int i, r; 1002 1003 if (lseek(fd, 0, SEEK_SET) == -1) 1004 err(EXIT_FAILURE, "lseek failed"); 1005 if ((a = archive_read_new()) == NULL) 1006 errx(EXIT_FAILURE, "%s", archive_error_string(a)); 1007 archive_read_support_format_ar(a); 1008 AC(archive_read_open_fd(a, fd, 10240)); 1009 for(;;) { 1010 r = archive_read_next_header(a, &entry); 1011 if (r == ARCHIVE_FATAL) 1012 errx(EXIT_FAILURE, "%s", archive_error_string(a)); 1013 if (r == ARCHIVE_EOF) 1014 break; 1015 if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY) 1016 warnx("%s", archive_error_string(a)); 1017 if (r == ARCHIVE_RETRY) 1018 continue; 1019 name = archive_entry_pathname(entry); 1020 size = archive_entry_size(entry); 1021 if (size == 0) 1022 continue; 1023 if ((buff = malloc(size)) == NULL) { 1024 warn("malloc failed"); 1025 continue; 1026 } 1027 if (archive_read_data(a, buff, size) != (ssize_t)size) { 1028 warnx("%s", archive_error_string(a)); 1029 free(buff); 1030 continue; 1031 } 1032 1033 /* 1034 * Note that when processing arsym via libarchive, there is 1035 * no way to tell which member a certain symbol belongs to, 1036 * since we can not just "lseek" to a member offset and read 1037 * the member header. 1038 */ 1039 if (!strcmp(name, "/") && ed->flags & PRINT_ARSYM) { 1040 b = buff; 1041 cnt = be32dec(b); 1042 if (cnt == 0) { 1043 free(buff); 1044 continue; 1045 } 1046 arsym = calloc(cnt, sizeof(*arsym)); 1047 if (arsym == NULL) 1048 err(EXIT_FAILURE, "calloc failed"); 1049 b += sizeof(uint32_t); 1050 for (i = 0; (size_t)i < cnt; i++) { 1051 arsym[i].off = be32dec(b); 1052 b += sizeof(uint32_t); 1053 } 1054 for (i = 0; (size_t)i < cnt; i++) { 1055 arsym[i].sym_name = b; 1056 b += strlen(b) + 1; 1057 } 1058 if (ed->flags & SOLARIS_FMT) { 1059 PRT("\nSymbol Table: (archive)\n"); 1060 PRT(" index offset symbol\n"); 1061 } else 1062 PRT("\nsymbol table (archive):\n"); 1063 for (i = 0; (size_t)i < cnt; i++) { 1064 if (ed->flags & SOLARIS_FMT) { 1065 snprintf(idx, sizeof(idx), "[%d]", i); 1066 PRT("%10s ", idx); 1067 PRT("0x%8.8jx ", 1068 (uintmax_t)arsym[i].off); 1069 PRT("%s\n", arsym[i].sym_name); 1070 } else { 1071 PRT("\nentry: %d\n", i); 1072 PRT("\toffset: %#jx\n", 1073 (uintmax_t)arsym[i].off); 1074 PRT("\tsymbol: %s\n", 1075 arsym[i].sym_name); 1076 } 1077 } 1078 free(arsym); 1079 free(buff); 1080 /* No need to continue if we only dump ARSYM. */ 1081 if (ed->flags & ONLY_ARSYM) { 1082 AC(archive_read_close(a)); 1083 AC(archive_read_free(a)); 1084 return; 1085 } 1086 continue; 1087 } 1088 if ((ed->elf = elf_memory(buff, size)) == NULL) { 1089 warnx("elf_memroy() failed: %s", 1090 elf_errmsg(-1)); 1091 free(buff); 1092 continue; 1093 } 1094 /* Skip non-ELF member. */ 1095 if (elf_kind(ed->elf) == ELF_K_ELF) { 1096 printf("\n%s(%s):\n", ed->archive, name); 1097 elf_print_elf(ed); 1098 } 1099 elf_end(ed->elf); 1100 free(buff); 1101 } 1102 AC(archive_read_close(a)); 1103 AC(archive_read_free(a)); 1104 } 1105 1106 #else /* USE_LIBARCHIVE_AR */ 1107 1108 /* 1109 * Dump an ar(1) archive. 1110 */ 1111 static void 1112 elf_print_ar(struct elfdump *ed, int fd) 1113 { 1114 Elf *e; 1115 Elf_Arhdr *arh; 1116 Elf_Arsym *arsym; 1117 Elf_Cmd cmd; 1118 char idx[10]; 1119 size_t cnt; 1120 int i; 1121 1122 ed->ar = ed->elf; 1123 1124 if (ed->flags & PRINT_ARSYM) { 1125 cnt = 0; 1126 if ((arsym = elf_getarsym(ed->ar, &cnt)) == NULL) { 1127 warnx("elf_getarsym failed: %s", elf_errmsg(-1)); 1128 goto print_members; 1129 } 1130 if (cnt == 0) 1131 goto print_members; 1132 if (ed->flags & SOLARIS_FMT) { 1133 PRT("\nSymbol Table: (archive)\n"); 1134 PRT(" index offset member name and symbol\n"); 1135 } else 1136 PRT("\nsymbol table (archive):\n"); 1137 for (i = 0; (size_t)i < cnt - 1; i++) { 1138 if (elf_rand(ed->ar, arsym[i].as_off) != 1139 arsym[i].as_off) { 1140 warnx("elf_rand failed: %s", elf_errmsg(-1)); 1141 break; 1142 } 1143 if ((e = elf_begin(fd, ELF_C_READ, ed->ar)) == NULL) { 1144 warnx("elf_begin failed: %s", elf_errmsg(-1)); 1145 break; 1146 } 1147 if ((arh = elf_getarhdr(e)) == NULL) { 1148 warnx("elf_getarhdr failed: %s", 1149 elf_errmsg(-1)); 1150 break; 1151 } 1152 if (ed->flags & SOLARIS_FMT) { 1153 snprintf(idx, sizeof(idx), "[%d]", i); 1154 PRT("%10s ", idx); 1155 PRT("0x%8.8jx ", 1156 (uintmax_t)arsym[i].as_off); 1157 PRT("(%s):%s\n", arh->ar_name, 1158 arsym[i].as_name); 1159 } else { 1160 PRT("\nentry: %d\n", i); 1161 PRT("\toffset: %#jx\n", 1162 (uintmax_t)arsym[i].as_off); 1163 PRT("\tmember: %s\n", arh->ar_name); 1164 PRT("\tsymbol: %s\n", arsym[i].as_name); 1165 } 1166 elf_end(e); 1167 } 1168 1169 /* No need to continue if we only dump ARSYM. */ 1170 if (ed->flags & ONLY_ARSYM) 1171 return; 1172 } 1173 1174 print_members: 1175 1176 /* Rewind the archive. */ 1177 if (elf_rand(ed->ar, SARMAG) != SARMAG) { 1178 warnx("elf_rand failed: %s", elf_errmsg(-1)); 1179 return; 1180 } 1181 1182 /* Dump each member of the archive. */ 1183 cmd = ELF_C_READ; 1184 while ((ed->elf = elf_begin(fd, cmd, ed->ar)) != NULL) { 1185 /* Skip non-ELF member. */ 1186 if (elf_kind(ed->elf) == ELF_K_ELF) { 1187 if ((arh = elf_getarhdr(ed->elf)) == NULL) { 1188 warnx("elf_getarhdr failed: %s", 1189 elf_errmsg(-1)); 1190 break; 1191 } 1192 printf("\n%s(%s):\n", ed->archive, arh->ar_name); 1193 elf_print_elf(ed); 1194 } 1195 cmd = elf_next(ed->elf); 1196 elf_end(ed->elf); 1197 } 1198 } 1199 1200 #endif /* USE_LIBARCHIVE_AR */ 1201 1202 /* 1203 * Dump an object. (ELF object or ar(1) archive) 1204 */ 1205 static void 1206 elf_print_object(struct elfdump *ed) 1207 { 1208 int fd; 1209 1210 if ((fd = open(ed->filename, O_RDONLY)) == -1) { 1211 warn("open %s failed", ed->filename); 1212 return; 1213 } 1214 1215 #ifdef USE_LIBARCHIVE_AR 1216 if (ac_detect_ar(fd)) { 1217 ed->archive = ed->filename; 1218 ac_print_ar(ed, fd); 1219 return; 1220 } 1221 #endif /* USE_LIBARCHIVE_AR */ 1222 1223 if ((ed->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 1224 warnx("elf_begin() failed: %s", elf_errmsg(-1)); 1225 return; 1226 } 1227 1228 switch (elf_kind(ed->elf)) { 1229 case ELF_K_NONE: 1230 warnx("Not an ELF file."); 1231 return; 1232 case ELF_K_ELF: 1233 if (ed->flags & PRINT_FILENAME) 1234 printf("\n%s:\n", ed->filename); 1235 elf_print_elf(ed); 1236 break; 1237 case ELF_K_AR: 1238 #ifndef USE_LIBARCHIVE_AR 1239 ed->archive = ed->filename; 1240 elf_print_ar(ed, fd); 1241 #endif 1242 break; 1243 default: 1244 warnx("Internal: libelf returned unknown elf kind."); 1245 return; 1246 } 1247 1248 elf_end(ed->elf); 1249 } 1250 1251 /* 1252 * Dump an ELF object. 1253 */ 1254 static void 1255 elf_print_elf(struct elfdump *ed) 1256 { 1257 1258 if (gelf_getehdr(ed->elf, &ed->ehdr) == NULL) { 1259 warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); 1260 return; 1261 } 1262 if ((ed->ec = gelf_getclass(ed->elf)) == ELFCLASSNONE) { 1263 warnx("gelf_getclass failed: %s", elf_errmsg(-1)); 1264 return; 1265 } 1266 1267 if (ed->options & (ED_SHDR | ED_DYN | ED_REL | ED_GOT | ED_SYMTAB | 1268 ED_SYMVER | ED_NOTE | ED_HASH)) 1269 load_sections(ed); 1270 1271 if (ed->options & ED_EHDR) 1272 elf_print_ehdr(ed); 1273 if (ed->options & ED_PHDR) 1274 elf_print_phdr(ed); 1275 if (ed->options & ED_INTERP) 1276 elf_print_interp(ed); 1277 if (ed->options & ED_SHDR) 1278 elf_print_shdr(ed); 1279 if (ed->options & ED_DYN) 1280 elf_print_dynamic(ed); 1281 if (ed->options & ED_REL) 1282 elf_print_reloc(ed); 1283 if (ed->options & ED_GOT) 1284 elf_print_got(ed); 1285 if (ed->options & ED_SYMTAB) 1286 elf_print_symtabs(ed); 1287 if (ed->options & ED_SYMVER) 1288 elf_print_symver(ed); 1289 if (ed->options & ED_NOTE) 1290 elf_print_note(ed); 1291 if (ed->options & ED_HASH) 1292 elf_print_hash(ed); 1293 if (ed->options & ED_CHECKSUM) 1294 elf_print_checksum(ed); 1295 1296 unload_sections(ed); 1297 } 1298 1299 /* 1300 * Read the section headers from ELF object and store them in the 1301 * internal cache. 1302 */ 1303 static void 1304 load_sections(struct elfdump *ed) 1305 { 1306 struct section *s; 1307 const char *name; 1308 Elf_Scn *scn; 1309 GElf_Shdr sh; 1310 size_t shstrndx, ndx; 1311 int elferr; 1312 1313 assert(ed->sl == NULL); 1314 1315 if (!elf_getshnum(ed->elf, &ed->shnum)) { 1316 warnx("elf_getshnum failed: %s", elf_errmsg(-1)); 1317 return; 1318 } 1319 if (ed->shnum == 0) 1320 return; 1321 if ((ed->sl = calloc(ed->shnum, sizeof(*ed->sl))) == NULL) 1322 err(EXIT_FAILURE, "calloc failed"); 1323 if (!elf_getshstrndx(ed->elf, &shstrndx)) { 1324 warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); 1325 return; 1326 } 1327 if ((scn = elf_getscn(ed->elf, 0)) == NULL) { 1328 warnx("elf_getscn failed: %s", elf_errmsg(-1)); 1329 return; 1330 } 1331 (void) elf_errno(); 1332 do { 1333 if (gelf_getshdr(scn, &sh) == NULL) { 1334 warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); 1335 (void) elf_errno(); 1336 continue; 1337 } 1338 if ((name = elf_strptr(ed->elf, shstrndx, sh.sh_name)) == NULL) { 1339 (void) elf_errno(); 1340 name = "ERROR"; 1341 } 1342 if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) 1343 if ((elferr = elf_errno()) != 0) { 1344 warnx("elf_ndxscn failed: %s", 1345 elf_errmsg(elferr)); 1346 continue; 1347 } 1348 if (ndx >= ed->shnum) { 1349 warnx("section index of '%s' out of range", name); 1350 continue; 1351 } 1352 s = &ed->sl[ndx]; 1353 s->name = name; 1354 s->scn = scn; 1355 s->off = sh.sh_offset; 1356 s->sz = sh.sh_size; 1357 s->entsize = sh.sh_entsize; 1358 s->align = sh.sh_addralign; 1359 s->type = sh.sh_type; 1360 s->flags = sh.sh_flags; 1361 s->addr = sh.sh_addr; 1362 s->link = sh.sh_link; 1363 s->info = sh.sh_info; 1364 } while ((scn = elf_nextscn(ed->elf, scn)) != NULL); 1365 elferr = elf_errno(); 1366 if (elferr != 0) 1367 warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); 1368 } 1369 1370 /* 1371 * Release section related resources. 1372 */ 1373 static void 1374 unload_sections(struct elfdump *ed) 1375 { 1376 if (ed->sl != NULL) { 1377 free(ed->sl); 1378 ed->sl = NULL; 1379 } 1380 } 1381 1382 /* 1383 * Add a name to the '-N' name list. 1384 */ 1385 static void 1386 add_name(struct elfdump *ed, const char *name) 1387 { 1388 struct spec_name *sn; 1389 1390 if (find_name(ed, name)) 1391 return; 1392 if ((sn = malloc(sizeof(*sn))) == NULL) { 1393 warn("malloc failed"); 1394 return; 1395 } 1396 sn->name = name; 1397 STAILQ_INSERT_TAIL(&ed->snl, sn, sn_list); 1398 } 1399 1400 /* 1401 * Lookup a name in the '-N' name list. 1402 */ 1403 static struct spec_name * 1404 find_name(struct elfdump *ed, const char *name) 1405 { 1406 struct spec_name *sn; 1407 1408 STAILQ_FOREACH(sn, &ed->snl, sn_list) { 1409 if (!strcmp(sn->name, name)) 1410 return (sn); 1411 } 1412 1413 return (NULL); 1414 } 1415 1416 /* 1417 * Retrieve the name of a symbol using the section index of the symbol 1418 * table and the index of the symbol within that table. 1419 */ 1420 static const char * 1421 get_symbol_name(struct elfdump *ed, int symtab, int i) 1422 { 1423 static char sname[64]; 1424 struct section *s; 1425 const char *name; 1426 GElf_Sym sym; 1427 Elf_Data *data; 1428 int elferr; 1429 1430 s = &ed->sl[symtab]; 1431 if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) 1432 return (""); 1433 (void) elf_errno(); 1434 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1435 elferr = elf_errno(); 1436 if (elferr != 0) 1437 warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1438 return (""); 1439 } 1440 if (gelf_getsym(data, i, &sym) != &sym) 1441 return (""); 1442 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) { 1443 if (sym.st_shndx < ed->shnum) { 1444 snprintf(sname, sizeof(sname), "%s (section)", 1445 ed->sl[sym.st_shndx].name); 1446 return (sname); 1447 } else 1448 return (""); 1449 } 1450 if ((name = elf_strptr(ed->elf, s->link, sym.st_name)) == NULL) 1451 return (""); 1452 1453 return (name); 1454 } 1455 1456 /* 1457 * Retrieve a string using string table section index and the string offset. 1458 */ 1459 static const char* 1460 get_string(struct elfdump *ed, int strtab, size_t off) 1461 { 1462 const char *name; 1463 1464 if ((name = elf_strptr(ed->elf, strtab, off)) == NULL) 1465 return (""); 1466 1467 return (name); 1468 } 1469 1470 /* 1471 * Dump the ELF Executable Header. 1472 */ 1473 static void 1474 elf_print_ehdr(struct elfdump *ed) 1475 { 1476 1477 if (!STAILQ_EMPTY(&ed->snl)) 1478 return; 1479 1480 if (ed->flags & SOLARIS_FMT) { 1481 PRT("\nELF Header\n"); 1482 PRT(" ei_magic: { %#x, %c, %c, %c }\n", 1483 ed->ehdr.e_ident[0], ed->ehdr.e_ident[1], 1484 ed->ehdr.e_ident[2], ed->ehdr.e_ident[3]); 1485 PRT(" ei_class: %-18s", 1486 ei_classes[ed->ehdr.e_ident[EI_CLASS]]); 1487 PRT(" ei_data: %s\n", ei_data[ed->ehdr.e_ident[EI_DATA]]); 1488 PRT(" e_machine: %-18s", e_machines(ed->ehdr.e_machine)); 1489 PRT(" e_version: %s\n", ei_versions[ed->ehdr.e_version]); 1490 PRT(" e_type: %s\n", e_types[ed->ehdr.e_type]); 1491 PRT(" e_flags: %18d\n", ed->ehdr.e_flags); 1492 PRT(" e_entry: %#18jx", (uintmax_t)ed->ehdr.e_entry); 1493 PRT(" e_ehsize: %6d", ed->ehdr.e_ehsize); 1494 PRT(" e_shstrndx:%5d\n", ed->ehdr.e_shstrndx); 1495 PRT(" e_shoff: %#18jx", (uintmax_t)ed->ehdr.e_shoff); 1496 PRT(" e_shentsize: %3d", ed->ehdr.e_shentsize); 1497 PRT(" e_shnum: %5d\n", ed->ehdr.e_shnum); 1498 PRT(" e_phoff: %#18jx", (uintmax_t)ed->ehdr.e_phoff); 1499 PRT(" e_phentsize: %3d", ed->ehdr.e_phentsize); 1500 PRT(" e_phnum: %5d\n", ed->ehdr.e_phnum); 1501 } else { 1502 PRT("\nelf header:\n"); 1503 PRT("\n"); 1504 PRT("\te_ident: %s %s %s\n", 1505 ei_classes[ed->ehdr.e_ident[EI_CLASS]], 1506 ei_data[ed->ehdr.e_ident[EI_DATA]], 1507 ei_abis[ed->ehdr.e_ident[EI_OSABI]]); 1508 PRT("\te_type: %s\n", e_types[ed->ehdr.e_type]); 1509 PRT("\te_machine: %s\n", e_machines(ed->ehdr.e_machine)); 1510 PRT("\te_version: %s\n", ei_versions[ed->ehdr.e_version]); 1511 PRT("\te_entry: %#jx\n", (uintmax_t)ed->ehdr.e_entry); 1512 PRT("\te_phoff: %ju\n", (uintmax_t)ed->ehdr.e_phoff); 1513 PRT("\te_shoff: %ju\n", (uintmax_t) ed->ehdr.e_shoff); 1514 PRT("\te_flags: %u\n", ed->ehdr.e_flags); 1515 PRT("\te_ehsize: %u\n", ed->ehdr.e_ehsize); 1516 PRT("\te_phentsize: %u\n", ed->ehdr.e_phentsize); 1517 PRT("\te_phnum: %u\n", ed->ehdr.e_phnum); 1518 PRT("\te_shentsize: %u\n", ed->ehdr.e_shentsize); 1519 PRT("\te_shnum: %u\n", ed->ehdr.e_shnum); 1520 PRT("\te_shstrndx: %u\n", ed->ehdr.e_shstrndx); 1521 } 1522 } 1523 1524 /* 1525 * Dump the ELF Program Header Table. 1526 */ 1527 static void 1528 elf_print_phdr(struct elfdump *ed) 1529 { 1530 GElf_Phdr ph; 1531 size_t phnum; 1532 int header, i; 1533 1534 if (elf_getphnum(ed->elf, &phnum) == 0) { 1535 warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 1536 return; 1537 } 1538 header = 0; 1539 for (i = 0; (u_int64_t) i < phnum; i++) { 1540 if (gelf_getphdr(ed->elf, i, &ph) != &ph) { 1541 warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 1542 continue; 1543 } 1544 if (!STAILQ_EMPTY(&ed->snl) && 1545 find_name(ed, p_types[ph.p_type & 0x7]) == NULL) 1546 continue; 1547 if (ed->flags & SOLARIS_FMT) { 1548 PRT("\nProgram Header[%d]:\n", i); 1549 PRT(" p_vaddr: %#-14jx", (uintmax_t)ph.p_vaddr); 1550 PRT(" p_flags: [ %s ]\n", p_flags[ph.p_flags]); 1551 PRT(" p_paddr: %#-14jx", (uintmax_t)ph.p_paddr); 1552 PRT(" p_type: [ %s ]\n", p_types[ph.p_type & 0x7]); 1553 PRT(" p_filesz: %#-14jx", 1554 (uintmax_t)ph.p_filesz); 1555 PRT(" p_memsz: %#jx\n", (uintmax_t)ph.p_memsz); 1556 PRT(" p_offset: %#-14jx", 1557 (uintmax_t)ph.p_offset); 1558 PRT(" p_align: %#jx\n", (uintmax_t)ph.p_align); 1559 } else { 1560 if (!header) { 1561 PRT("\nprogram header:\n"); 1562 header = 1; 1563 } 1564 PRT("\n"); 1565 PRT("entry: %d\n", i); 1566 PRT("\tp_type: %s\n", p_types[ph.p_type & 0x7]); 1567 PRT("\tp_offset: %ju\n", (uintmax_t)ph.p_offset); 1568 PRT("\tp_vaddr: %#jx\n", (uintmax_t)ph.p_vaddr); 1569 PRT("\tp_paddr: %#jx\n", (uintmax_t)ph.p_paddr); 1570 PRT("\tp_filesz: %ju\n", (uintmax_t)ph.p_filesz); 1571 PRT("\tp_memsz: %ju\n", (uintmax_t)ph.p_memsz); 1572 PRT("\tp_flags: %s\n", p_flags[ph.p_flags]); 1573 PRT("\tp_align: %ju\n", (uintmax_t)ph.p_align); 1574 } 1575 } 1576 } 1577 1578 /* 1579 * Dump the ELF Section Header Table. 1580 */ 1581 static void 1582 elf_print_shdr(struct elfdump *ed) 1583 { 1584 struct section *s; 1585 int i; 1586 1587 if (!STAILQ_EMPTY(&ed->snl)) 1588 return; 1589 1590 if ((ed->flags & SOLARIS_FMT) == 0) 1591 PRT("\nsection header:\n"); 1592 for (i = 0; (size_t)i < ed->shnum; i++) { 1593 s = &ed->sl[i]; 1594 if (ed->flags & SOLARIS_FMT) { 1595 if (i == 0) 1596 continue; 1597 PRT("\nSection Header[%d]:", i); 1598 PRT(" sh_name: %s\n", s->name); 1599 PRT(" sh_addr: %#-14jx", (uintmax_t)s->addr); 1600 if (s->flags != 0) 1601 PRT(" sh_flags: [ %s ]\n", sh_flags(s->flags)); 1602 else 1603 PRT(" sh_flags: 0\n"); 1604 PRT(" sh_size: %#-14jx", (uintmax_t)s->sz); 1605 PRT(" sh_type: [ %s ]\n", sh_types(s->type)); 1606 PRT(" sh_offset: %#-14jx", (uintmax_t)s->off); 1607 PRT(" sh_entsize: %#jx\n", (uintmax_t)s->entsize); 1608 PRT(" sh_link: %-14u", s->link); 1609 PRT(" sh_info: %u\n", s->info); 1610 PRT(" sh_addralign: %#jx\n", (uintmax_t)s->align); 1611 } else { 1612 PRT("\n"); 1613 PRT("entry: %ju\n", (uintmax_t)i); 1614 PRT("\tsh_name: %s\n", s->name); 1615 PRT("\tsh_type: %s\n", sh_types(s->type)); 1616 PRT("\tsh_flags: %s\n", sh_flags(s->flags)); 1617 PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr); 1618 PRT("\tsh_offset: %ju\n", (uintmax_t)s->off); 1619 PRT("\tsh_size: %ju\n", (uintmax_t)s->sz); 1620 PRT("\tsh_link: %u\n", s->link); 1621 PRT("\tsh_info: %u\n", s->info); 1622 PRT("\tsh_addralign: %ju\n", (uintmax_t)s->align); 1623 PRT("\tsh_entsize: %ju\n", (uintmax_t)s->entsize); 1624 } 1625 } 1626 } 1627 1628 /* 1629 * Retrieve the content of the corresponding SHT_SUNW_versym section for 1630 * a symbol table section. 1631 */ 1632 static void 1633 get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs) 1634 { 1635 struct section *s; 1636 Elf_Data *data; 1637 int j, elferr; 1638 1639 s = NULL; 1640 for (j = 0; (size_t)j < ed->shnum; j++) { 1641 s = &ed->sl[j]; 1642 if (s->type == SHT_SUNW_versym && s->link == (uint32_t)i) 1643 break; 1644 } 1645 if ((size_t)j >= ed->shnum) { 1646 *vs = NULL; 1647 return; 1648 } 1649 (void) elf_errno(); 1650 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1651 elferr = elf_errno(); 1652 if (elferr != 0) 1653 warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1654 *vs = NULL; 1655 return; 1656 } 1657 1658 *vs = data->d_buf; 1659 *nvs = data->d_size / s->entsize; 1660 } 1661 1662 /* 1663 * Dump the symbol table section. 1664 */ 1665 static void 1666 elf_print_symtab(struct elfdump *ed, int i) 1667 { 1668 struct section *s; 1669 const char *name; 1670 uint16_t *vs; 1671 char idx[10]; 1672 Elf_Data *data; 1673 GElf_Sym sym; 1674 int len, j, elferr, nvs; 1675 1676 s = &ed->sl[i]; 1677 if (ed->flags & SOLARIS_FMT) 1678 PRT("\nSymbol Table Section: %s\n", s->name); 1679 else 1680 PRT("\nsymbol table (%s):\n", s->name); 1681 (void) elf_errno(); 1682 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1683 elferr = elf_errno(); 1684 if (elferr != 0) 1685 warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1686 return; 1687 } 1688 vs = NULL; 1689 nvs = 0; 1690 len = data->d_size / s->entsize; 1691 if (ed->flags & SOLARIS_FMT) { 1692 if (ed->ec == ELFCLASS32) 1693 PRT(" index value "); 1694 else 1695 PRT(" index value "); 1696 PRT("size type bind oth ver shndx name\n"); 1697 get_versym(ed, i, &vs, &nvs); 1698 if (vs != NULL && nvs != len) { 1699 warnx("#symbol not equal to #versym"); 1700 vs = NULL; 1701 } 1702 } 1703 for (j = 0; j < len; j++) { 1704 if (gelf_getsym(data, j, &sym) != &sym) { 1705 warnx("gelf_getsym failed: %s", elf_errmsg(-1)); 1706 continue; 1707 } 1708 name = get_string(ed, s->link, sym.st_name); 1709 if (ed->flags & SOLARIS_FMT) { 1710 snprintf(idx, sizeof(idx), "[%d]", j); 1711 if (ed->ec == ELFCLASS32) 1712 PRT("%10s ", idx); 1713 else 1714 PRT("%10s ", idx); 1715 PRT("0x%8.8jx ", (uintmax_t)sym.st_value); 1716 if (ed->ec == ELFCLASS32) 1717 PRT("0x%8.8jx ", (uintmax_t)sym.st_size); 1718 else 1719 PRT("0x%12.12jx ", (uintmax_t)sym.st_size); 1720 PRT("%s ", st_types_S[GELF_ST_TYPE(sym.st_info)]); 1721 PRT("%s ", st_bindings_S[GELF_ST_BIND(sym.st_info)]); 1722 PRT("%c ", st_others[sym.st_other]); 1723 PRT("%3u ", (vs == NULL ? 0 : vs[j])); 1724 PRT("%-11.11s ", sh_name(ed, sym.st_shndx)); 1725 PRT("%s\n", name); 1726 } else { 1727 PRT("\nentry: %d\n", j); 1728 PRT("\tst_name: %s\n", name); 1729 PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value); 1730 PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size); 1731 PRT("\tst_info: %s %s\n", 1732 st_types[GELF_ST_TYPE(sym.st_info)], 1733 st_bindings[GELF_ST_BIND(sym.st_info)]); 1734 PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx); 1735 } 1736 } 1737 } 1738 1739 /* 1740 * Dump the symbol tables. (.dynsym and .symtab) 1741 */ 1742 static void 1743 elf_print_symtabs(struct elfdump *ed) 1744 { 1745 int i; 1746 1747 for (i = 0; (size_t)i < ed->shnum; i++) 1748 if ((ed->sl[i].type == SHT_SYMTAB || 1749 ed->sl[i].type == SHT_DYNSYM) && 1750 (STAILQ_EMPTY(&ed->snl) || find_name(ed, ed->sl[i].name))) 1751 elf_print_symtab(ed, i); 1752 } 1753 1754 /* 1755 * Dump the content of .dynamic section. 1756 */ 1757 static void 1758 elf_print_dynamic(struct elfdump *ed) 1759 { 1760 struct section *s; 1761 const char *name; 1762 char idx[10]; 1763 Elf_Data *data; 1764 GElf_Dyn dyn; 1765 int elferr, i, len; 1766 1767 s = NULL; 1768 for (i = 0; (size_t)i < ed->shnum; i++) { 1769 s = &ed->sl[i]; 1770 if (s->type == SHT_DYNAMIC && 1771 (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 1772 break; 1773 } 1774 if ((size_t)i >= ed->shnum) 1775 return; 1776 1777 if (ed->flags & SOLARIS_FMT) { 1778 PRT("Dynamic Section: %s\n", s->name); 1779 PRT(" index tag value\n"); 1780 } else 1781 PRT("\ndynamic:\n"); 1782 (void) elf_errno(); 1783 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1784 elferr = elf_errno(); 1785 if (elferr != 0) 1786 warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 1787 return; 1788 } 1789 len = data->d_size / s->entsize; 1790 for (i = 0; i < len; i++) { 1791 if (gelf_getdyn(data, i, &dyn) != &dyn) { 1792 warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); 1793 continue; 1794 } 1795 1796 if (ed->flags & SOLARIS_FMT) { 1797 snprintf(idx, sizeof(idx), "[%d]", i); 1798 PRT("%10s %-16s ", idx, d_tags(dyn.d_tag)); 1799 } else { 1800 PRT("\n"); 1801 PRT("entry: %d\n", i); 1802 PRT("\td_tag: %s\n", d_tags(dyn.d_tag)); 1803 } 1804 switch(dyn.d_tag) { 1805 case DT_NEEDED: 1806 case DT_SONAME: 1807 case DT_RPATH: 1808 if ((name = elf_strptr(ed->elf, s->link, 1809 dyn.d_un.d_val)) == NULL) 1810 name = ""; 1811 if (ed->flags & SOLARIS_FMT) 1812 PRT("%#-16jx %s\n", (uintmax_t)dyn.d_un.d_val, 1813 name); 1814 else 1815 PRT("\td_val: %s\n", name); 1816 break; 1817 case DT_PLTRELSZ: 1818 case DT_RELA: 1819 case DT_RELASZ: 1820 case DT_RELAENT: 1821 case DT_RELACOUNT: 1822 case DT_STRSZ: 1823 case DT_SYMENT: 1824 case DT_RELSZ: 1825 case DT_RELENT: 1826 case DT_PLTREL: 1827 case DT_VERDEF: 1828 case DT_VERDEFNUM: 1829 case DT_VERNEED: 1830 case DT_VERNEEDNUM: 1831 case DT_VERSYM: 1832 if (ed->flags & SOLARIS_FMT) 1833 PRT("%#jx\n", (uintmax_t)dyn.d_un.d_val); 1834 else 1835 PRT("\td_val: %ju\n", 1836 (uintmax_t)dyn.d_un.d_val); 1837 break; 1838 case DT_PLTGOT: 1839 case DT_HASH: 1840 case DT_GNU_HASH: 1841 case DT_STRTAB: 1842 case DT_SYMTAB: 1843 case DT_INIT: 1844 case DT_FINI: 1845 case DT_REL: 1846 case DT_JMPREL: 1847 case DT_DEBUG: 1848 if (ed->flags & SOLARIS_FMT) 1849 PRT("%#jx\n", (uintmax_t)dyn.d_un.d_ptr); 1850 else 1851 PRT("\td_ptr: %#jx\n", 1852 (uintmax_t)dyn.d_un.d_ptr); 1853 break; 1854 case DT_NULL: 1855 case DT_SYMBOLIC: 1856 case DT_TEXTREL: 1857 default: 1858 if (ed->flags & SOLARIS_FMT) 1859 PRT("\n"); 1860 break; 1861 } 1862 } 1863 } 1864 1865 /* 1866 * Dump a .rel/.rela section entry. 1867 */ 1868 static void 1869 elf_print_rel_entry(struct elfdump *ed, struct section *s, int j, 1870 struct rel_entry *r) 1871 { 1872 1873 if (ed->flags & SOLARIS_FMT) { 1874 PRT(" %-23s ", r_type(ed->ehdr.e_machine, 1875 GELF_R_TYPE(r->u_r.rel.r_info))); 1876 PRT("%#12jx ", (uintmax_t)r->u_r.rel.r_offset); 1877 if (r->type == SHT_RELA) 1878 PRT("%10jd ", (intmax_t)r->u_r.rela.r_addend); 1879 else 1880 PRT(" "); 1881 PRT("%-14s ", s->name); 1882 PRT("%s\n", r->symn); 1883 } else { 1884 PRT("\n"); 1885 PRT("entry: %d\n", j); 1886 PRT("\tr_offset: %#jx\n", (uintmax_t)r->u_r.rel.r_offset); 1887 if (ed->ec == ELFCLASS32) 1888 PRT("\tr_info: %#jx\n", (uintmax_t) 1889 ELF32_R_INFO(ELF64_R_SYM(r->u_r.rel.r_info), 1890 ELF64_R_TYPE(r->u_r.rel.r_info))); 1891 else 1892 PRT("\tr_info: %#jx\n", (uintmax_t)r->u_r.rel.r_info); 1893 if (r->type == SHT_RELA) 1894 PRT("\tr_addend: %jd\n", 1895 (intmax_t)r->u_r.rela.r_addend); 1896 } 1897 } 1898 1899 /* 1900 * Dump a relocation section of type SHT_RELA. 1901 */ 1902 static void 1903 elf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data) 1904 { 1905 struct rel_entry r; 1906 int j, len; 1907 1908 if (ed->flags & SOLARIS_FMT) { 1909 PRT("\nRelocation Section: %s\n", s->name); 1910 PRT(" type offset " 1911 "addend section with respect to\n"); 1912 } else 1913 PRT("\nrelocation with addend (%s):\n", s->name); 1914 r.type = SHT_RELA; 1915 len = data->d_size / s->entsize; 1916 for (j = 0; j < len; j++) { 1917 if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) { 1918 warnx("gelf_getrela failed: %s", 1919 elf_errmsg(-1)); 1920 continue; 1921 } 1922 r.symn = get_symbol_name(ed, s->link, 1923 GELF_R_SYM(r.u_r.rela.r_info)); 1924 elf_print_rel_entry(ed, s, j, &r); 1925 } 1926 } 1927 1928 /* 1929 * Dump a relocation section of type SHT_REL. 1930 */ 1931 static void 1932 elf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data) 1933 { 1934 struct rel_entry r; 1935 int j, len; 1936 1937 if (ed->flags & SOLARIS_FMT) { 1938 PRT("\nRelocation Section: %s\n", s->name); 1939 PRT(" type offset " 1940 "section with respect to\n"); 1941 } else 1942 PRT("\nrelocation (%s):\n", s->name); 1943 r.type = SHT_REL; 1944 len = data->d_size / s->entsize; 1945 for (j = 0; j < len; j++) { 1946 if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) { 1947 warnx("gelf_getrel failed: %s", elf_errmsg(-1)); 1948 continue; 1949 } 1950 r.symn = get_symbol_name(ed, s->link, 1951 GELF_R_SYM(r.u_r.rel.r_info)); 1952 elf_print_rel_entry(ed, s, j, &r); 1953 } 1954 } 1955 1956 /* 1957 * Dump relocation sections. 1958 */ 1959 static void 1960 elf_print_reloc(struct elfdump *ed) 1961 { 1962 struct section *s; 1963 Elf_Data *data; 1964 int i, elferr; 1965 1966 for (i = 0; (size_t)i < ed->shnum; i++) { 1967 s = &ed->sl[i]; 1968 if ((s->type == SHT_REL || s->type == SHT_RELA) && 1969 (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 1970 (void) elf_errno(); 1971 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 1972 elferr = elf_errno(); 1973 if (elferr != 0) 1974 warnx("elf_getdata failed: %s", 1975 elf_errmsg(elferr)); 1976 continue; 1977 } 1978 if (s->type == SHT_REL) 1979 elf_print_rel(ed, s, data); 1980 else 1981 elf_print_rela(ed, s, data); 1982 } 1983 } 1984 } 1985 1986 /* 1987 * Dump the content of PT_INTERP segment. 1988 */ 1989 static void 1990 elf_print_interp(struct elfdump *ed) 1991 { 1992 const char *s; 1993 GElf_Phdr phdr; 1994 size_t phnum; 1995 int i; 1996 1997 if (!STAILQ_EMPTY(&ed->snl) && find_name(ed, "PT_INTERP") == NULL) 1998 return; 1999 2000 if ((s = elf_rawfile(ed->elf, NULL)) == NULL) { 2001 warnx("elf_rawfile failed: %s", elf_errmsg(-1)); 2002 return; 2003 } 2004 if (!elf_getphnum(ed->elf, &phnum)) { 2005 warnx("elf_getphnum failed: %s", elf_errmsg(-1)); 2006 return; 2007 } 2008 for (i = 0; (size_t)i < phnum; i++) { 2009 if (gelf_getphdr(ed->elf, i, &phdr) != &phdr) { 2010 warnx("elf_getphdr failed: %s", elf_errmsg(-1)); 2011 continue; 2012 } 2013 if (phdr.p_type == PT_INTERP) { 2014 PRT("\ninterp:\n"); 2015 PRT("\t%s\n", s + phdr.p_offset); 2016 } 2017 } 2018 } 2019 2020 /* 2021 * Search the relocation sections for entries refering to the .got section. 2022 */ 2023 static void 2024 find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got) 2025 { 2026 struct section *s; 2027 struct rel_entry r; 2028 Elf_Data *data; 2029 int elferr, i, j, k, len; 2030 2031 for(i = 0; (size_t)i < ed->shnum; i++) { 2032 s = &ed->sl[i]; 2033 if (s->type != SHT_REL && s->type != SHT_RELA) 2034 continue; 2035 (void) elf_errno(); 2036 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2037 elferr = elf_errno(); 2038 if (elferr != 0) 2039 warnx("elf_getdata failed: %s", 2040 elf_errmsg(elferr)); 2041 return; 2042 } 2043 memset(&r, 0, sizeof(struct rel_entry)); 2044 r.type = s->type; 2045 len = data->d_size / s->entsize; 2046 for (j = 0; j < len; j++) { 2047 if (s->type == SHT_REL) { 2048 if (gelf_getrel(data, j, &r.u_r.rel) != 2049 &r.u_r.rel) { 2050 warnx("gelf_getrel failed: %s", 2051 elf_errmsg(-1)); 2052 continue; 2053 } 2054 } else { 2055 if (gelf_getrela(data, j, &r.u_r.rela) != 2056 &r.u_r.rela) { 2057 warnx("gelf_getrel failed: %s", 2058 elf_errmsg(-1)); 2059 continue; 2060 } 2061 } 2062 if (r.u_r.rel.r_offset >= gs->addr && 2063 r.u_r.rel.r_offset < gs->addr + gs->sz) { 2064 r.symn = get_symbol_name(ed, s->link, 2065 GELF_R_SYM(r.u_r.rel.r_info)); 2066 k = (r.u_r.rel.r_offset - gs->addr) / 2067 gs->entsize; 2068 memcpy(&got[k], &r, sizeof(struct rel_entry)); 2069 } 2070 } 2071 } 2072 } 2073 2074 static void 2075 elf_print_got_section(struct elfdump *ed, struct section *s) 2076 { 2077 struct rel_entry *got; 2078 Elf_Data *data, dst; 2079 int elferr, i, len; 2080 2081 if (s->entsize == 0) { 2082 /* XXX IA64 GOT section generated by gcc has entry size 0. */ 2083 if (s->align != 0) 2084 s->entsize = s->align; 2085 else 2086 return; 2087 } 2088 2089 if (ed->flags & SOLARIS_FMT) 2090 PRT("\nGlobal Offset Table Section: %s (%jd entries)\n", 2091 s->name, s->sz / s->entsize); 2092 else 2093 PRT("\nglobal offset table: %s\n", s->name); 2094 (void) elf_errno(); 2095 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2096 elferr = elf_errno(); 2097 if (elferr != 0) 2098 warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 2099 return; 2100 } 2101 2102 /* 2103 * GOT section has section type SHT_PROGBITS, thus libelf treats it as 2104 * byte stream and will not perfrom any translation on it. As a result, 2105 * an exlicit call to gelf_xlatetom is needed here. Depends on arch, 2106 * GOT section should be translated to either WORD or XWORD. 2107 */ 2108 if (ed->ec == ELFCLASS32) 2109 data->d_type = ELF_T_WORD; 2110 else 2111 data->d_type = ELF_T_XWORD; 2112 memcpy(&dst, data, sizeof(Elf_Data)); 2113 if (gelf_xlatetom(ed->elf, &dst, data, ed->ehdr.e_ident[EI_DATA]) != 2114 &dst) { 2115 warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 2116 return; 2117 } 2118 len = dst.d_size / s->entsize; 2119 if (ed->flags & SOLARIS_FMT) { 2120 /* 2121 * In verbose/Solaris mode, we search the relocation sections 2122 * and try to find the corresponding reloc entry for each GOT 2123 * section entry. 2124 */ 2125 if ((got = calloc(len, sizeof(struct rel_entry))) == NULL) 2126 err(EXIT_FAILURE, "calloc failed"); 2127 find_gotrel(ed, s, got); 2128 if (ed->ec == ELFCLASS32) { 2129 PRT(" ndx addr value reloc "); 2130 PRT("addend symbol\n"); 2131 } else { 2132 PRT(" ndx addr value "); 2133 PRT("reloc addend symbol\n"); 2134 } 2135 for(i = 0; i < len; i++) { 2136 PRT("[%5.5d] ", i); 2137 if (ed->ec == ELFCLASS32) { 2138 PRT("%-8.8jx ", s->addr + i * s->entsize); 2139 PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i)); 2140 } else { 2141 PRT("%-16.16jx ", s->addr + i * s->entsize); 2142 PRT("%-16.16jx ", *((uint64_t *)dst.d_buf + i)); 2143 } 2144 PRT("%-18s ", r_type(ed->ehdr.e_machine, 2145 GELF_R_TYPE(got[i].u_r.rel.r_info))); 2146 if (ed->ec == ELFCLASS32) 2147 PRT("%-8.8jd ", 2148 (intmax_t)got[i].u_r.rela.r_addend); 2149 else 2150 PRT("%-12.12jd ", 2151 (intmax_t)got[i].u_r.rela.r_addend); 2152 if (got[i].symn == NULL) 2153 got[i].symn = ""; 2154 PRT("%s\n", got[i].symn); 2155 } 2156 free(got); 2157 } else { 2158 for(i = 0; i < len; i++) { 2159 PRT("\nentry: %d\n", i); 2160 if (ed->ec == ELFCLASS32) 2161 PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i)); 2162 else 2163 PRT("\t%#jx\n", *((uint64_t *)dst.d_buf + i)); 2164 } 2165 } 2166 } 2167 2168 /* 2169 * Dump the content of Global Offset Table section. 2170 */ 2171 static void 2172 elf_print_got(struct elfdump *ed) 2173 { 2174 struct section *s; 2175 int i; 2176 2177 if (!STAILQ_EMPTY(&ed->snl)) 2178 return; 2179 2180 s = NULL; 2181 for (i = 0; (size_t)i < ed->shnum; i++) { 2182 s = &ed->sl[i]; 2183 if (s->name && !strncmp(s->name, ".got", 4) && 2184 (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 2185 elf_print_got_section(ed, s); 2186 } 2187 } 2188 2189 /* 2190 * Dump the content of .note.ABI-tag section. 2191 */ 2192 static void 2193 elf_print_note(struct elfdump *ed) 2194 { 2195 struct section *s; 2196 Elf_Data *data; 2197 Elf_Note *en; 2198 uint32_t namesz; 2199 uint32_t descsz; 2200 uint32_t desc; 2201 size_t count; 2202 int elferr, i; 2203 char *src, idx[10]; 2204 2205 s = NULL; 2206 for (i = 0; (size_t)i < ed->shnum; i++) { 2207 s = &ed->sl[i]; 2208 if (s->type == SHT_NOTE && s->name && 2209 !strcmp(s->name, ".note.ABI-tag") && 2210 (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) 2211 break; 2212 } 2213 if ((size_t)i >= ed->shnum) 2214 return; 2215 if (ed->flags & SOLARIS_FMT) 2216 PRT("\nNote Section: %s\n", s->name); 2217 else 2218 PRT("\nnote (%s):\n", s->name); 2219 (void) elf_errno(); 2220 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2221 elferr = elf_errno(); 2222 if (elferr != 0) 2223 warnx("elf_getdata failed: %s", elf_errmsg(elferr)); 2224 return; 2225 } 2226 src = data->d_buf; 2227 count = data->d_size; 2228 while (count > sizeof(Elf_Note)) { 2229 en = (Elf_Note *) (uintptr_t) src; 2230 namesz = en->n_namesz; 2231 descsz = en->n_descsz; 2232 src += sizeof(Elf_Note); 2233 count -= sizeof(Elf_Note); 2234 if (ed->flags & SOLARIS_FMT) { 2235 PRT("\n type %#x\n", en->n_type); 2236 PRT(" namesz %#x:\n", en->n_namesz); 2237 PRT("%s\n", src); 2238 } else 2239 PRT("\t%s ", src); 2240 src += roundup2(namesz, 4); 2241 count -= roundup2(namesz, 4); 2242 2243 /* 2244 * Note that we dump the whole desc part if we're in 2245 * "Solaris mode", while in the normal mode, we only look 2246 * at the first 4 bytes (a 32bit word) of the desc, i.e, 2247 * we assume that it's always a FreeBSD version number. 2248 */ 2249 if (ed->flags & SOLARIS_FMT) { 2250 PRT(" descsz %#x:", en->n_descsz); 2251 for (i = 0; (uint32_t)i < descsz; i++) { 2252 if ((i & 0xF) == 0) { 2253 snprintf(idx, sizeof(idx), "desc[%d]", 2254 i); 2255 PRT("\n %-9s", idx); 2256 } else if ((i & 0x3) == 0) 2257 PRT(" "); 2258 PRT(" %2.2x", src[i]); 2259 } 2260 PRT("\n"); 2261 } else { 2262 if (ed->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) 2263 desc = be32dec(src); 2264 else 2265 desc = le32dec(src); 2266 PRT("%d\n", desc); 2267 } 2268 src += roundup2(descsz, 4); 2269 count -= roundup2(descsz, 4); 2270 } 2271 } 2272 2273 /* 2274 * Dump a hash table. 2275 */ 2276 static void 2277 elf_print_svr4_hash(struct elfdump *ed, struct section *s) 2278 { 2279 Elf_Data *data; 2280 uint32_t *buf; 2281 uint32_t *bucket, *chain; 2282 uint32_t nbucket, nchain; 2283 uint32_t *bl, *c, maxl, total; 2284 int i, j, first, elferr; 2285 char idx[10]; 2286 2287 if (ed->flags & SOLARIS_FMT) 2288 PRT("\nHash Section: %s\n", s->name); 2289 else 2290 PRT("\nhash table (%s):\n", s->name); 2291 (void) elf_errno(); 2292 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2293 elferr = elf_errno(); 2294 if (elferr != 0) 2295 warnx("elf_getdata failed: %s", 2296 elf_errmsg(elferr)); 2297 return; 2298 } 2299 if (data->d_size < 2 * sizeof(uint32_t)) { 2300 warnx(".hash section too small"); 2301 return; 2302 } 2303 buf = data->d_buf; 2304 nbucket = buf[0]; 2305 nchain = buf[1]; 2306 if (nbucket <= 0 || nchain <= 0) { 2307 warnx("Malformed .hash section"); 2308 return; 2309 } 2310 if (data->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) { 2311 warnx("Malformed .hash section"); 2312 return; 2313 } 2314 bucket = &buf[2]; 2315 chain = &buf[2 + nbucket]; 2316 2317 if (ed->flags & SOLARIS_FMT) { 2318 maxl = 0; 2319 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 2320 err(EXIT_FAILURE, "calloc failed"); 2321 for (i = 0; (uint32_t)i < nbucket; i++) 2322 for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; 2323 j = chain[j]) 2324 if (++bl[i] > maxl) 2325 maxl = bl[i]; 2326 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 2327 err(EXIT_FAILURE, "calloc failed"); 2328 for (i = 0; (uint32_t)i < nbucket; i++) 2329 c[bl[i]]++; 2330 PRT(" bucket symndx name\n"); 2331 for (i = 0; (uint32_t)i < nbucket; i++) { 2332 first = 1; 2333 for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; 2334 j = chain[j]) { 2335 if (first) { 2336 PRT("%10d ", i); 2337 first = 0; 2338 } else 2339 PRT(" "); 2340 snprintf(idx, sizeof(idx), "[%d]", j); 2341 PRT("%-10s ", idx); 2342 PRT("%s\n", get_symbol_name(ed, s->link, j)); 2343 } 2344 } 2345 PRT("\n"); 2346 total = 0; 2347 for (i = 0; (uint32_t)i <= maxl; i++) { 2348 total += c[i] * i; 2349 PRT("%10u buckets contain %8d symbols\n", c[i], i); 2350 } 2351 PRT("%10u buckets %8u symbols (globals)\n", nbucket, 2352 total); 2353 } else { 2354 PRT("\nnbucket: %u\n", nbucket); 2355 PRT("nchain: %u\n\n", nchain); 2356 for (i = 0; (uint32_t)i < nbucket; i++) 2357 PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 2358 for (i = 0; (uint32_t)i < nchain; i++) 2359 PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 2360 } 2361 } 2362 2363 /* 2364 * Dump a 64bit hash table. 2365 */ 2366 static void 2367 elf_print_svr4_hash64(struct elfdump *ed, struct section *s) 2368 { 2369 Elf_Data *data, dst; 2370 uint64_t *buf; 2371 uint64_t *bucket, *chain; 2372 uint64_t nbucket, nchain; 2373 uint64_t *bl, *c, maxl, total; 2374 int i, j, elferr, first; 2375 char idx[10]; 2376 2377 if (ed->flags & SOLARIS_FMT) 2378 PRT("\nHash Section: %s\n", s->name); 2379 else 2380 PRT("\nhash table (%s):\n", s->name); 2381 2382 /* 2383 * ALPHA uses 64-bit hash entries. Since libelf assumes that 2384 * .hash section contains only 32-bit entry, an explicit 2385 * gelf_xlatetom is needed here. 2386 */ 2387 (void) elf_errno(); 2388 if ((data = elf_rawdata(s->scn, NULL)) == NULL) { 2389 elferr = elf_errno(); 2390 if (elferr != 0) 2391 warnx("elf_rawdata failed: %s", 2392 elf_errmsg(elferr)); 2393 return; 2394 } 2395 data->d_type = ELF_T_XWORD; 2396 memcpy(&dst, data, sizeof(Elf_Data)); 2397 if (gelf_xlatetom(ed->elf, &dst, data, 2398 ed->ehdr.e_ident[EI_DATA]) != &dst) { 2399 warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); 2400 return; 2401 } 2402 if (dst.d_size < 2 * sizeof(uint64_t)) { 2403 warnx(".hash section too small"); 2404 return; 2405 } 2406 buf = dst.d_buf; 2407 nbucket = buf[0]; 2408 nchain = buf[1]; 2409 if (nbucket <= 0 || nchain <= 0) { 2410 warnx("Malformed .hash section"); 2411 return; 2412 } 2413 if (dst.d_size != (nbucket + nchain + 2) * sizeof(uint64_t)) { 2414 warnx("Malformed .hash section"); 2415 return; 2416 } 2417 bucket = &buf[2]; 2418 chain = &buf[2 + nbucket]; 2419 2420 if (ed->flags & SOLARIS_FMT) { 2421 maxl = 0; 2422 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 2423 err(EXIT_FAILURE, "calloc failed"); 2424 for (i = 0; (uint64_t)i < nbucket; i++) 2425 for (j = bucket[i]; j > 0 && (uint64_t)j < nchain; 2426 j = chain[j]) 2427 if (++bl[i] > maxl) 2428 maxl = bl[i]; 2429 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 2430 err(EXIT_FAILURE, "calloc failed"); 2431 for (i = 0; (uint64_t)i < nbucket; i++) 2432 c[bl[i]]++; 2433 PRT(" bucket symndx name\n"); 2434 for (i = 0; (uint64_t)i < nbucket; i++) { 2435 first = 1; 2436 for (j = bucket[i]; j > 0 && (uint64_t)j < nchain; 2437 j = chain[j]) { 2438 if (first) { 2439 PRT("%10d ", i); 2440 first = 0; 2441 } else 2442 PRT(" "); 2443 snprintf(idx, sizeof(idx), "[%d]", j); 2444 PRT("%-10s ", idx); 2445 PRT("%s\n", get_symbol_name(ed, s->link, j)); 2446 } 2447 } 2448 PRT("\n"); 2449 total = 0; 2450 for (i = 0; (uint64_t)i <= maxl; i++) { 2451 total += c[i] * i; 2452 PRT("%10ju buckets contain %8d symbols\n", 2453 (uintmax_t)c[i], i); 2454 } 2455 PRT("%10ju buckets %8ju symbols (globals)\n", 2456 (uintmax_t)nbucket, (uintmax_t)total); 2457 } else { 2458 PRT("\nnbucket: %ju\n", (uintmax_t)nbucket); 2459 PRT("nchain: %ju\n\n", (uintmax_t)nchain); 2460 for (i = 0; (uint64_t)i < nbucket; i++) 2461 PRT("bucket[%d]:\n\t%ju\n\n", i, (uintmax_t)bucket[i]); 2462 for (i = 0; (uint64_t)i < nchain; i++) 2463 PRT("chain[%d]:\n\t%ju\n\n", i, (uintmax_t)chain[i]); 2464 } 2465 2466 } 2467 2468 /* 2469 * Dump a GNU hash table. 2470 */ 2471 static void 2472 elf_print_gnu_hash(struct elfdump *ed, struct section *s) 2473 { 2474 struct section *ds; 2475 Elf_Data *data; 2476 uint32_t *buf; 2477 uint32_t *bucket, *chain; 2478 uint32_t nbucket, nchain, symndx, maskwords, shift2; 2479 uint32_t *bl, *c, maxl, total; 2480 int i, j, first, elferr, dynsymcount; 2481 char idx[10]; 2482 2483 if (ed->flags & SOLARIS_FMT) 2484 PRT("\nGNU Hash Section: %s\n", s->name); 2485 else 2486 PRT("\ngnu hash table (%s):\n", s->name); 2487 (void) elf_errno(); 2488 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2489 elferr = elf_errno(); 2490 if (elferr != 0) 2491 warnx("elf_getdata failed: %s", 2492 elf_errmsg(elferr)); 2493 return; 2494 } 2495 if (data->d_size < 4 * sizeof(uint32_t)) { 2496 warnx(".gnu.hash section too small"); 2497 return; 2498 } 2499 buf = data->d_buf; 2500 nbucket = buf[0]; 2501 symndx = buf[1]; 2502 maskwords = buf[2]; 2503 shift2 = buf[3]; 2504 buf += 4; 2505 ds = &ed->sl[s->link]; 2506 dynsymcount = ds->sz / ds->entsize; 2507 nchain = dynsymcount - symndx; 2508 if (data->d_size != 4 * sizeof(uint32_t) + maskwords * 2509 (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + 2510 (nbucket + nchain) * sizeof(uint32_t)) { 2511 warnx("Malformed .gnu.hash section"); 2512 return; 2513 } 2514 bucket = buf + (ed->ec == ELFCLASS32 ? maskwords : maskwords * 2); 2515 chain = bucket + nbucket; 2516 2517 if (ed->flags & SOLARIS_FMT) { 2518 maxl = 0; 2519 if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) 2520 err(EXIT_FAILURE, "calloc failed"); 2521 for (i = 0; (uint32_t)i < nbucket; i++) 2522 for (j = bucket[i]; 2523 j > 0 && (uint32_t)j - symndx < nchain; 2524 j++) { 2525 if (++bl[i] > maxl) 2526 maxl = bl[i]; 2527 if (chain[j - symndx] & 1) 2528 break; 2529 } 2530 if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) 2531 err(EXIT_FAILURE, "calloc failed"); 2532 for (i = 0; (uint32_t)i < nbucket; i++) 2533 c[bl[i]]++; 2534 PRT(" bucket symndx name\n"); 2535 for (i = 0; (uint32_t)i < nbucket; i++) { 2536 first = 1; 2537 for (j = bucket[i]; 2538 j > 0 && (uint32_t)j - symndx < nchain; 2539 j++) { 2540 if (first) { 2541 PRT("%10d ", i); 2542 first = 0; 2543 } else 2544 PRT(" "); 2545 snprintf(idx, sizeof(idx), "[%d]", j ); 2546 PRT("%-10s ", idx); 2547 PRT("%s\n", get_symbol_name(ed, s->link, j)); 2548 if (chain[j - symndx] & 1) 2549 break; 2550 } 2551 } 2552 PRT("\n"); 2553 total = 0; 2554 for (i = 0; (uint32_t)i <= maxl; i++) { 2555 total += c[i] * i; 2556 PRT("%10u buckets contain %8d symbols\n", c[i], i); 2557 } 2558 PRT("%10u buckets %8u symbols (globals)\n", nbucket, 2559 total); 2560 } else { 2561 PRT("\nnbucket: %u\n", nbucket); 2562 PRT("symndx: %u\n", symndx); 2563 PRT("maskwords: %u\n", maskwords); 2564 PRT("shift2: %u\n", shift2); 2565 PRT("nchain: %u\n\n", nchain); 2566 for (i = 0; (uint32_t)i < nbucket; i++) 2567 PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]); 2568 for (i = 0; (uint32_t)i < nchain; i++) 2569 PRT("chain[%d]:\n\t%u\n\n", i, chain[i]); 2570 } 2571 } 2572 2573 /* 2574 * Dump hash tables. 2575 */ 2576 static void 2577 elf_print_hash(struct elfdump *ed) 2578 { 2579 struct section *s; 2580 int i; 2581 2582 for (i = 0; (size_t)i < ed->shnum; i++) { 2583 s = &ed->sl[i]; 2584 if ((s->type == SHT_HASH || s->type == SHT_GNU_HASH) && 2585 (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) { 2586 if (s->type == SHT_GNU_HASH) 2587 elf_print_gnu_hash(ed, s); 2588 else if (ed->ehdr.e_machine == EM_ALPHA && 2589 s->entsize == 8) 2590 elf_print_svr4_hash64(ed, s); 2591 else 2592 elf_print_svr4_hash(ed, s); 2593 } 2594 } 2595 } 2596 2597 /* 2598 * Dump the content of a Version Definition(SHT_SUNW_Verdef) Section. 2599 */ 2600 static void 2601 elf_print_verdef(struct elfdump *ed, struct section *s) 2602 { 2603 Elf_Data *data; 2604 Elf32_Verdef *vd; 2605 Elf32_Verdaux *vda; 2606 const char *str; 2607 char idx[10]; 2608 uint8_t *buf, *end, *buf2; 2609 int i, j, elferr, count; 2610 2611 if (ed->flags & SOLARIS_FMT) 2612 PRT("Version Definition Section: %s\n", s->name); 2613 else 2614 PRT("\nversion definition section (%s):\n", s->name); 2615 (void) elf_errno(); 2616 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2617 elferr = elf_errno(); 2618 if (elferr != 0) 2619 warnx("elf_getdata failed: %s", 2620 elf_errmsg(elferr)); 2621 return; 2622 } 2623 buf = data->d_buf; 2624 end = buf + data->d_size; 2625 i = 0; 2626 if (ed->flags & SOLARIS_FMT) 2627 PRT(" index version dependency\n"); 2628 while (buf + sizeof(Elf32_Verdef) <= end) { 2629 vd = (Elf32_Verdef *) (uintptr_t) buf; 2630 if (ed->flags & SOLARIS_FMT) { 2631 snprintf(idx, sizeof(idx), "[%d]", vd->vd_ndx); 2632 PRT("%10s ", idx); 2633 } else { 2634 PRT("\nentry: %d\n", i++); 2635 PRT("\tvd_version: %u\n", vd->vd_version); 2636 PRT("\tvd_flags: %u\n", vd->vd_flags); 2637 PRT("\tvd_ndx: %u\n", vd->vd_ndx); 2638 PRT("\tvd_cnt: %u\n", vd->vd_cnt); 2639 PRT("\tvd_hash: %u\n", vd->vd_hash); 2640 PRT("\tvd_aux: %u\n", vd->vd_aux); 2641 PRT("\tvd_next: %u\n\n", vd->vd_next); 2642 } 2643 buf2 = buf + vd->vd_aux; 2644 j = 0; 2645 count = 0; 2646 while (buf2 + sizeof(Elf32_Verdaux) <= end && j < vd->vd_cnt) { 2647 vda = (Elf32_Verdaux *) (uintptr_t) buf2; 2648 str = get_string(ed, s->link, vda->vda_name); 2649 if (ed->flags & SOLARIS_FMT) { 2650 if (count == 0) 2651 PRT("%-26.26s", str); 2652 else if (count == 1) 2653 PRT(" %-20.20s", str); 2654 else { 2655 PRT("\n%40.40s", ""); 2656 PRT("%s", str); 2657 } 2658 } else { 2659 PRT("\t\tvda: %d\n", j++); 2660 PRT("\t\t\tvda_name: %s\n", str); 2661 PRT("\t\t\tvda_next: %u\n", vda->vda_next); 2662 } 2663 if (vda->vda_next == 0) { 2664 if (ed->flags & SOLARIS_FMT) { 2665 if (vd->vd_flags & VER_FLG_BASE) { 2666 if (count == 0) 2667 PRT("%-20.20s", ""); 2668 PRT("%s", "[ BASE ]"); 2669 } 2670 PRT("\n"); 2671 } 2672 break; 2673 } 2674 if (ed->flags & SOLARIS_FMT) 2675 count++; 2676 buf2 += vda->vda_next; 2677 } 2678 if (vd->vd_next == 0) 2679 break; 2680 buf += vd->vd_next; 2681 } 2682 } 2683 2684 /* 2685 * Dump the content of a Version Needed(SHT_SUNW_Verneed) Section. 2686 */ 2687 static void 2688 elf_print_verneed(struct elfdump *ed, struct section *s) 2689 { 2690 Elf_Data *data; 2691 Elf32_Verneed *vn; 2692 Elf32_Vernaux *vna; 2693 uint8_t *buf, *end, *buf2; 2694 int i, j, elferr, first; 2695 2696 if (ed->flags & SOLARIS_FMT) 2697 PRT("\nVersion Needed Section: %s\n", s->name); 2698 else 2699 PRT("\nversion need section (%s):\n", s->name); 2700 (void) elf_errno(); 2701 if ((data = elf_getdata(s->scn, NULL)) == NULL) { 2702 elferr = elf_errno(); 2703 if (elferr != 0) 2704 warnx("elf_getdata failed: %s", 2705 elf_errmsg(elferr)); 2706 return; 2707 } 2708 buf = data->d_buf; 2709 end = buf + data->d_size; 2710 if (ed->flags & SOLARIS_FMT) 2711 PRT(" file version\n"); 2712 i = 0; 2713 while (buf + sizeof(Elf32_Verneed) <= end) { 2714 vn = (Elf32_Verneed *) (uintptr_t) buf; 2715 if (ed->flags & SOLARIS_FMT) 2716 PRT(" %-26.26s ", 2717 get_string(ed, s->link, vn->vn_file)); 2718 else { 2719 PRT("\nentry: %d\n", i++); 2720 PRT("\tvn_version: %u\n", vn->vn_version); 2721 PRT("\tvn_cnt: %u\n", vn->vn_cnt); 2722 PRT("\tvn_file: %s\n", 2723 get_string(ed, s->link, vn->vn_file)); 2724 PRT("\tvn_aux: %u\n", vn->vn_aux); 2725 PRT("\tvn_next: %u\n\n", vn->vn_next); 2726 } 2727 buf2 = buf + vn->vn_aux; 2728 j = 0; 2729 first = 1; 2730 while (buf2 + sizeof(Elf32_Vernaux) <= end && j < vn->vn_cnt) { 2731 vna = (Elf32_Vernaux *) (uintptr_t) buf2; 2732 if (ed->flags & SOLARIS_FMT) { 2733 if (!first) 2734 PRT("%40.40s", ""); 2735 else 2736 first = 0; 2737 PRT("%s\n", get_string(ed, s->link, 2738 vna->vna_name)); 2739 } else { 2740 PRT("\t\tvna: %d\n", j++); 2741 PRT("\t\t\tvna_hash: %u\n", vna->vna_hash); 2742 PRT("\t\t\tvna_flags: %u\n", vna->vna_flags); 2743 PRT("\t\t\tvna_other: %u\n", vna->vna_other); 2744 PRT("\t\t\tvna_name: %s\n", 2745 get_string(ed, s->link, vna->vna_name)); 2746 PRT("\t\t\tvna_next: %u\n", vna->vna_next); 2747 } 2748 if (vna->vna_next == 0) 2749 break; 2750 buf2 += vna->vna_next; 2751 } 2752 if (vn->vn_next == 0) 2753 break; 2754 buf += vn->vn_next; 2755 } 2756 } 2757 2758 /* 2759 * Dump the symbol-versioning sections. 2760 */ 2761 static void 2762 elf_print_symver(struct elfdump *ed) 2763 { 2764 struct section *s; 2765 int i; 2766 2767 for (i = 0; (size_t)i < ed->shnum; i++) { 2768 s = &ed->sl[i]; 2769 if (!STAILQ_EMPTY(&ed->snl) && !find_name(ed, s->name)) 2770 continue; 2771 if (s->type == SHT_SUNW_verdef) 2772 elf_print_verdef(ed, s); 2773 if (s->type == SHT_SUNW_verneed) 2774 elf_print_verneed(ed, s); 2775 } 2776 } 2777 2778 /* 2779 * Dump the ELF checksum. See gelf_checksum(3) for details. 2780 */ 2781 static void 2782 elf_print_checksum(struct elfdump *ed) 2783 { 2784 2785 if (!STAILQ_EMPTY(&ed->snl)) 2786 return; 2787 2788 PRT("\nelf checksum: %#lx\n", gelf_checksum(ed->elf)); 2789 } 2790 2791 #define USAGE_MESSAGE "\ 2792 Usage: %s [options] file...\n\ 2793 Display information about ELF objects and ar(1) archives.\n\n\ 2794 Options:\n\ 2795 -a Show all information.\n\ 2796 -c Show shared headers.\n\ 2797 -d Show dynamic symbols.\n\ 2798 -e Show the ELF header.\n\ 2799 -G Show the GOT.\n\ 2800 -H | --help Show a usage message and exit.\n\ 2801 -h Show hash values.\n\ 2802 -i Show the dynamic interpreter.\n\ 2803 -k Show the ELF checksum.\n\ 2804 -n Show the contents of note sections.\n\ 2805 -N NAME Show the section named \"NAME\".\n\ 2806 -p Show the program header.\n\ 2807 -r Show relocations.\n\ 2808 -s Show the symbol table.\n\ 2809 -S Use the Solaris elfdump format.\n\ 2810 -v Show symbol-versioning information.\n\ 2811 -V | --version Print a version identifier and exit.\n\ 2812 -w FILE Write output to \"FILE\".\n" 2813 2814 static void 2815 usage(void) 2816 { 2817 fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 2818 exit(EXIT_FAILURE); 2819 } 2820