Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /****************************    elf.cpp    *********************************
  2. * Author:        Agner Fog
  3. * Date created:  2006-07-18
  4. * Last modified: 2017-10-18
  5. * Project:       objconv
  6. * Module:        elf.cpp
  7. * Description:
  8. * Module for reading ELF files
  9. *
  10. * Class CELF is used for reading, interpreting and dumping ELF files.
  11. *
  12. * Copyright 2006-2017 GNU General Public License http://www.gnu.org/licenses
  13. *****************************************************************************/
  14. #include "stdafx.h"
  15. // All functions in this module are templated to make two versions: 32 and 64 bits.
  16. // See instantiations at the end of this file.
  17.  
  18.  
  19. // File class names
  20. SIntTxt ELFFileClassNames[] = {
  21.    {ELFCLASSNONE,      "None"},
  22.    {ELFCLASS32,        "32-bit object"},
  23.    {ELFCLASS64,        "64-bit object"}
  24. };
  25.  
  26. // Data encoding names
  27. SIntTxt ELFDataEncodeNames[] = {
  28.    {ELFDATANONE,        "None"},
  29.    {ELFDATA2LSB,        "Little Endian"},
  30.    {ELFDATA2MSB,        "Big Endian"}
  31. };
  32.  
  33. // ABI names
  34. SIntTxt ELFABINames[] = {
  35.    {ELFOSABI_SYSV,      "System V"},
  36.    {ELFOSABI_HPUX,      "HP-UX"},
  37.    {ELFOSABI_ARM,       "ARM"},
  38.    {ELFOSABI_STANDALONE,"Embedded"},
  39. };
  40.  
  41. // File type names
  42. SIntTxt ELFFileTypeNames[] = {
  43.    {ET_NONE,   "None"},
  44.    {ET_REL,    "Relocatable"},
  45.    {ET_EXEC,   "Executable"},
  46.    {ET_DYN,    "Shared object"},
  47.    {ET_CORE,   "Core file"}
  48. };
  49.  
  50. // Section type names
  51. SIntTxt ELFSectionTypeNames[] = {
  52.    {SHT_NULL,          "None"},
  53.    {SHT_PROGBITS,      "Program data"},
  54.    {SHT_SYMTAB,        "Symbol table"},
  55.    {SHT_STRTAB,        "String table"},
  56.    {SHT_RELA,          "Relocation w addends"},
  57.    {SHT_HASH,          "Symbol hash table"},
  58.    {SHT_DYNAMIC,       "Dynamic linking info"},
  59.    {SHT_NOTE,          "Notes"},
  60.    {SHT_NOBITS,        "bss"},
  61.    {SHT_REL,           "Relocation entries"},
  62.    {SHT_SHLIB,         "Reserved"},
  63.    {SHT_DYNSYM,        "Dynamic linker symbol table"},
  64.    {SHT_INIT_ARRAY,    "Array of constructors"},
  65.    {SHT_FINI_ARRAY,    "Array of destructors"},
  66.    {SHT_PREINIT_ARRAY, "Array of pre-constructors"},
  67.    {SHT_GROUP,         "Section group"},
  68.    {SHT_SYMTAB_SHNDX,  "Extended section indices"}
  69. };
  70.  
  71. // Section flag names
  72. SIntTxt ELFSectionFlagNames[] = {
  73.    {SHF_WRITE,         "Writeable"},
  74.    {SHF_ALLOC,         "Allocate"},
  75.    {SHF_EXECINSTR,     "Executable"},
  76.    {SHF_MERGE,         "Merge"},
  77.    {SHF_STRINGS,       "Strings"},
  78.    {SHF_INFO_LINK,     "sh_info"},
  79.    {SHF_LINK_ORDER,    "Preserve order"},
  80.    {SHF_OS_NONCONFORMING,"OS specific"}
  81. };
  82.  
  83. // Symbol binding names
  84. SIntTxt ELFSymbolBindingNames[] = {
  85.    {STB_LOCAL,  "Local"},
  86.    {STB_GLOBAL, "Global"},
  87.    {STB_WEAK,   "Weak"}
  88. };
  89.  
  90. // Symbol Type names
  91. SIntTxt ELFSymbolTypeNames[] = {
  92.    {STT_NOTYPE,  "None"},
  93.    {STT_OBJECT,  "Object"},
  94.    {STT_FUNC,    "Function"},
  95.    {STT_SECTION, "Section"},
  96.    {STT_FILE,    "File"},
  97.    {STT_COMMON,  "Common"},
  98.    {STT_GNU_IFUNC, "Indirect function/dispatcher"}
  99. };
  100.  
  101. // Relocation type names x86 32 bit
  102. SIntTxt ELF32RelocationNames[] = {
  103.    {R_386_NONE,         "None"},
  104.    {R_386_32,           "Absolute 32 bit"},
  105.    {R_386_PC32,         "Self-relative 32 bit"},
  106.    {R_386_GOT32,        "32 bit GOT entry"},
  107.    {R_386_PLT32,        "32 bit PLT address"},
  108.    {R_386_COPY,         "Copy symbol at runtime"},
  109.    {R_386_GLOB_DAT,     "Create GOT entry"},
  110.    {R_386_JMP_SLOT,     "Create PLT entry"},
  111.    {R_386_RELATIVE,     "Adjust by image base"},
  112.    {R_386_GOTOFF,       "32 bit offset to GOT"},
  113.    {R_386_GOTPC,        "32 bit PC relative offset to GOT"},
  114.    {R_386_IRELATIVE,    "32 bit ref. to indirect function PLT"}
  115. };
  116.  
  117. // Relocation type names x86 64 bit
  118. SIntTxt ELF64RelocationNames[] = {
  119.    {R_X86_64_NONE,      "None"},
  120.    {R_X86_64_64,        "Direct 64 bit"},
  121.    {R_X86_64_PC32,      "Self relative 32 bit signed"},
  122.    {R_X86_64_GOT32,     "32 bit GOT entry"},
  123.    {R_X86_64_PLT32,     "32 bit PLT address"},
  124.    {R_X86_64_COPY,      "Copy symbol at runtime"},
  125.    {R_X86_64_GLOB_DAT,  "Create GOT entry"},
  126.    {R_X86_64_JUMP_SLOT, "Create PLT entry"},
  127.    {R_X86_64_RELATIVE,  "Adjust by program base"},
  128.    {R_X86_64_GOTPCREL,  "32 bit signed pc relative offset to GOT"},
  129.    {R_X86_64_32,        "Direct 32 bit zero extended"},
  130.    {R_X86_64_32S,       "Direct 32 bit sign extended"},
  131.    {R_X86_64_16,        "Direct 16 bit zero extended"},
  132.    {R_X86_64_PC16,      "16 bit sign extended pc relative"},
  133.    {R_X86_64_8,         "Direct 8 bit sign extended"},
  134.    {R_X86_64_PC8,       "8 bit sign extended pc relative"},
  135.    {R_X86_64_IRELATIVE, "32 bit ref. to indirect function PLT"}
  136. };
  137.  
  138.  
  139. // Machine names
  140. SIntTxt ELFMachineNames[] = {
  141.    {EM_NONE,        "None"},     // No machine
  142.    {EM_M32,         "AT&T WE 32100"},
  143.    {EM_SPARC,       "SPARC"},
  144.    {EM_386,         "Intel x86"},
  145.    {EM_68K,         "Motorola m68k"},
  146.    {EM_88K,         "Motorola m88k"},
  147.    {EM_860,         "MIPS R3000 big-endian"},
  148.    {EM_MIPS,        "MIPS R3000 big-endian"},
  149.    {EM_S370,        "IBM System/370"},
  150.    {EM_MIPS_RS3_LE, "NMIPS R3000 little-endianone"},
  151.    {EM_PARISC,      "HPPA"},
  152.    {EM_VPP500,      "Fujitsu VPP500"},
  153.    {EM_SPARC32PLUS, "Sun v8plus"},
  154.    {EM_960,         "Intel 80960"},
  155.    {EM_PPC,         "PowerPC"},
  156.    {EM_PPC64,       "PowerPC 64-bit"},
  157.    {EM_S390,        "IBM S390"},
  158.    {EM_V800,        "NEC V800"},
  159.    {EM_FR20,        "Fujitsu FR20"},
  160.    {EM_RH32,        "TRW RH-32"},
  161.    {EM_RCE,         "Motorola RCE"},
  162.    {EM_ARM,         "ARM"},
  163.    {EM_FAKE_ALPHA,  "Digital Alpha"},
  164.    {EM_SH,          "Hitachi SH"},
  165.    {EM_SPARCV9,     "SPARC v9 64-bit"},
  166.    {EM_TRICORE,     "Siemens Tricore"},
  167.    {EM_ARC,         "Argonaut RISC"},
  168.    {EM_H8_300,      "Hitachi H8/300"},
  169.    {EM_H8_300H,     "Hitachi H8/300H"},
  170.    {EM_H8S,         "Hitachi H8S"},
  171.    {EM_H8_500,      "EM_H8_500"},
  172.    {EM_IA_64,       "Intel IA64"},
  173.    {EM_MIPS_X,      "Stanford MIPS-X"},
  174.    {EM_COLDFIRE,    "Motorola Coldfire"},
  175.    {EM_68HC12,      "Motorola M68HC12"},
  176.    {EM_MMA,         "Fujitsu MMA"},
  177.    {EM_PCP,         "Siemens PCP"},
  178.    {EM_NCPU,        "Sony nCPU"},
  179.    {EM_NDR1,        "Denso NDR1"},
  180.    {EM_STARCORE,    "Motorola Start*Core"},
  181.    {EM_ME16,        "Toyota ME16"},
  182.    {EM_ST100,       "ST100"},
  183.    {EM_TINYJ,       "Tinyj"},
  184.    {EM_X86_64,      "x86-64"},
  185.    {EM_PDSP,        "Sony DSP"},
  186.    {EM_FX66,        "Siemens FX66"},
  187.    {EM_ST9PLUS,     "ST9+ 8/16"},
  188.    {EM_ST7,         "ST7 8"},
  189.    {EM_68HC16,      "MC68HC16"},
  190.    {EM_68HC11,      "MC68HC11"},
  191.    {EM_68HC08,      "MC68HC08"},
  192.    {EM_68HC05,      "MC68HC05"},
  193.    {EM_SVX,         "SVx"},
  194.    {EM_AT19,        "ST19"},
  195.    {EM_VAX,         "VAX"},
  196.    {EM_CRIS,        "Axis"},
  197.    {EM_JAVELIN,     "Infineon"},
  198.    {EM_FIREPATH,    "Element 14"},
  199.    {EM_ZSP,         "LSI Logic"},
  200.    {EM_HUANY,       "Harvard"},
  201.    {EM_PRISM,       "SiTera Prism"},
  202.    {EM_AVR,         "Atmel AVR"},
  203.    {EM_FR30,        "FR30"},
  204.    {EM_D10V,        "D10V"},
  205.    {EM_D30V,        "D30V"},
  206.    {EM_V850,        "NEC v850"},
  207.    {EM_M32R,        "M32R"},
  208.    {EM_MN10300,     "MN10300"},
  209.    {EM_MN10200,     "MN10200"},
  210.    {EM_PJ,          "picoJava"},
  211.    {EM_ALPHA,       "Alpha"}
  212. };
  213.  
  214. // Program header type names
  215. SIntTxt ELFPTypeNames[] = {
  216.    {PT_NULL,        "Unused"},
  217.    {PT_LOAD,        "Loadable program segment"},
  218.    {PT_DYNAMIC,     "Dynamic linking information"},
  219.    {PT_INTERP,      "Program interpreter"},
  220.    {PT_NOTE,        "Auxiliary information"},
  221.    {PT_SHLIB,       "Reserved"},
  222.    {PT_PHDR,        "Entry for header table itself"}
  223. };
  224.  
  225.  
  226. // Class CELF members:
  227. // Constructor
  228. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  229. CELF<ELFSTRUCTURES>::CELF() {
  230.    memset(this, 0, sizeof(*this));
  231. }
  232.  
  233. // ParseFile
  234. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  235. void CELF<ELFSTRUCTURES>::ParseFile(){
  236.    // Load and parse file buffer
  237.    uint32 i;
  238.    FileHeader = *(TELF_Header*)Buf();   // Copy file header
  239.    NSections = FileHeader.e_shnum;
  240.    SectionHeaders.SetNum(NSections);    // Allocate space for section headers
  241.    SectionHeaders.SetZero();
  242.    uint32 Symtabi = 0;                  // Index to symbol table
  243.  
  244.    // check header integrity
  245.    if (FileHeader.e_phoff > GetDataSize() || FileHeader.e_phoff + FileHeader.e_phentsize > GetDataSize()) err.submit(2035);
  246.    if (FileHeader.e_shoff > GetDataSize() || FileHeader.e_shoff + FileHeader.e_shentsize > GetDataSize()) err.submit(2035);
  247.  
  248.    // Find section headers
  249.    SectionHeaderSize = FileHeader.e_shentsize;
  250.    if (SectionHeaderSize <= 0) err.submit(2033);
  251.    uint32 SectionOffset = uint32(FileHeader.e_shoff);
  252.  
  253.    for (i = 0; i < NSections; i++) {
  254.       SectionHeaders[i] = Get<TELF_SectionHeader>(SectionOffset);
  255.       // check section header integrity
  256.       if (SectionHeaders[i].sh_type != SHT_NOBITS && (SectionHeaders[i].sh_offset > GetDataSize()
  257.           || SectionHeaders[i].sh_offset + SectionHeaders[i].sh_size > GetDataSize()
  258.           || SectionHeaders[i].sh_offset + SectionHeaders[i].sh_entsize > GetDataSize())) {
  259.               err.submit(2035);
  260.       }
  261.       SectionOffset += SectionHeaderSize;
  262.       if (SectionHeaders[i].sh_type == SHT_SYMTAB) {
  263.          // Symbol table found
  264.          Symtabi = i;
  265.       }
  266.    }
  267.  
  268.    // if (Buf() && GetNumEntries()) {
  269.    if (Buf() && GetDataSize()) {
  270.        SecStringTable = Buf() + uint32(SectionHeaders[FileHeader.e_shstrndx].sh_offset);
  271.        SecStringTableLen = uint32(SectionHeaders[FileHeader.e_shstrndx].sh_size);
  272.    }
  273.    if (SectionOffset > GetDataSize()) {
  274.       err.submit(2110);     // Section table points to outside file
  275.    }
  276.    if (Symtabi) {
  277.       // Save offset to symbol table
  278.       SymbolTableOffset = (uint32)(SectionHeaders[Symtabi].sh_offset);
  279.       SymbolTableEntrySize = (uint32)(SectionHeaders[Symtabi].sh_entsize); // Entry size of symbol table
  280.       if (SymbolTableEntrySize == 0) {err.submit(2034); return;} // Avoid division by zero
  281.       SymbolTableEntries = uint32(SectionHeaders[Symtabi].sh_size) / SymbolTableEntrySize;
  282.       // Find associated string table
  283.       uint32 Stringtabi = SectionHeaders[Symtabi].sh_link;
  284.       if (Stringtabi < NSections) {
  285.          SymbolStringTableOffset = (uint32)(SectionHeaders[Stringtabi].sh_offset);
  286.          SymbolStringTableSize = (uint32)(SectionHeaders[Stringtabi].sh_size);
  287.       }
  288.       else {
  289.          Symtabi = 0;  // Error
  290.       }  
  291.    }
  292. }
  293.  
  294.  
  295. // Dump
  296. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  297. void CELF<ELFSTRUCTURES>::Dump(int options) {
  298.    uint32 i;
  299.    if (options & DUMP_FILEHDR) {
  300.       // File header
  301.       printf("\nDump of ELF file %s", FileName);
  302.       printf("\n-----------------------------------------------");
  303.       printf("\nFile size: %i", GetDataSize());
  304.       printf("\nFile header:");
  305.       printf("\nFile class: %s, Data encoding: %s, ELF version %i, ABI: %s, ABI version %i",
  306.          Lookup(ELFFileClassNames, FileHeader.e_ident[EI_CLASS]),
  307.          Lookup(ELFDataEncodeNames, FileHeader.e_ident[EI_DATA]),
  308.          FileHeader.e_ident[EI_VERSION],
  309.          Lookup(ELFABINames, FileHeader.e_ident[EI_OSABI]),
  310.          FileHeader.e_ident[EI_ABIVERSION]);
  311.  
  312.       printf("\nFile type: %s, Machine: %s, version: %i",
  313.          Lookup(ELFFileTypeNames, FileHeader.e_type),
  314.          Lookup(ELFMachineNames, FileHeader.e_machine),
  315.          FileHeader.e_version);
  316.       printf("\nNumber of sections: %2i, Processor flags: 0x%X",
  317.          NSections, FileHeader.e_flags);
  318.    }
  319.  
  320.    if ((options & DUMP_SECTHDR) && FileHeader.e_phnum) {      
  321.        // Dump program headers
  322.        uint32 nProgramHeaders = FileHeader.e_phnum;
  323.        uint32 programHeaderSize = FileHeader.e_phentsize;  
  324.        if (programHeaderSize <= 0) err.submit(2033);
  325.        uint32 programHeaderOffset = (uint32)FileHeader.e_phoff;
  326.        Elf64_Phdr pHeader;
  327.        for (i = 0; i < nProgramHeaders; i++) {
  328.            if (WordSize == 32) {
  329.                Elf32_Phdr pHeader32 = Get<Elf32_Phdr>(programHeaderOffset);
  330.                pHeader.p_type = pHeader32.p_type;
  331.                pHeader.p_offset = pHeader32.p_offset;
  332.                pHeader.p_vaddr = pHeader32.p_vaddr;
  333.                pHeader.p_paddr = pHeader32.p_paddr;
  334.                pHeader.p_filesz = pHeader32.p_filesz;
  335.                pHeader.p_memsz = pHeader32.p_memsz;
  336.                pHeader.p_flags = pHeader32.p_flags;
  337.                pHeader.p_align = pHeader32.p_align;
  338.            }
  339.            else {
  340.                pHeader = Get<Elf64_Phdr>(programHeaderOffset);
  341.            }
  342.            printf("\nProgram header Type: %s, flags 0x%X",
  343.                Lookup(ELFPTypeNames, (uint32)pHeader.p_type), (uint32)pHeader.p_flags);
  344.            printf("\noffset = 0x%X, vaddr = 0x%X, paddr = 0x%X, filesize = 0x%X, memsize = 0x%X, align = 0x%X",
  345.                (uint32)pHeader.p_offset, (uint32)pHeader.p_vaddr, (uint32)pHeader.p_paddr, (uint32)pHeader.p_filesz, (uint32)pHeader.p_memsz, (uint32)pHeader.p_align);
  346.            programHeaderOffset += programHeaderSize;
  347.            if (pHeader.p_filesz < 0x100 && (int32)pHeader.p_offset < GetDataSize() && memchr(Buf()+pHeader.p_offset, 0, (uint32)pHeader.p_filesz)) {
  348.                printf("\nContents: %s", Buf()+(int32)pHeader.p_offset);
  349.            }
  350.        }
  351.    }
  352.  
  353.    if (options & DUMP_SECTHDR) {
  354.       // Dump section headers
  355.       printf("\n\nSection headers:");
  356.       for (uint32 sc = 0; sc < NSections; sc++) {
  357.          // Get copy of 32-bit header or converted 64-bit header
  358.          TELF_SectionHeader sheader = SectionHeaders[sc];
  359.          uint32 entrysize = (uint32)(sheader.sh_entsize);
  360.          uint32 namei = sheader.sh_name;
  361.          if (namei >= SecStringTableLen) {err.submit(2112); break;}
  362.          printf("\n%2i Name: %-18s Type: %s", sc, SecStringTable + namei,
  363.             Lookup(ELFSectionTypeNames, sheader.sh_type));
  364.          if (sheader.sh_flags) {
  365.             printf("\n  Flags: 0x%X:", uint32(sheader.sh_flags));
  366.             for (int fi = 1; fi < (1 << 30); fi <<= 1) {
  367.                if (uint32(sheader.sh_flags) & fi) {
  368.                   printf(" %s", Lookup(ELFSectionFlagNames,fi));
  369.                }
  370.             }
  371.          }
  372.          if (sheader.sh_addr) {
  373.             printf("\n  Address: 0x%X", uint32(sheader.sh_addr));
  374.          }
  375.          if (sheader.sh_offset || sheader.sh_size) {
  376.             printf("\n  FileOffset: 0x%X, Size: 0x%X",
  377.                uint32(sheader.sh_offset), uint32(sheader.sh_size));
  378.          }
  379.          if (sheader.sh_addralign) {
  380.             printf("\n  Alignment: 0x%X", uint32(sheader.sh_addralign));
  381.          }
  382.          if (sheader.sh_entsize) {
  383.             printf("\n  Entry size: 0x%X", uint32(sheader.sh_entsize));
  384.             switch (sheader.sh_type) {
  385.             case SHT_DYNAMIC:
  386.                printf("\n  String table: %i", sheader.sh_link);
  387.                break;
  388.             case SHT_HASH:
  389.                printf("\n  Symbol table: %i", sheader.sh_link);
  390.                break;
  391.             case SHT_REL: case SHT_RELA:
  392.                printf("\n  Symbol table: %i, Reloc. section: %i",
  393.                   sheader.sh_link, sheader.sh_info);
  394.                break;
  395.             case SHT_SYMTAB: case SHT_DYNSYM:
  396.                printf("\n  Symbol string table: %i, First global symbol: %i",
  397.                   sheader.sh_link, sheader.sh_info);
  398.                break;
  399.             default:
  400.                if (sheader.sh_link) {
  401.                   printf("\n  Link: %i", sheader.sh_link);
  402.                }
  403.                if (sheader.sh_info) {
  404.                   printf("\n  Info: %i", sheader.sh_info);
  405.                }
  406.             }
  407.          }
  408.          if (sheader.sh_type == SHT_STRTAB && (options & DUMP_STRINGTB)) {
  409.             // Print string table
  410.             printf("\n  String table:");
  411.             char * p = Buf() + uint32(sheader.sh_offset) + 1;
  412.             uint32 nread = 1, len;
  413.             while (nread < uint32(sheader.sh_size)) {
  414.                len = (uint32)strlen(p);
  415.                printf(" >>%s<<", p);
  416.                nread += len + 1;
  417.                p += len + 1;
  418.             }
  419.          }
  420.          if ((sheader.sh_type==SHT_SYMTAB || sheader.sh_type==SHT_DYNSYM) && (options & DUMP_SYMTAB)) {
  421.             // Dump symbol table
  422.  
  423.             // Find associated string table
  424.             if (sheader.sh_link >= (uint32)NSections) {err.submit(2035); sheader.sh_link = 0;}
  425.             int8 * strtab = Buf() + uint32(SectionHeaders[sheader.sh_link].sh_offset);
  426.  
  427.             // Find symbol table
  428.             uint32 symtabsize = (uint32)(sheader.sh_size);
  429.             int8 * symtab = Buf() + uint32(sheader.sh_offset);
  430.             int8 * symtabend = symtab + symtabsize;
  431.             if (entrysize < sizeof(TELF_Symbol)) {err.submit(2033); entrysize = sizeof(TELF_Symbol);}
  432.  
  433.             printf("\n  Symbols:");
  434.             // Loop through symbol table
  435.             int symi;  // Symbol number
  436.             for (symi = 0; symtab < symtabend; symtab += entrysize, symi++) {
  437.                // Copy 32 bit symbol table entry or convert 64 bit entry
  438.                TELF_Symbol sym = *(TELF_Symbol*)symtab;
  439.                int type = sym.st_type;
  440.                int binding = sym.st_bind;
  441.                if (*(strtab + sym.st_name)) {
  442.                   printf("\n  %2i Name: %s,", symi, strtab + sym.st_name);}
  443.                else {
  444.                   printf("\n  %2i Unnamed,", symi);}
  445.                if (sym.st_value || type == STT_OBJECT || type == STT_FUNC || type == STT_GNU_IFUNC || int16(sym.st_shndx) < 0)
  446.                   printf(" Value: 0x%X", uint32(sym.st_value));
  447.                if (sym.st_size)  printf(" Size: %i", uint32(sym.st_size));
  448.                if (sym.st_other) printf(" Other: 0x%X", sym.st_other);
  449.                if (int16(sym.st_shndx) >= 0) printf(" Section: %i", sym.st_shndx);
  450.                else { // Special segment values
  451.                   switch (int16(sym.st_shndx)) {
  452.                   case SHN_ABS:
  453.                      printf(" Absolute,"); break;
  454.                   case SHN_COMMON:
  455.                      printf(" Common,"); break;
  456.                   case SHN_XINDEX:
  457.                      printf(" Index in extra table,"); break;
  458.                   default:
  459.                      printf(" Section: 0x%X", sym.st_shndx);
  460.                   }
  461.                }
  462.                if (sym.st_type || sym.st_bind) {
  463.                   printf(" Type: %s, Binding: %s",
  464.                      Lookup(ELFSymbolTypeNames, type),
  465.                      Lookup(ELFSymbolBindingNames, binding));
  466.                }
  467.             }
  468.          }
  469.          if ((sheader.sh_type==SHT_REL || sheader.sh_type==SHT_RELA ) && (options & DUMP_RELTAB)) {
  470.             printf("\n  Relocations:");
  471.             int8 * reltab = Buf() + uint32(sheader.sh_offset);
  472.             int8 * reltabend = reltab + uint32(sheader.sh_size);
  473.             uint32 expectedentrysize = sheader.sh_type == SHT_RELA ?
  474.                sizeof(TELF_Relocation) :              // Elf32_Rela, Elf64_Rela
  475.                sizeof(TELF_Relocation) - WordSize/8;  // Elf32_Rel,  Elf64_Rel
  476.             if (entrysize < expectedentrysize) {err.submit(2033); entrysize = expectedentrysize;}
  477.  
  478.             // Loop through entries
  479.             for (; reltab < reltabend; reltab += entrysize) {
  480.                // Copy relocation table entry with or without addend
  481.                TELF_Relocation rel;  rel.r_addend = 0;
  482.                memcpy(&rel, reltab, entrysize);
  483.                printf ("\n  Offset: 0x%X, Symbol: %i, Name: %s\n   Type: %s",
  484.                   uint32(rel.r_offset), rel.r_sym, SymbolName(rel.r_sym),
  485.                   (WordSize == 32) ?
  486.                   Lookup (ELF32RelocationNames, rel.r_type) :
  487.                   Lookup (ELF64RelocationNames, rel.r_type));
  488.                if (rel.r_addend) printf (", Addend: 0x%X", uint32(rel.r_addend));
  489.  
  490.                // Find inline addend
  491.                TELF_SectionHeader relsheader = SectionHeaders[sheader.sh_info];
  492.                uint32 relsoffset = uint32(relsheader.sh_offset);
  493.                if (relsoffset+rel.r_offset < GetDataSize()) {
  494.                   int32 * piaddend = (int32*)(Buf()+relsoffset+rel.r_offset);
  495.                   if (* piaddend) printf (", Inline addend: 0x%X", * piaddend);
  496.                }
  497.             }
  498.          }
  499.       }
  500.    }
  501. }
  502.  
  503.  
  504. // PublicNames
  505. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  506. void CELF<ELFSTRUCTURES>::PublicNames(CMemoryBuffer * Strings, CSList<SStringEntry> * Index, int m) {
  507.    // Make list of public names
  508.    // Interpret header:
  509.    ParseFile();
  510.  
  511.    // Loop through section headers
  512.    for (uint32 sc = 0; sc < NSections; sc++) {
  513.       // Get copy of 32-bit header or converted 64-bit header
  514.       TELF_SectionHeader sheader = SectionHeaders[sc];
  515.       uint32 entrysize = uint32(sheader.sh_entsize);
  516.  
  517.       if (sheader.sh_type==SHT_SYMTAB || sheader.sh_type==SHT_DYNSYM) {
  518.          // Dump symbol table
  519.  
  520.          // Find associated string table
  521.          if (sheader.sh_link >= (uint32)NSections) {err.submit(2035); sheader.sh_link = 0;}
  522.          int8 * strtab = Buf() + uint32(SectionHeaders[sheader.sh_link].sh_offset);
  523.  
  524.          // Find symbol table
  525.          uint32 symtabsize = uint32(sheader.sh_size);
  526.          int8 * symtab = Buf() + uint32(sheader.sh_offset);
  527.          int8 * symtabend = symtab + symtabsize;
  528.          if (entrysize < sizeof(TELF_Symbol)) {err.submit(2033); entrysize = sizeof(TELF_Symbol);}
  529.  
  530.          // Loop through symbol table
  531.          for (int symi = 0; symtab < symtabend; symtab += entrysize, symi++) {
  532.             // Copy 32 bit symbol table entry or convert 64 bit entry
  533.             TELF_Symbol sym = *(TELF_Symbol*)symtab;
  534.             int type = sym.st_type;
  535.             int binding = sym.st_bind;
  536.             if (int16(sym.st_shndx) > 0
  537.             && type != STT_SECTION && type != STT_FILE
  538.             && (binding == STB_GLOBAL || binding == STB_WEAK)) {
  539.                // Public symbol found
  540.                SStringEntry se;
  541.                se.Member = m;
  542.                // Store name
  543.                se.String = Strings->PushString(strtab + sym.st_name);
  544.                // Store name index
  545.                Index->Push(se);
  546.             }
  547.          }
  548.       }
  549.    }
  550. }
  551.  
  552. // SymbolName
  553. template <class TELF_Header, class TELF_SectionHeader, class TELF_Symbol, class TELF_Relocation>
  554. const char * CELF<ELFSTRUCTURES>::SymbolName(uint32 index) {
  555.    // Get name of symbol. (ParseFile() must be called first)
  556.    const char * symname = "?";  // Symbol name
  557.    uint32 symi;           // Symbol index
  558.    uint32 stri;           // String index
  559.    if (SymbolTableOffset) {
  560.       symi = SymbolTableOffset + index * SymbolTableEntrySize;
  561.       if (symi < GetDataSize()) {
  562.          stri = Get<TELF_Symbol>(symi).st_name;
  563.          if (stri < SymbolStringTableSize) {
  564.             symname = Buf() + SymbolStringTableOffset + stri;
  565.          }
  566.       }
  567.    }
  568.    return symname;
  569. }
  570.  
  571.  
  572. // Make template instances for 32 and 64 bits
  573. template class CELF<ELF32STRUCTURES>;
  574. template class CELF<ELF64STRUCTURES>;
  575.