FileLoader_ELF.cc Source File

Back to the index.

FileLoader_ELF.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2019 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <assert.h>
29 #include <string.h>
30 #include <fstream>
31 #include <iomanip>
32 
33 using std::setw;
34 using std::setfill;
35 using std::ifstream;
36 
37 #include "AddressDataBus.h"
39 #include "FileLoader_ELF.h"
40 
41 #include "thirdparty/exec_elf.h"
42 
43 
44 /* ELF machine types as strings: (same as exec_elf.h) */
45 #define N_ELF_MACHINE_TYPES 244
46 static const char *elf_machine_type[N_ELF_MACHINE_TYPES] = {
47  "NONE", "M32", "SPARC", "386", /* 0..3 */
48  "68K", "88K", "486", "i860", /* 4..7 */
49  "MIPS", "S370", "MIPS_RS3_LE", "RS6000", /* 8..11 */
50  "unknown12", "unknown13", "unknown14", "PARISC", /* 12..15 */
51  "NCUBE", "VPP500", "SPARC32PLUS", "i960", /* 16..19 */
52  "PPC", "PPC64", "unknown22", "unknown23", /* 20..23 */
53  "unknown24", "unknown25", "unknown26", "unknown27", /* 24..27 */
54  "unknown28", "unknown29", "unknown30", "unknown31", /* 28..31 */
55  "unknown32", "unknown33", "unknown34", "unknown35", /* 32..35 */
56  "V800", "FR20", "RH32", "RCE", /* 36..39 */
57  "ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */
58  "TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */
59  "H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */
60  "COLDFIRE", "68HC12", "Fujitsu MMA", "Siemens PCP", /* 52..55 */
61  "nCPU", "NDR1", "STARCORE", "ME16", /* 56..59 */
62  "ST100", "TINYJ", "AMD64", "PDSP", /* 60..63 */
63  "PDP10", "PDP11", "FX66", "ST9PLUS", /* 64..67 */
64  "ST7", "68HC16", "68HC11", "68HC08", /* 68..71 */
65  "68HC05", "SVX", "ST19", "VAX", /* 72..75 */
66  "CRIS", "JAVELIN", "FIREPATH", "ZSP", /* 76..79 */
67  "MMIX", "HUANY", "PRISM", "AVR", /* 80..83 */
68  "FR30", "D10V", "D30V", "V850", /* 84..87 */
69  "M32R", "MN10300", "MN10200", "picoJava", /* 88..91 */
70  "OR1K", "ARC_A5", "Xtensa", "Alphamosaic VideoCore", /* 92..95 */
71  "TMM_GPP", "NS32K", "TPC", "SNP1K", /* 96..99 */
72  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 100..103 */
73  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 104..107 */
74  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 108..111 */
75  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 112..115 */
76  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 116..119 */
77  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 120..123 */
78  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 124..127 */
79  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 128..131 */
80  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 132..135 */
81  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 136..139 */
82  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 140..143 */
83  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 144..147 */
84  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 148..151 */
85  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 152..155 */
86  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 156..159 */
87  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 160..163 */
88  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 164..167 */
89  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 168..171 */
90  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 172..175 */
91  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 176..179 */
92  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 180..183 */
93  "unknown1xx", "unknown1xx", "unknown1xx", "TILE64", /* 184..187 */
94  "TILEPro", "MicroBlaze", "unknown1xx", "unknown1xx", /* 188..191 */
95  "TILE-GX", "unknown1xx", "unknown1xx", "unknown1xx", /* 192..195 */
96  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 196..199 */
97  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 200..203 */
98  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 204..207 */
99  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 208..211 */
100  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 212..215 */
101  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 216..219 */
102  "Zilog Z80", "unknown1xx", "unknown1xx", "unknown1xx", /* 220..223 */
103  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 224..227 */
104  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 228..231 */
105  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 232..235 */
106  "unknown1xx", "unknown1xx", "unknown1xx", "unknown1xx", /* 236..239 */
107  "unknown1xx", "unknown1xx", "unknown1xx", "RISC-V", /* 240..243 */
108 };
109 
110 
111 FileLoader_ELF::FileLoader_ELF(const string& filename)
112  : FileLoaderImpl(filename)
113 {
114 }
115 
116 
117 string FileLoader_ELF::DetectFileType(unsigned char *buf, size_t buflen, float& matchness) const
118 {
119  if (buflen < sizeof(Elf32_Ehdr))
120  return "";
121 
122  // Note: The e_ident part of the 32-bit and the 64-bit variants have
123  // the same layout, so it is safe to only check the 32-bit variant here.
124  Elf32_Ehdr* elf32_ehdr = (Elf32_Ehdr*) buf;
125  if (elf32_ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
126  elf32_ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
127  elf32_ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
128  elf32_ehdr->e_ident[EI_MAG3] == ELFMAG3) {
129  // We are here if this is either an ELF32 or ELF64.
130  int elfClass = elf32_ehdr->e_ident[EI_CLASS];
131 
132  matchness = 1.0;
133  if (elfClass == ELFCLASS32)
134  return "ELF32";
135  if (elfClass == ELFCLASS64)
136  return "ELF64";
137 
138  matchness = 0.0;
139  stringstream ss;
140  ss << "ELF Unknown class " << elfClass;
141  return ss.str();
142  }
143 
144  return "";
145 }
146 
147 
148 bool FileLoader_ELF::LoadIntoComponent(refcount_ptr<Component> component, ostream& messages) const
149 {
150  AddressDataBus* bus = component->AsAddressDataBus();
151  if (bus == NULL) {
152  messages << "Target is not an AddressDataBus.\n";
153  return false;
154  }
155 
156  ifstream file(Filename().c_str());
157  if (!file.is_open()) {
158  messages << "Unable to read file.\n";
159  return false;
160  }
161 
162  char buf[64];
163 
164  // buf must be large enough for the largest possible header we wish
165  // to examine to fit.
166  assert(sizeof(buf) >= sizeof(Elf32_Ehdr));
167  assert(sizeof(buf) >= sizeof(Elf64_Ehdr));
168 
169  memset(buf, 0, sizeof(buf));
170  file.read(buf, sizeof(buf));
171 
172  // Note: The e_ident part of the 32-bit and the 64-bit variants have
173  // the same layout, so it is safe to only use the 32-bit variant here.
174  Elf32_Ehdr* ehdr32 = (Elf32_Ehdr*) buf;
175  Elf64_Ehdr* ehdr64 = (Elf64_Ehdr*) buf;
176  if (ehdr32->e_ident[EI_MAG0] != ELFMAG0 ||
177  ehdr32->e_ident[EI_MAG1] != ELFMAG1 ||
178  ehdr32->e_ident[EI_MAG2] != ELFMAG2 ||
179  ehdr32->e_ident[EI_MAG3] != ELFMAG3) {
180  messages << "Not an ELF.\n";
181  return false;
182  }
183 
184  int elfClass = ehdr32->e_ident[EI_CLASS];
185  int elfDataEncoding = ehdr32->e_ident[EI_DATA];
186  int elfVersion = ehdr32->e_ident[EI_VERSION];
187 
188  if (elfClass != ELFCLASS32 && elfClass != ELFCLASS64) {
189  messages << "Unknown ELF class.\n";
190  return false;
191  }
192  if (elfDataEncoding != ELFDATA2LSB && elfDataEncoding != ELFDATA2MSB) {
193  messages << "Unknown ELF data encoding.\n";
194  return false;
195  }
196  if (elfVersion != EV_CURRENT) {
197  messages << "Unknown ELF version.\n";
198  return false;
199  }
200 
201  bool elf32 = elfClass == ELFCLASS32;
202 
203 #define ELF_HEADER_VAR(hdr32,hdr64,type,name) type name = elf32? hdr32->name \
204  : hdr64->name; \
205  if (elfDataEncoding == ELFDATA2LSB) { \
206  int size = elf32? sizeof(hdr32->name) : sizeof(hdr64->name); \
207  switch (size) { \
208  case 2: name = LE16_TO_HOST(name); break; \
209  case 4: name = LE32_TO_HOST(name); break; \
210  case 8: name = LE64_TO_HOST(name); break; \
211  } \
212  } else { \
213  int size = elf32? sizeof(hdr32->name) : sizeof(hdr64->name); \
214  switch (size) { \
215  case 2: name = BE16_TO_HOST(name); break; \
216  case 4: name = BE32_TO_HOST(name); break; \
217  case 8: name = BE64_TO_HOST(name); break; \
218  } \
219  }
220 
221  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_type);
222 
223  if (e_type != ET_EXEC) {
224  messages << "ELF file is not an Executable.\n";
225  return false;
226  }
227 
228  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_entry);
229  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_machine);
230 
231  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_phoff);
232  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_phentsize);
233  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_phnum);
234 
235  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_shoff);
236  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_shentsize);
237  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_shnum);
238 
239  size_t expectedPhentSize = (elf32? sizeof(Elf32_Phdr) : sizeof(Elf64_Phdr));
240  if (e_phentsize != expectedPhentSize) {
241  messages << "Incorrect ELF phentsize? " << e_phentsize << ", should "
242  "be " << expectedPhentSize << "\n"
243  "Perhaps this is a dynamically linked "
244  "binary (which isn't supported yet).\n";
245  return false;
246  }
247 
248  size_t expectedShentSize = (elf32? sizeof(Elf32_Shdr) : sizeof(Elf64_Shdr));
249  if (e_shentsize != expectedShentSize) {
250  messages << "Incorrect ELF shentsize? " << e_shentsize << ", should "
251  "be " << expectedShentSize << "\n"
252  "Perhaps this is a dynamically linked "
253  "binary (which isn't supported yet).\n";
254  return false;
255  }
256 
257  if (e_machine < N_ELF_MACHINE_TYPES)
258  messages << elf_machine_type[e_machine];
259  else
260  messages << "machine type '" << e_machine << "'";
261  messages << " ELF" << (elf32? 32 : 64) << " ";
262 
263  messages << (elfDataEncoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)") << ": ";
264 
265  if (!elf32 && (e_machine == EM_PPC || e_machine == EM_PPC64))
266  messages << "PPC function descriptor at";
267  else
268  messages << "entry point";
269 
270  messages << " 0x";
271  messages.flags(std::ios::hex);
272 
273  // Special case for MIPS: 32-bit addresses are sign-extended.
274  if (e_machine == EM_MIPS && elf32)
275  e_entry = (int32_t) e_entry;
276 
277  uint64_t display_entry_point = e_entry;
278 
279  // MIPS16 encoding (16-bit words) is indicated by the lowest bit of the PC.
280  bool mips16 = false;
281  if (e_machine == EM_MIPS && (e_entry & 1)) {
282  display_entry_point &= ~1;
283  mips16 = true;
284  }
285 
286  // SHmedia (SH64) 32-bit encoding is indicated by the lowest bit of the PC.
287  bool shmedia = false;
288  if (e_machine == EM_SH && (e_entry & 1)) {
289  display_entry_point &= ~1;
290  shmedia = true;
291  }
292 
293  if (elf32)
294  messages << setw(8) << setfill('0') << (uint32_t) display_entry_point;
295  else
296  messages << setw(16) << setfill('0') << (uint64_t) display_entry_point;
297 
298  if (mips16)
299  messages << " (MIPS16 encoding)";
300 
301  if (shmedia)
302  messages << " (SHmedia encoding)";
303 
304  messages << "\n";
305 
306  // PROGRAM HEADERS
307  size_t i;
308  for (i=0; i<e_phnum; ++i) {
309  // Load Phdr number i:
310  file.seekg(e_phoff + i * e_phentsize, std::ios::beg);
311 
312  char phdr_buf[64];
313  assert(sizeof(phdr_buf) >= sizeof(Elf32_Phdr));
314  assert(sizeof(phdr_buf) >= sizeof(Elf64_Phdr));
315  Elf32_Phdr* phdr32 = (Elf32_Phdr*) phdr_buf;
316  Elf64_Phdr* phdr64 = (Elf64_Phdr*) phdr_buf;
317 
318  memset(phdr_buf, 0, sizeof(phdr_buf));
319 
320  int toRead = elf32? sizeof(Elf32_Phdr) : sizeof(Elf64_Phdr);
321  file.read(phdr_buf, toRead);
322  if (file.gcount() != toRead) {
323  messages << "Unable to read Phdr.\n";
324  return false;
325  }
326 
327  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_type);
328  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_offset);
329  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_vaddr);
330  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_filesz);
331  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_memsz);
332 
333  // Skip non-loadable program segments:
334  if (p_type != PT_LOAD)
335  continue;
336 
337  if (p_memsz < p_filesz) {
338  messages << "memsz < filesz. TODO: how"
339  " to handle this? memsz = " << p_memsz <<
340  ", filesz = " << p_filesz << "\n";
341  return false;
342  }
343 
344  // Special case for MIPS: 32-bit addresses are sign-extended.
345  if (e_machine == EM_MIPS && elf32)
346  p_vaddr = (int32_t) p_vaddr;
347 
348  messages.flags(std::ios::hex);
349  messages << "loadable chunk: vaddr 0x";
350 
351  if (elf32)
352  messages << setw(8) << setfill('0') << (uint32_t) p_vaddr;
353  else
354  messages << setw(16) << setfill('0') << (uint64_t) p_vaddr;
355 
356  messages.flags(std::ios::dec);
357  messages << ", " << p_filesz << " bytes\n";
358 
359  file.seekg(p_offset, std::ios::beg);
360  char databuf[65536];
361  uint64_t bytesRead = 0;
362  uint64_t vaddrToWriteTo = p_vaddr;
363 
364  while (bytesRead < p_filesz) {
365  int sizeToRead = sizeof(databuf);
366  if (sizeToRead + bytesRead > p_filesz)
367  sizeToRead = p_filesz - bytesRead;
368 
369  assert(sizeToRead != 0);
370  memset(databuf, 0, sizeToRead);
371 
372  file.read(databuf, sizeToRead);
373  int bytesReadThisTime = file.gcount();
374  bytesRead += bytesReadThisTime;
375 
376  // Write to the bus, one byte at a time.
377  for (int k=0; k<bytesReadThisTime; ++k) {
378  bus->AddressSelect(vaddrToWriteTo);
379  if (!bus->WriteData(databuf[k])) {
380  messages.flags(std::ios::hex);
381  messages << "Failed to write data to "
382  "virtual address 0x"
383  << vaddrToWriteTo << "\n";
384  return false;
385  }
386 
387  ++ vaddrToWriteTo;
388  }
389  }
390  }
391 
392  // SECTION HEADERS
393  vector<char> symtab;
394  vector<char> symstrings;
395  for (i=0; i<e_shnum; ++i) {
396  // Load Shdr number i:
397  file.seekg(e_shoff + i * e_shentsize, std::ios::beg);
398 
399  char shdr_buf[64];
400  assert(sizeof(shdr_buf) >= sizeof(Elf32_Shdr));
401  assert(sizeof(shdr_buf) >= sizeof(Elf64_Shdr));
402  Elf32_Shdr* shdr32 = (Elf32_Shdr*) shdr_buf;
403  Elf64_Shdr* shdr64 = (Elf64_Shdr*) shdr_buf;
404 
405  memset(shdr_buf, 0, sizeof(shdr_buf));
406 
407  int toRead = elf32? sizeof(Elf32_Shdr) : sizeof(Elf64_Shdr);
408  file.read(shdr_buf, toRead);
409  if (file.gcount() != toRead) {
410  messages << "Unable to read Shdr.\n";
411  return false;
412  }
413 
414  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_name);
415  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_type);
416  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_flags);
417  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_addr);
418  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_offset);
419  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_size);
420  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_link);
421  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_info);
422  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_addralign);
423  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_entsize);
424 
425  if (sh_type == SHT_SYMTAB) {
426  if (symtab.size() > 0) {
427  messages << "symtab: another symtab already loaded? TODO\n";
428  return false;
429  }
430 
431  int entrySize = elf32? sizeof(Elf32_Sym) : sizeof(Elf64_Sym);
432  int nEntries = sh_size / entrySize;
433 
434  messages.flags(std::ios::dec);
435  messages << "symtab: " << nEntries << " symbols at 0x";
436  messages.flags(std::ios::hex);
437  messages << sh_offset << "\n";
438 
439  symtab.resize(sh_size);
440  file.seekg(sh_offset, std::ios::beg);
441  file.read(&symtab[0], sh_size);
442  if ((uint64_t) file.gcount() != sh_size) {
443  messages << "Failed to read all " << sh_size << " symbol bytes.\n";
444  return false;
445  }
446  }
447 
448  // TODO/HACK: Figure out which strtab to use. For now, simply
449  // use the largest one!
450  if (sh_type == SHT_STRTAB && sh_size > symstrings.size()) {
451  messages.flags(std::ios::dec);
452  messages << "strtab: " << sh_size << " bytes at 0x";
453  messages.flags(std::ios::hex);
454  messages << sh_offset << "\n";
455 
456  symstrings.resize(sh_size);
457  file.seekg(sh_offset, std::ios::beg);
458  file.read(&symstrings[0], sh_size);
459  if ((uint64_t) file.gcount() != sh_size) {
460  messages << "Failed to read all " << sh_size << " symbol string bytes.\n";
461  return false;
462  }
463  }
464  }
465 
466  SymbolRegistry* symbolRegistry = NULL;
467  CPUComponent* cpu = component->AsCPUComponent();
468  if (cpu != NULL)
469  symbolRegistry = &cpu->GetSymbolRegistry();
470 
471  // Symbols
472  if (symbolRegistry != NULL && symtab.size() > 0 && symstrings.size() > 0) {
473  int entrySize = elf32? sizeof(Elf32_Sym) : sizeof(Elf64_Sym);
474  int nEntries = symtab.size() / entrySize;
475 
476  // For safety:
477  symstrings.resize(symstrings.size() + 1);
478  symstrings[symstrings.size() - 1] = '\0';
479 
480  int nsymbols = 0;
481 
482  messages.flags(std::ios::hex);
483 
484  for (int j=0; j<nEntries; j++) {
485  size_t p = j * entrySize;
486  Elf32_Sym* sym32 = (Elf32_Sym*) &symtab[p];
487  Elf64_Sym* sym64 = (Elf64_Sym*) &symtab[p];
488 
489  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_name);
490  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_info);
491  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_value);
492  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_size);
493 
494  // TODO: Is this needed?
495  //int bind = elf32? ELF32_ST_BIND(st_info) : ELF64_ST_BIND(st_info);
496  //if (bind == STB_LOCAL)
497  // continue;
498 
499  if (st_size == 0)
500  st_size ++;
501 
502  if (st_name >= symstrings.size() - 1) {
503  messages << "symbol pointer mismatch?\n";
504  continue;
505  }
506 
507  string symbol = &symstrings[st_name];
508 
509  // Special case for MIPS: 32-bit addresses are sign-extended.
510  if (e_machine == EM_MIPS && elf32)
511  st_value = (int32_t) st_value;
512 
513  // Special case for MIPS: _gp symbol initiates the GP register.
514  if (e_machine == EM_MIPS && symbol == "_gp") {
515  messages << "found _gp address: 0x";
516  if (elf32)
517  messages << setw(8) << setfill('0') << (uint32_t) st_value << "\n";
518  else
519  messages << setw(16) << setfill('0') << (uint64_t) st_value << "\n";
520 
521  stringstream ss;
522  ss << st_value;
523  component->SetVariableValue("gp", ss.str());
524  }
525 
526  // FOR DEBUGGING ONLY:
527  //messages << "symbol name '" << symbol << "', addr 0x" <<
528  // st_value << ", size 0x" << st_size << "\n";
529 
530  // Add this symbol to the symbol registry:
531  symbolRegistry->AddSymbol(symbol, st_value);
532  ++ nsymbols;
533  }
534 
535  messages.flags(std::ios::dec);
536  messages << nsymbols << " symbols read\n";
537  }
538 
539  // Set the CPU's entry point.
540 
541 #if 0
542  if (elf64 && arch == ARCH_PPC) {
543  /*
544  * Special case for 64-bit PPC ELFs:
545  *
546  * The ELF starting symbol points to a ".opd" section
547  * which contains a function descriptor:
548  *
549  * uint64_t start;
550  * uint64_t toc_base;
551  * uint64_t something_else; (?)
552  */
553  int res;
554  unsigned char b[sizeof(uint64_t)];
555  uint64_t toc_base;
556 
557  debug("PPC64: ");
558 
559  res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
560  sizeof(b), MEM_READ, NO_EXCEPTIONS);
561  if (!res)
562  debug(" [WARNING: could not read memory?] ");
563 
564  /* PPC are always big-endian: */
565  *entrypointp = ((uint64_t)b[0] << 56) +
566  ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
567  ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
568  ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
569  (uint64_t)b[7];
570 
571  res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
572  b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
573  if (!res)
574  fatal(" [WARNING: could not read memory?] ");
575 
576  toc_base = ((uint64_t)b[0] << 56) +
577  ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
578  ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
579  ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
580  (uint64_t)b[7];
581 
582  debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n",
583  (uint64_t) *entrypointp, (uint64_t) toc_base);
584  if (tocp != NULL)
585  *tocp = toc_base;
586  }
587 #endif
588 
589  stringstream ss;
590  ss << e_entry;
591  component->SetVariableValue("pc", ss.str());
592  component->SetVariableValue("bigendian",
593  elfDataEncoding == ELFDATA2LSB? "false" : "true");
594 
595  return true;
596 }
597 
598 
599 /*****************************************************************************/
600 
601 
602 #ifdef WITHUNITTESTS
603 
604 #include "ComponentFactory.h"
605 
606 static void Test_FileLoader_ELF_Constructor()
607 {
608  FileLoader_ELF elfLoader("test/FileLoader_ELF_MIPS");
609 }
610 
612 {
613  UNITTEST(Test_FileLoader_ELF_Constructor);
614 
615  // TODO
616 }
617 
618 #endif
EM_MIPS
#define EM_MIPS
Definition: exec_elf.h:210
EV_CURRENT
#define EV_CURRENT
Definition: exec_elf.h:160
ELFCLASS32
#define ELFCLASS32
Definition: exec_elf.h:149
ARCH_PPC
#define ARCH_PPC
Definition: machine.h:204
PT_LOAD
#define PT_LOAD
Definition: exec_elf.h:337
ComponentFactory.h
debug
#define debug
Definition: dev_adb.cc:57
EI_CLASS
#define EI_CLASS
Definition: exec_elf.h:132
ELFCLASS64
#define ELFCLASS64
Definition: exec_elf.h:150
MEM_READ
#define MEM_READ
Definition: memory.h:116
EI_DATA
#define EI_DATA
Definition: exec_elf.h:133
refcount_ptr< Component >
ELFMAG3
#define ELFMAG3
Definition: exec_elf.h:143
UNITTESTS
#define UNITTESTS(class)
Helper for unit test case execution.
Definition: UnitTest.h:184
ET_EXEC
#define ET_EXEC
Definition: exec_elf.h:190
FileLoader_ELF
ELF binary loader.
Definition: FileLoader_ELF.h:46
EI_VERSION
#define EI_VERSION
Definition: exec_elf.h:134
FileLoader_ELF.h
FileLoader_ELF::DetectFileType
string DetectFileType(unsigned char *buf, size_t buflen, float &matchness) const
Attempt to detect file type.
Definition: FileLoader_ELF.cc:117
FileLoader_ELF::LoadIntoComponent
bool LoadIntoComponent(refcount_ptr< Component > component, ostream &messages) const
Loads the file into a Component.
Definition: FileLoader_ELF.cc:148
UNITTEST
#define UNITTEST(functionname)
Helper for unit test case execution.
Definition: UnitTest.h:217
exec_elf.h
Elf64_Phdr
Definition: exec_elf.h:324
SymbolRegistry::AddSymbol
void AddSymbol(const string &symbol, uint64_t vaddr)
Adds a symbol to the registry.
Definition: SymbolRegistry.cc:42
EI_MAG0
#define EI_MAG0
Definition: exec_elf.h:128
AddressDataBus::WriteData
virtual bool WriteData(const uint8_t &data, Endianness endianness=BigEndian)=0
Writes 8-bit data to the currently selected address.
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
N_ELF_MACHINE_TYPES
#define N_ELF_MACHINE_TYPES
Definition: FileLoader_ELF.cc:45
SymbolRegistry
A registry for loaded symbols.
Definition: SymbolRegistry.h:41
Elf64_Ehdr
Definition: exec_elf.h:110
Elf64_Shdr
Definition: exec_elf.h:374
EI_MAG3
#define EI_MAG3
Definition: exec_elf.h:131
Elf32_Phdr
Definition: exec_elf.h:313
Component::SetVariableValue
bool SetVariableValue(const string &name, const string &expression)
Sets a variable to a new value.
Definition: Component.cc:1030
AddressDataBus::AddressSelect
virtual void AddressSelect(uint64_t address)=0
Place an address on the bus.
FileLoader_ELF::FileLoader_ELF
FileLoader_ELF(const string &filename)
Definition: FileLoader_ELF.cc:111
EM_PPC64
#define EM_PPC64
Definition: exec_elf.h:221
SHT_SYMTAB
#define SHT_SYMTAB
Definition: exec_elf.h:390
ELFMAG0
#define ELFMAG0
Definition: exec_elf.h:140
Elf32_Ehdr
Definition: exec_elf.h:93
Elf32_Shdr
Definition: exec_elf.h:361
NO_EXCEPTIONS
#define NO_EXCEPTIONS
Definition: memory.h:125
CPUComponent.h
symbol
Definition: symbol.h:37
Elf32_Ehdr::e_ident
unsigned char e_ident[ELF_NIDENT]
Definition: exec_elf.h:94
EI_MAG2
#define EI_MAG2
Definition: exec_elf.h:130
EI_MAG1
#define EI_MAG1
Definition: exec_elf.h:129
FileLoaderImpl
A file loader.
Definition: FileLoaderImpl.h:42
SHT_STRTAB
#define SHT_STRTAB
Definition: exec_elf.h:391
ELFDATA2LSB
#define ELFDATA2LSB
Definition: exec_elf.h:155
ELFMAG2
#define ELFMAG2
Definition: exec_elf.h:142
ELFDATA2MSB
#define ELFDATA2MSB
Definition: exec_elf.h:156
cpu
Definition: cpu.h:326
Elf64_Sym
Definition: exec_elf.h:429
EM_PPC
#define EM_PPC
Definition: exec_elf.h:220
Component::AsCPUComponent
virtual CPUComponent * AsCPUComponent()
Returns the component's CPUComponent interface.
Definition: Component.cc:360
AddressDataBus
An interface for implementing components that read/write data via an address bus.
Definition: AddressDataBus.h:45
ELF_HEADER_VAR
#define ELF_HEADER_VAR(hdr32, hdr64, type, name)
ELFMAG1
#define ELFMAG1
Definition: exec_elf.h:141
AddressDataBus.h
Elf32_Sym
Definition: exec_elf.h:420
Component::AsAddressDataBus
virtual AddressDataBus * AsAddressDataBus()
Returns the component's AddressDataBus interface, if any.
Definition: Component.cc:367
EM_SH
#define EM_SH
Definition: exec_elf.h:230
FileLoaderImpl::Filename
const string & Filename() const
Definition: FileLoaderImpl.h:81
CPUComponent
A base-class for processors Component implementations.
Definition: CPUComponent.h:47

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18