FileLoader_ELF.cc Source File

Back to the index.

FileLoader_ELF.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2010 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 89
46 static const char *elf_machine_type[N_ELF_MACHINE_TYPES] = {
47  "NONE", "M32", "SPARC", "386", /* 0..3 */
48  "68K", "88K", "486", "860", /* 4..7 */
49  "MIPS", "S370", "MIPS_RS3_LE", "RS6000", /* 8..11 */
50  "unknown12", "unknown13", "unknown14", "PARISC", /* 12..15 */
51  "NCUBE", "VPP500", "SPARC32PLUS", "960", /* 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", "unknown54", "unknown55", /* 52..55 */
61  "unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */
62  "unknown60", "unknown61", "AMD64", "unknown63", /* 60..63 */
63  "unknown64", "unknown65", "unknown66", "unknown67", /* 64..67 */
64  "unknown68", "unknown69", "unknown70", "unknown71", /* 68..71 */
65  "unknown72", "unknown73", "unknown74", "unknown75", /* 72..75 */
66  "unknown76", "unknown77", "unknown78", "unknown79", /* 76..79 */
67  "unknown80", "unknown81", "unknown82", "AVR", /* 80..83 */
68  "unknown84", "unknown85", "unknown86", "unknown87", /* 84..87 */
69  "M32R" /* 88 */
70 };
71 
72 
73 FileLoader_ELF::FileLoader_ELF(const string& filename)
74  : FileLoaderImpl(filename)
75 {
76 }
77 
78 
79 string FileLoader_ELF::DetectFileType(unsigned char *buf, size_t buflen, float& matchness) const
80 {
81  if (buflen < sizeof(Elf32_Ehdr))
82  return "";
83 
84  // Note: The e_ident part of the 32-bit and the 64-bit variants have
85  // the same layout, so it is safe to only check the 32-bit variant here.
86  Elf32_Ehdr* elf32_ehdr = (Elf32_Ehdr*) buf;
87  if (elf32_ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
88  elf32_ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
89  elf32_ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
90  elf32_ehdr->e_ident[EI_MAG3] == ELFMAG3) {
91  // We are here if this is either an ELF32 or ELF64.
92  int elfClass = elf32_ehdr->e_ident[EI_CLASS];
93 
94  matchness = 1.0;
95  if (elfClass == ELFCLASS32)
96  return "ELF32";
97  if (elfClass == ELFCLASS64)
98  return "ELF64";
99 
100  matchness = 0.0;
101  stringstream ss;
102  ss << "ELF Unknown class " << elfClass;
103  return ss.str();
104  }
105 
106  return "";
107 }
108 
109 
110 bool FileLoader_ELF::LoadIntoComponent(refcount_ptr<Component> component, ostream& messages) const
111 {
112  AddressDataBus* bus = component->AsAddressDataBus();
113  if (bus == NULL) {
114  messages << "Target is not an AddressDataBus.\n";
115  return false;
116  }
117 
118  ifstream file(Filename().c_str());
119  if (!file.is_open()) {
120  messages << "Unable to read file.\n";
121  return false;
122  }
123 
124  char buf[64];
125 
126  // buf must be large enough for the largest possible header we wish
127  // to examine to fit.
128  assert(sizeof(buf) >= sizeof(Elf32_Ehdr));
129  assert(sizeof(buf) >= sizeof(Elf64_Ehdr));
130 
131  memset(buf, 0, sizeof(buf));
132  file.read(buf, sizeof(buf));
133 
134  // Note: The e_ident part of the 32-bit and the 64-bit variants have
135  // the same layout, so it is safe to only use the 32-bit variant here.
136  Elf32_Ehdr* ehdr32 = (Elf32_Ehdr*) buf;
137  Elf64_Ehdr* ehdr64 = (Elf64_Ehdr*) buf;
138  if (ehdr32->e_ident[EI_MAG0] != ELFMAG0 ||
139  ehdr32->e_ident[EI_MAG1] != ELFMAG1 ||
140  ehdr32->e_ident[EI_MAG2] != ELFMAG2 ||
141  ehdr32->e_ident[EI_MAG3] != ELFMAG3) {
142  messages << "Not an ELF.\n";
143  return false;
144  }
145 
146  int elfClass = ehdr32->e_ident[EI_CLASS];
147  int elfDataEncoding = ehdr32->e_ident[EI_DATA];
148  int elfVersion = ehdr32->e_ident[EI_VERSION];
149 
150  if (elfClass != ELFCLASS32 && elfClass != ELFCLASS64) {
151  messages << "Unknown ELF class.\n";
152  return false;
153  }
154  if (elfDataEncoding != ELFDATA2LSB && elfDataEncoding != ELFDATA2MSB) {
155  messages << "Unknown ELF data encoding.\n";
156  return false;
157  }
158  if (elfVersion != EV_CURRENT) {
159  messages << "Unknown ELF version.\n";
160  return false;
161  }
162 
163  bool elf32 = elfClass == ELFCLASS32;
164 
165 #define ELF_HEADER_VAR(hdr32,hdr64,type,name) type name = elf32? hdr32->name \
166  : hdr64->name; \
167  if (elfDataEncoding == ELFDATA2LSB) { \
168  int size = elf32? sizeof(hdr32->name) : sizeof(hdr64->name); \
169  switch (size) { \
170  case 2: name = LE16_TO_HOST(name); break; \
171  case 4: name = LE32_TO_HOST(name); break; \
172  case 8: name = LE64_TO_HOST(name); break; \
173  } \
174  } else { \
175  int size = elf32? sizeof(hdr32->name) : sizeof(hdr64->name); \
176  switch (size) { \
177  case 2: name = BE16_TO_HOST(name); break; \
178  case 4: name = BE32_TO_HOST(name); break; \
179  case 8: name = BE64_TO_HOST(name); break; \
180  } \
181  }
182 
183  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_type);
184 
185  if (e_type != ET_EXEC) {
186  messages << "ELF file is not an Executable.\n";
187  return false;
188  }
189 
190  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_entry);
191  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_machine);
192 
193  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_phoff);
194  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_phentsize);
195  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_phnum);
196 
197  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_shoff);
198  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_shentsize);
199  ELF_HEADER_VAR(ehdr32, ehdr64, uint64_t, e_shnum);
200 
201  size_t expectedPhentSize = (elf32? sizeof(Elf32_Phdr) : sizeof(Elf64_Phdr));
202  if (e_phentsize != expectedPhentSize) {
203  messages << "Incorrect ELF phentsize? " << e_phentsize << ", should "
204  "be " << expectedPhentSize << "\n"
205  "Perhaps this is a dynamically linked "
206  "binary (which isn't supported yet).\n";
207  return false;
208  }
209 
210  size_t expectedShentSize = (elf32? sizeof(Elf32_Shdr) : sizeof(Elf64_Shdr));
211  if (e_shentsize != expectedShentSize) {
212  messages << "Incorrect ELF shentsize? " << e_shentsize << ", should "
213  "be " << expectedShentSize << "\n"
214  "Perhaps this is a dynamically linked "
215  "binary (which isn't supported yet).\n";
216  return false;
217  }
218 
219  if (e_machine < N_ELF_MACHINE_TYPES)
220  messages << elf_machine_type[e_machine];
221  else
222  messages << "machine type '" << e_machine << "'";
223  messages << " ELF" << (elf32? 32 : 64) << " ";
224 
225  messages << (elfDataEncoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)") << ": ";
226 
227  if (!elf32 && (e_machine == EM_PPC || e_machine == EM_PPC64))
228  messages << "PPC function descriptor at";
229  else
230  messages << "entry point";
231 
232  messages << " 0x";
233  messages.flags(std::ios::hex);
234 
235  // Special case for MIPS: 32-bit addresses are sign-extended.
236  if (e_machine == EM_MIPS && elf32)
237  e_entry = (int32_t) e_entry;
238 
239  uint64_t display_entry_point = e_entry;
240 
241  // MIPS16 encoding (16-bit words) is indicated by the lowest bit of the PC.
242  bool mips16 = false;
243  if (e_machine == EM_MIPS && (e_entry & 1)) {
244  display_entry_point &= ~1;
245  mips16 = true;
246  }
247 
248  // SHmedia (SH64) 32-bit encoding is indicated by the lowest bit of the PC.
249  bool shmedia = false;
250  if (e_machine == EM_SH && (e_entry & 1)) {
251  display_entry_point &= ~1;
252  shmedia = true;
253  }
254 
255  if (elf32)
256  messages << setw(8) << setfill('0') << (uint32_t) display_entry_point;
257  else
258  messages << setw(16) << setfill('0') << (uint64_t) display_entry_point;
259 
260  if (mips16)
261  messages << " (MIPS16 encoding)";
262 
263  if (shmedia)
264  messages << " (SHmedia encoding)";
265 
266  messages << "\n";
267 
268  // PROGRAM HEADERS
269  size_t i;
270  for (i=0; i<e_phnum; ++i) {
271  // Load Phdr number i:
272  file.seekg(e_phoff + i * e_phentsize, std::ios::beg);
273 
274  char phdr_buf[64];
275  assert(sizeof(phdr_buf) >= sizeof(Elf32_Phdr));
276  assert(sizeof(phdr_buf) >= sizeof(Elf64_Phdr));
277  Elf32_Phdr* phdr32 = (Elf32_Phdr*) phdr_buf;
278  Elf64_Phdr* phdr64 = (Elf64_Phdr*) phdr_buf;
279 
280  memset(phdr_buf, 0, sizeof(phdr_buf));
281 
282  int toRead = elf32? sizeof(Elf32_Phdr) : sizeof(Elf64_Phdr);
283  file.read(phdr_buf, toRead);
284  if (file.gcount() != toRead) {
285  messages << "Unable to read Phdr.\n";
286  return false;
287  }
288 
289  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_type);
290  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_offset);
291  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_vaddr);
292  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_filesz);
293  ELF_HEADER_VAR(phdr32, phdr64, uint64_t, p_memsz);
294 
295  // Skip non-loadable program segments:
296  if (p_type != PT_LOAD)
297  continue;
298 
299  if (p_memsz < p_filesz) {
300  messages << "memsz < filesz. TODO: how"
301  " to handle this? memsz = " << p_memsz <<
302  ", filesz = " << p_filesz << "\n";
303  return false;
304  }
305 
306  // Special case for MIPS: 32-bit addresses are sign-extended.
307  if (e_machine == EM_MIPS && elf32)
308  p_vaddr = (int32_t) p_vaddr;
309 
310  messages.flags(std::ios::hex);
311  messages << "loadable chunk: vaddr 0x";
312 
313  if (elf32)
314  messages << setw(8) << setfill('0') << (uint32_t) p_vaddr;
315  else
316  messages << setw(16) << setfill('0') << (uint64_t) p_vaddr;
317 
318  messages.flags(std::ios::dec);
319  messages << ", " << p_filesz << " bytes\n";
320 
321  file.seekg(p_offset, std::ios::beg);
322  char databuf[65536];
323  uint64_t bytesRead = 0;
324  uint64_t vaddrToWriteTo = p_vaddr;
325 
326  while (bytesRead < p_filesz) {
327  int sizeToRead = sizeof(databuf);
328  if (sizeToRead + bytesRead > p_filesz)
329  sizeToRead = p_filesz - bytesRead;
330 
331  assert(sizeToRead != 0);
332  memset(databuf, 0, sizeToRead);
333 
334  file.read(databuf, sizeToRead);
335  int bytesReadThisTime = file.gcount();
336  bytesRead += bytesReadThisTime;
337 
338  // Write to the bus, one byte at a time.
339  for (int k=0; k<bytesReadThisTime; ++k) {
340  bus->AddressSelect(vaddrToWriteTo);
341  if (!bus->WriteData(databuf[k])) {
342  messages.flags(std::ios::hex);
343  messages << "Failed to write data to "
344  "virtual address 0x"
345  << vaddrToWriteTo << "\n";
346  return false;
347  }
348 
349  ++ vaddrToWriteTo;
350  }
351  }
352  }
353 
354  // SECTION HEADERS
355  vector<char> symtab;
356  vector<char> symstrings;
357  for (i=0; i<e_shnum; ++i) {
358  // Load Shdr number i:
359  file.seekg(e_shoff + i * e_shentsize, std::ios::beg);
360 
361  char shdr_buf[64];
362  assert(sizeof(shdr_buf) >= sizeof(Elf32_Shdr));
363  assert(sizeof(shdr_buf) >= sizeof(Elf64_Shdr));
364  Elf32_Shdr* shdr32 = (Elf32_Shdr*) shdr_buf;
365  Elf64_Shdr* shdr64 = (Elf64_Shdr*) shdr_buf;
366 
367  memset(shdr_buf, 0, sizeof(shdr_buf));
368 
369  int toRead = elf32? sizeof(Elf32_Shdr) : sizeof(Elf64_Shdr);
370  file.read(shdr_buf, toRead);
371  if (file.gcount() != toRead) {
372  messages << "Unable to read Shdr.\n";
373  return false;
374  }
375 
376  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_name);
377  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_type);
378  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_flags);
379  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_addr);
380  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_offset);
381  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_size);
382  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_link);
383  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_info);
384  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_addralign);
385  ELF_HEADER_VAR(shdr32, shdr64, uint64_t, sh_entsize);
386 
387  if (sh_type == SHT_SYMTAB) {
388  if (symtab.size() > 0) {
389  messages << "symtab: another symtab already loaded? TODO\n";
390  return false;
391  }
392 
393  int entrySize = elf32? sizeof(Elf32_Sym) : sizeof(Elf64_Sym);
394  int nEntries = sh_size / entrySize;
395 
396  messages.flags(std::ios::dec);
397  messages << "symtab: " << nEntries << " symbols at 0x";
398  messages.flags(std::ios::hex);
399  messages << sh_offset << "\n";
400 
401  symtab.resize(sh_size);
402  file.seekg(sh_offset, std::ios::beg);
403  file.read(&symtab[0], sh_size);
404  if ((uint64_t) file.gcount() != sh_size) {
405  messages << "Failed to read all " << sh_size << " symbol bytes.\n";
406  return false;
407  }
408  }
409 
410  // TODO/HACK: Figure out which strtab to use. For now, simply
411  // use the largest one!
412  if (sh_type == SHT_STRTAB && sh_size > symstrings.size()) {
413  messages.flags(std::ios::dec);
414  messages << "strtab: " << sh_size << " bytes at 0x";
415  messages.flags(std::ios::hex);
416  messages << sh_offset << "\n";
417 
418  symstrings.resize(sh_size);
419  file.seekg(sh_offset, std::ios::beg);
420  file.read(&symstrings[0], sh_size);
421  if ((uint64_t) file.gcount() != sh_size) {
422  messages << "Failed to read all " << sh_size << " symbol string bytes.\n";
423  return false;
424  }
425  }
426  }
427 
428  SymbolRegistry* symbolRegistry = NULL;
429  CPUComponent* cpu = component->AsCPUComponent();
430  if (cpu != NULL)
431  symbolRegistry = &cpu->GetSymbolRegistry();
432 
433  // Symbols
434  if (symbolRegistry != NULL && symtab.size() > 0 && symstrings.size() > 0) {
435  int entrySize = elf32? sizeof(Elf32_Sym) : sizeof(Elf64_Sym);
436  int nEntries = symtab.size() / entrySize;
437 
438  // For safety:
439  symstrings.resize(symstrings.size() + 1);
440  symstrings[symstrings.size() - 1] = '\0';
441 
442  int nsymbols = 0;
443 
444  messages.flags(std::ios::hex);
445 
446  for (int j=0; j<nEntries; j++) {
447  size_t p = j * entrySize;
448  Elf32_Sym* sym32 = (Elf32_Sym*) &symtab[p];
449  Elf64_Sym* sym64 = (Elf64_Sym*) &symtab[p];
450 
451  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_name);
452  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_info);
453  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_value);
454  ELF_HEADER_VAR(sym32, sym64, uint64_t, st_size);
455 
456  int bind = elf32? ELF32_ST_BIND(st_info) : ELF64_ST_BIND(st_info);
457  if (bind == STB_LOCAL)
458  continue;
459 
460  if (st_size == 0)
461  st_size ++;
462 
463  if (st_name >= symstrings.size() - 1) {
464  messages << "symbol pointer mismatch?\n";
465  continue;
466  }
467 
468  string symbol = &symstrings[st_name];
469 
470  // Special case for MIPS: 32-bit addresses are sign-extended.
471  if (e_machine == EM_MIPS && elf32)
472  st_value = (int32_t) st_value;
473 
474  // Special case for MIPS: _gp symbol initiates the GP register.
475  if (e_machine == EM_MIPS && symbol == "_gp") {
476  messages << "found _gp address: 0x";
477  if (elf32)
478  messages << setw(8) << setfill('0') << (uint32_t) st_value << "\n";
479  else
480  messages << setw(16) << setfill('0') << (uint64_t) st_value << "\n";
481 
482  stringstream ss;
483  ss << st_value;
484  component->SetVariableValue("gp", ss.str());
485  }
486 
487  // FOR DEBUGGING ONLY:
488  // messages << "symbol name '" << symbol << "', addr 0x" <<
489  // st_value << ", size 0x" << st_size << "\n";
490 
491  // Add this symbol to the symbol registry:
492  symbolRegistry->AddSymbol(symbol, st_value);
493  ++ nsymbols;
494  }
495 
496  messages.flags(std::ios::dec);
497  messages << nsymbols << " symbols read\n";
498  }
499 
500  // Set the CPU's entry point.
501 
502 #if 0
503  if (elf64 && arch == ARCH_PPC) {
504  /*
505  * Special case for 64-bit PPC ELFs:
506  *
507  * The ELF starting symbol points to a ".opd" section
508  * which contains a function descriptor:
509  *
510  * uint64_t start;
511  * uint64_t toc_base;
512  * uint64_t something_else; (?)
513  */
514  int res;
515  unsigned char b[sizeof(uint64_t)];
516  uint64_t toc_base;
517 
518  debug("PPC64: ");
519 
520  res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
521  sizeof(b), MEM_READ, NO_EXCEPTIONS);
522  if (!res)
523  debug(" [WARNING: could not read memory?] ");
524 
525  /* PPC are always big-endian: */
526  *entrypointp = ((uint64_t)b[0] << 56) +
527  ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
528  ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
529  ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
530  (uint64_t)b[7];
531 
532  res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
533  b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
534  if (!res)
535  fatal(" [WARNING: could not read memory?] ");
536 
537  toc_base = ((uint64_t)b[0] << 56) +
538  ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
539  ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
540  ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
541  (uint64_t)b[7];
542 
543  debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n",
544  (uint64_t) *entrypointp, (uint64_t) toc_base);
545  if (tocp != NULL)
546  *tocp = toc_base;
547  }
548 #endif
549 
550  stringstream ss;
551  ss << e_entry;
552  component->SetVariableValue("pc", ss.str());
553  component->SetVariableValue("bigendian",
554  elfDataEncoding == ELFDATA2LSB? "false" : "true");
555 
556  return true;
557 }
558 
559 
560 /*****************************************************************************/
561 
562 
563 #ifdef WITHUNITTESTS
564 
565 #include "ComponentFactory.h"
566 
567 static void Test_FileLoader_ELF_Constructor()
568 {
569  FileLoader_ELF elfLoader("test/FileLoader_ELF_MIPS");
570 }
571 
573 {
574  UNITTEST(Test_FileLoader_ELF_Constructor);
575 
576  // TODO
577 }
578 
579 #endif
A registry for loaded symbols.
#define N_ELF_MACHINE_TYPES
virtual CPUComponent * AsCPUComponent()
Returns the component&#39;s CPUComponent interface.
Definition: Component.cc:360
void fatal(const char *fmt,...)
Definition: main.cc:152
bool LoadIntoComponent(refcount_ptr< Component > component, ostream &messages) const
Loads the file into a Component.
void AddSymbol(const string &symbol, uint64_t vaddr)
Adds a symbol to the registry.
#define ELFMAG2
Definition: exec_elf.h:141
#define ARCH_PPC
Definition: machine.h:204
const string & Filename() const
#define EM_MIPS
Definition: exec_elf.h:189
virtual bool WriteData(const uint8_t &data, Endianness endianness=BigEndian)=0
Writes 8-bit data to the currently selected address.
#define MEM_READ
Definition: memory.h:116
ELF binary loader.
#define ELFMAG1
Definition: exec_elf.h:140
#define ELFMAG0
Definition: exec_elf.h:139
#define ELF64_ST_BIND(info)
Definition: exec_elf.h:385
An interface for implementing components that read/write data via an address bus. ...
A file loader.
#define ELFDATA2LSB
Definition: exec_elf.h:154
#define ELFDATA2MSB
Definition: exec_elf.h:155
#define UNITTESTS(class)
Helper for unit test case execution.
Definition: UnitTest.h:184
#define EI_MAG1
Definition: exec_elf.h:128
#define SHT_STRTAB
Definition: exec_elf.h:306
#define EM_PPC64
Definition: exec_elf.h:199
#define STB_LOCAL
Definition: exec_elf.h:357
#define EI_MAG2
Definition: exec_elf.h:129
#define EI_CLASS
Definition: exec_elf.h:131
#define ELFCLASS64
Definition: exec_elf.h:149
#define PT_LOAD
Definition: exec_elf.h:252
#define SHT_SYMTAB
Definition: exec_elf.h:305
#define EI_MAG3
Definition: exec_elf.h:130
#define ET_EXEC
Definition: exec_elf.h:170
#define EI_MAG0
Definition: exec_elf.h:127
SymbolRegistry & GetSymbolRegistry()
Gets a reference to the CPU&#39;s symbol registry.
Definition: CPUComponent.h:63
#define EI_VERSION
Definition: exec_elf.h:133
#define EM_PPC
Definition: exec_elf.h:198
#define debug
Definition: dev_adb.cc:57
string DetectFileType(unsigned char *buf, size_t buflen, float &matchness) const
Attempt to detect file type.
Definition: cpu.h:326
#define NO_EXCEPTIONS
Definition: memory.h:125
unsigned char e_ident[ELF_NIDENT]
Definition: exec_elf.h:93
A base-class for processors Component implementations.
Definition: CPUComponent.h:43
#define EI_DATA
Definition: exec_elf.h:132
virtual void AddressSelect(uint64_t address)=0
Place an address on the bus.
bool SetVariableValue(const string &name, const string &expression)
Sets a variable to a new value.
Definition: Component.cc:1030
#define ELFCLASS32
Definition: exec_elf.h:148
#define EM_SH
Definition: exec_elf.h:206
virtual AddressDataBus * AsAddressDataBus()
Returns the component&#39;s AddressDataBus interface, if any.
Definition: Component.cc:367
Definition: symbol.h:37
#define EV_CURRENT
Definition: exec_elf.h:159
FileLoader_ELF(const string &filename)
#define ELFMAG3
Definition: exec_elf.h:142
#define UNITTEST(functionname)
Helper for unit test case execution.
Definition: UnitTest.h:217
#define ELF32_ST_BIND(info)
Definition: exec_elf.h:381
#define ELF_HEADER_VAR(hdr32, hdr64, type, name)

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13