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