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