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>
CELF()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>
ParseFile()235 void CELF<ELFSTRUCTURES>::ParseFile(){
236    // Load and parse file buffer
237    uint32_t 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_t 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_t SectionOffset = uint32_t(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 = (char*)Buf() + uint32_t(SectionHeaders[FileHeader.e_shstrndx].sh_offset);
271        SecStringTableLen = uint32_t(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_t)(SectionHeaders[Symtabi].sh_offset);
279       SymbolTableEntrySize = (uint32_t)(SectionHeaders[Symtabi].sh_entsize); // Entry size of symbol table
280       if (SymbolTableEntrySize == 0) {err.submit(2034); return;} // Avoid division by zero
281       SymbolTableEntries = uint32_t(SectionHeaders[Symtabi].sh_size) / SymbolTableEntrySize;
282       // Find associated string table
283       uint32_t Stringtabi = SectionHeaders[Symtabi].sh_link;
284       if (Stringtabi < NSections) {
285          SymbolStringTableOffset = (uint32_t)(SectionHeaders[Stringtabi].sh_offset);
286          SymbolStringTableSize = (uint32_t)(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>
Dump(int options)297 void CELF<ELFSTRUCTURES>::Dump(int options) {
298    uint32_t 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_t nProgramHeaders = FileHeader.e_phnum;
323        uint32_t programHeaderSize = FileHeader.e_phentsize;
324        if (programHeaderSize <= 0) err.submit(2033);
325        uint32_t programHeaderOffset = (uint32_t)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_t)pHeader.p_type), (uint32_t)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_t)pHeader.p_offset, (uint32_t)pHeader.p_vaddr, (uint32_t)pHeader.p_paddr, (uint32_t)pHeader.p_filesz, (uint32_t)pHeader.p_memsz, (uint32_t)pHeader.p_align);
346            programHeaderOffset += programHeaderSize;
347            if (pHeader.p_filesz < 0x100 && (int32_t)pHeader.p_offset < GetDataSize() && memchr(Buf()+pHeader.p_offset, 0, (uint32_t)pHeader.p_filesz)) {
348                printf("\nContents: %s", Buf()+(int32_t)pHeader.p_offset);
349            }
350        }
351    }
352 
353    if (options & DUMP_SECTHDR) {
354       // Dump section headers
355       printf("\n\nSection headers:");
356       for (uint32_t 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_t entrysize = (uint32_t)(sheader.sh_entsize);
360          uint32_t 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_t(sheader.sh_flags));
366             for (int fi = 1; fi < (1 << 30); fi <<= 1) {
367                if (uint32_t(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_t(sheader.sh_addr));
374          }
375          if (sheader.sh_offset || sheader.sh_size) {
376             printf("\n  FileOffset: 0x%X, Size: 0x%X",
377                uint32_t(sheader.sh_offset), uint32_t(sheader.sh_size));
378          }
379          if (sheader.sh_addralign) {
380             printf("\n  Alignment: 0x%X", uint32_t(sheader.sh_addralign));
381          }
382          if (sheader.sh_entsize) {
383             printf("\n  Entry size: 0x%X", uint32_t(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 = (char*)Buf() + uint32_t(sheader.sh_offset) + 1;
412             uint32_t nread = 1, len;
413             while (nread < uint32_t(sheader.sh_size)) {
414                len = (uint32_t)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_t)NSections) {err.submit(2035); sheader.sh_link = 0;}
425             int8_t * strtab = Buf() + uint32_t(SectionHeaders[sheader.sh_link].sh_offset);
426 
427             // Find symbol table
428             uint32_t symtabsize = (uint32_t)(sheader.sh_size);
429             int8_t * symtab = Buf() + uint32_t(sheader.sh_offset);
430             int8_t * 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_t(sym.st_shndx) < 0)
446                   printf(" Value: 0x%X", uint32_t(sym.st_value));
447                if (sym.st_size)  printf(" Size: %i", uint32_t(sym.st_size));
448                if (sym.st_other) printf(" Other: 0x%X", sym.st_other);
449                if (int16_t(sym.st_shndx) >= 0) printf(" Section: %i", sym.st_shndx);
450                else { // Special segment values
451                   switch (int16_t(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_t * reltab = Buf() + uint32_t(sheader.sh_offset);
472             int8_t * reltabend = reltab + uint32_t(sheader.sh_size);
473             uint32_t 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_t(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_t(rel.r_addend));
489 
490                // Find inline addend
491                TELF_SectionHeader relsheader = SectionHeaders[sheader.sh_info];
492                uint32_t relsoffset = uint32_t(relsheader.sh_offset);
493                if (relsoffset+rel.r_offset < GetDataSize()) {
494                   int32_t * piaddend = (int32_t*)(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>
PublicNames(CMemoryBuffer * Strings,CSList<SStringEntry> * Index,int m)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_t 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_t entrysize = uint32_t(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_t)NSections) {err.submit(2035); sheader.sh_link = 0;}
522          char * strtab = (char*)Buf() + uint32_t(SectionHeaders[sheader.sh_link].sh_offset);
523 
524          // Find symbol table
525          uint32_t symtabsize = uint32_t(sheader.sh_size);
526          int8_t * symtab = Buf() + uint32_t(sheader.sh_offset);
527          int8_t * 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_t(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>
SymbolName(uint32_t index)554 const char * CELF<ELFSTRUCTURES>::SymbolName(uint32_t index) {
555    // Get name of symbol. (ParseFile() must be called first)
556    const char * symname = "?";  // Symbol name
557    uint32_t symi;           // Symbol index
558    uint32_t 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 = (char*)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