LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
COFFObjectFile.cpp
Go to the documentation of this file.
1 //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares the COFFObjectFile class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Object/COFF.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/Support/Debug.h"
21 #include <cctype>
22 
23 using namespace llvm;
24 using namespace object;
25 
26 namespace {
31 }
32 
33 namespace {
34 // Returns false if size is greater than the buffer size. And sets ec.
35 bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
36  if (m->getBufferSize() < size) {
38  return false;
39  }
40  return true;
41 }
42 
43 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
44 // Returns unexpected_eof if error.
45 template<typename T>
46 error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr,
47  const size_t Size = sizeof(T)) {
48  uintptr_t Addr = uintptr_t(Ptr);
49  if (Addr + Size < Addr ||
50  Addr + Size < Size ||
51  Addr + Size > uintptr_t(M->getBufferEnd())) {
53  }
54  Obj = reinterpret_cast<const T *>(Addr);
55  return object_error::success;
56 }
57 }
58 
59 const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const {
60  const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p);
61 
62 # ifndef NDEBUG
63  // Verify that the symbol points to a valid entry in the symbol table.
64  uintptr_t offset = uintptr_t(addr) - uintptr_t(base());
65  if (offset < COFFHeader->PointerToSymbolTable
66  || offset >= COFFHeader->PointerToSymbolTable
67  + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
68  report_fatal_error("Symbol was outside of symbol table.");
69 
70  assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
71  == 0 && "Symbol did not point to the beginning of a symbol");
72 # endif
73 
74  return addr;
75 }
76 
77 const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const {
78  const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p);
79 
80 # ifndef NDEBUG
81  // Verify that the section points to a valid entry in the section table.
82  if (addr < SectionTable
83  || addr >= (SectionTable + COFFHeader->NumberOfSections))
84  report_fatal_error("Section was outside of section table.");
85 
86  uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable);
87  assert(offset % sizeof(coff_section) == 0 &&
88  "Section did not point to the beginning of a section");
89 # endif
90 
91  return addr;
92 }
93 
95  SymbolRef &Result) const {
96  const coff_symbol *symb = toSymb(Symb);
97  symb += 1 + symb->NumberOfAuxSymbols;
98  Symb.p = reinterpret_cast<uintptr_t>(symb);
99  Result = SymbolRef(Symb, this);
100  return object_error::success;
101 }
102 
104  StringRef &Result) const {
105  const coff_symbol *symb = toSymb(Symb);
106  return getSymbolName(symb, Result);
107 }
108 
110  uint64_t &Result) const {
111  const coff_symbol *symb = toSymb(Symb);
112  const coff_section *Section = NULL;
113  if (error_code ec = getSection(symb->SectionNumber, Section))
114  return ec;
115 
117  Result = UnknownAddressOrSize;
118  else if (Section)
119  Result = Section->PointerToRawData + symb->Value;
120  else
121  Result = symb->Value;
122  return object_error::success;
123 }
124 
126  uint64_t &Result) const {
127  const coff_symbol *symb = toSymb(Symb);
128  const coff_section *Section = NULL;
129  if (error_code ec = getSection(symb->SectionNumber, Section))
130  return ec;
131 
133  Result = UnknownAddressOrSize;
134  else if (Section)
135  Result = Section->VirtualAddress + symb->Value;
136  else
137  Result = symb->Value;
138  return object_error::success;
139 }
140 
142  SymbolRef::Type &Result) const {
143  const coff_symbol *symb = toSymb(Symb);
144  Result = SymbolRef::ST_Other;
147  Result = SymbolRef::ST_Unknown;
148  } else {
150  Result = SymbolRef::ST_Function;
151  } else {
152  uint32_t Characteristics = 0;
153  if (symb->SectionNumber > 0) {
154  const coff_section *Section = NULL;
155  if (error_code ec = getSection(symb->SectionNumber, Section))
156  return ec;
157  Characteristics = Section->Characteristics;
158  }
159  if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
160  ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
161  Result = SymbolRef::ST_Data;
162  }
163  }
164  return object_error::success;
165 }
166 
168  uint32_t &Result) const {
169  const coff_symbol *symb = toSymb(Symb);
170  Result = SymbolRef::SF_None;
171 
172  // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common
173 
176  Result |= SymbolRef::SF_Undefined;
177 
178  // TODO: This are certainly too restrictive.
180  Result |= SymbolRef::SF_Global;
181 
183  Result |= SymbolRef::SF_Weak;
184 
186  Result |= SymbolRef::SF_Absolute;
187 
188  return object_error::success;
189 }
190 
192  uint64_t &Result) const {
193  // FIXME: Return the correct size. This requires looking at all the symbols
194  // in the same section as this symbol, and looking for either the next
195  // symbol, or the end of the section.
196  const coff_symbol *symb = toSymb(Symb);
197  const coff_section *Section = NULL;
198  if (error_code ec = getSection(symb->SectionNumber, Section))
199  return ec;
200 
202  Result = UnknownAddressOrSize;
203  else if (Section)
204  Result = Section->SizeOfRawData - symb->Value;
205  else
206  Result = 0;
207  return object_error::success;
208 }
209 
211  section_iterator &Result) const {
212  const coff_symbol *symb = toSymb(Symb);
214  Result = end_sections();
215  else {
216  const coff_section *sec = 0;
217  if (error_code ec = getSection(symb->SectionNumber, sec)) return ec;
218  DataRefImpl Sec;
219  Sec.p = reinterpret_cast<uintptr_t>(sec);
220  Result = section_iterator(SectionRef(Sec, this));
221  }
222  return object_error::success;
223 }
224 
226  uint64_t &Val) const {
227  report_fatal_error("getSymbolValue unimplemented in COFFObjectFile");
228 }
229 
231  SectionRef &Result) const {
232  const coff_section *sec = toSec(Sec);
233  sec += 1;
234  Sec.p = reinterpret_cast<uintptr_t>(sec);
235  Result = SectionRef(Sec, this);
236  return object_error::success;
237 }
238 
240  StringRef &Result) const {
241  const coff_section *sec = toSec(Sec);
242  return getSectionName(sec, Result);
243 }
244 
246  uint64_t &Result) const {
247  const coff_section *sec = toSec(Sec);
248  Result = sec->VirtualAddress;
249  return object_error::success;
250 }
251 
253  uint64_t &Result) const {
254  const coff_section *sec = toSec(Sec);
255  Result = sec->SizeOfRawData;
256  return object_error::success;
257 }
258 
260  StringRef &Result) const {
261  const coff_section *sec = toSec(Sec);
262  ArrayRef<uint8_t> Res;
263  error_code EC = getSectionContents(sec, Res);
264  Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
265  return EC;
266 }
267 
269  uint64_t &Res) const {
270  const coff_section *sec = toSec(Sec);
271  if (!sec)
273  Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1);
274  return object_error::success;
275 }
276 
278  bool &Result) const {
279  const coff_section *sec = toSec(Sec);
280  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
281  return object_error::success;
282 }
283 
285  bool &Result) const {
286  const coff_section *sec = toSec(Sec);
287  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
288  return object_error::success;
289 }
290 
292  bool &Result) const {
293  const coff_section *sec = toSec(Sec);
294  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
295  return object_error::success;
296 }
297 
299  bool &Result) const {
300  // FIXME: Unimplemented
301  Result = true;
302  return object_error::success;
303 }
304 
306  bool &Result) const {
307  const coff_section *sec = toSec(Sec);
308  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
309  return object_error::success;
310 }
311 
313  bool &Result) const {
314  // FIXME: Unimplemented.
315  Result = false;
316  return object_error::success;
317 }
318 
320  bool &Result) const {
321  // FIXME: Unimplemented.
322  Result = false;
323  return object_error::success;
324 }
325 
327  DataRefImpl Symb,
328  bool &Result) const {
329  const coff_section *sec = toSec(Sec);
330  const coff_symbol *symb = toSymb(Symb);
331  const coff_section *symb_sec = 0;
332  if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec;
333  if (symb_sec == sec)
334  Result = true;
335  else
336  Result = false;
337  return object_error::success;
338 }
339 
341  const coff_section *sec = toSec(Sec);
342  DataRefImpl ret;
343  if (sec->NumberOfRelocations == 0)
344  ret.p = 0;
345  else
346  ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations);
347 
348  return relocation_iterator(RelocationRef(ret, this));
349 }
350 
352  const coff_section *sec = toSec(Sec);
353  DataRefImpl ret;
354  if (sec->NumberOfRelocations == 0)
355  ret.p = 0;
356  else
357  ret.p = reinterpret_cast<uintptr_t>(
358  reinterpret_cast<const coff_relocation*>(
359  base() + sec->PointerToRelocations)
360  + sec->NumberOfRelocations);
361 
362  return relocation_iterator(RelocationRef(ret, this));
363 }
364 
365 // Initialize the pointer to the symbol table.
366 error_code COFFObjectFile::initSymbolTablePtr() {
367  if (error_code ec = getObject(
368  SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable,
369  COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
370  return ec;
371 
372  // Find string table. The first four byte of the string table contains the
373  // total size of the string table, including the size field itself. If the
374  // string table is empty, the value of the first four byte would be 4.
375  const uint8_t *StringTableAddr =
376  base() + COFFHeader->PointerToSymbolTable +
377  COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
378  const ulittle32_t *StringTableSizePtr;
379  if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr))
380  return ec;
381  StringTableSize = *StringTableSizePtr;
382  if (error_code ec =
383  getObject(StringTable, Data, StringTableAddr, StringTableSize))
384  return ec;
385 
386  // Check that the string table is null terminated if has any in it.
387  if (StringTableSize < 4 ||
388  (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0))
390  return object_error::success;
391 }
392 
393 // Returns the file offset for the given RVA.
394 error_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const {
395  error_code ec;
396  for (section_iterator i = begin_sections(), e = end_sections(); i != e;
397  i.increment(ec)) {
398  if (ec)
399  return ec;
400  const coff_section *Section = getCOFFSection(i);
401  uint32_t SectionStart = Section->VirtualAddress;
402  uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
403  if (SectionStart <= Rva && Rva < SectionEnd) {
404  uint32_t Offset = Rva - SectionStart;
405  Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
406  return object_error::success;
407  }
408  }
410 }
411 
412 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
413 // table entry.
415 getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const {
416  uintptr_t IntPtr = 0;
417  if (error_code ec = getRvaPtr(Rva, IntPtr))
418  return ec;
419  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
420  Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
421  Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
422  return object_error::success;
423 }
424 
425 // Find the import table.
426 error_code COFFObjectFile::initImportTablePtr() {
427  // First, we get the RVA of the import table. If the file lacks a pointer to
428  // the import table, do nothing.
429  const data_directory *DataEntry;
430  if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
431  return object_error::success;
432 
433  // Do nothing if the pointer to import table is NULL.
434  if (DataEntry->RelativeVirtualAddress == 0)
435  return object_error::success;
436 
437  uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
438  NumberOfImportDirectory = DataEntry->Size /
440 
441  // Find the section that contains the RVA. This is needed because the RVA is
442  // the import table's memory address which is different from its file offset.
443  uintptr_t IntPtr = 0;
444  if (error_code ec = getRvaPtr(ImportTableRva, IntPtr))
445  return ec;
446  ImportDirectory = reinterpret_cast<
447  const import_directory_table_entry *>(IntPtr);
448 
449  // It's an error if there's no section containing the Import Table RVA.
451 }
452 
454  : ObjectFile(Binary::ID_COFF, Object)
455  , COFFHeader(0)
456  , PE32Header(0)
457  , DataDirectory(0)
458  , SectionTable(0)
459  , SymbolTable(0)
460  , StringTable(0)
461  , StringTableSize(0)
462  , ImportDirectory(0)
463  , NumberOfImportDirectory(0) {
464  // Check that we at least have enough room for a header.
465  if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
466 
467  // The current location in the file where we are looking at.
468  uint64_t CurPtr = 0;
469 
470  // PE header is optional and is present only in executables. If it exists,
471  // it is placed right after COFF header.
472  bool hasPEHeader = false;
473 
474  // Check if this is a PE/COFF file.
475  if (base()[0] == 0x4d && base()[1] == 0x5a) {
476  // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
477  // PE signature to find 'normal' COFF header.
478  if (!checkSize(Data, ec, 0x3c + 8)) return;
479  CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c);
480  // Check the PE magic bytes. ("PE\0\0")
481  if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) {
483  return;
484  }
485  CurPtr += 4; // Skip the PE magic bytes.
486  hasPEHeader = true;
487  }
488 
489  if ((ec = getObject(COFFHeader, Data, base() + CurPtr)))
490  return;
491  CurPtr += sizeof(coff_file_header);
492 
493  if (hasPEHeader) {
494  if ((ec = getObject(PE32Header, Data, base() + CurPtr)))
495  return;
496  if (PE32Header->Magic != 0x10b) {
497  // We only support PE32. If this is PE32 (not PE32+), the magic byte
498  // should be 0x10b. If this is not PE32, continue as if there's no PE
499  // header in this file.
500  PE32Header = 0;
501  } else if (PE32Header->NumberOfRvaAndSize > 0) {
502  const uint8_t *addr = base() + CurPtr + sizeof(pe32_header);
503  uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
504  if ((ec = getObject(DataDirectory, Data, addr, size)))
505  return;
506  }
507  CurPtr += COFFHeader->SizeOfOptionalHeader;
508  }
509 
510  if (!COFFHeader->isImportLibrary())
511  if ((ec = getObject(SectionTable, Data, base() + CurPtr,
512  COFFHeader->NumberOfSections * sizeof(coff_section))))
513  return;
514 
515  // Initialize the pointer to the symbol table.
516  if (COFFHeader->PointerToSymbolTable != 0)
517  if ((ec = initSymbolTablePtr()))
518  return;
519 
520  // Initialize the pointer to the beginning of the import table.
521  if ((ec = initImportTablePtr()))
522  return;
523 
525 }
526 
528  DataRefImpl ret;
529  ret.p = reinterpret_cast<uintptr_t>(SymbolTable);
530  return symbol_iterator(SymbolRef(ret, this));
531 }
532 
534  // The symbol table ends where the string table begins.
535  DataRefImpl ret;
536  ret.p = reinterpret_cast<uintptr_t>(StringTable);
537  return symbol_iterator(SymbolRef(ret, this));
538 }
539 
541  // TODO: implement
542  report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
543 }
544 
546  // TODO: implement
547  report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
548 }
549 
551  // TODO: implement
552  report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
553 }
554 
556  // TODO: implement
557  report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
558 }
559 
561  // COFF does not have this field.
562  return "";
563 }
564 
566  DataRefImpl Imp;
567  Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory);
569 }
570 
572  DataRefImpl Imp;
573  if (ImportDirectory) {
574  Imp.p = reinterpret_cast<uintptr_t>(
575  ImportDirectory + (NumberOfImportDirectory - 1));
576  } else {
577  Imp.p = 0;
578  }
580 }
581 
583  DataRefImpl ret;
584  ret.p = reinterpret_cast<uintptr_t>(SectionTable);
585  return section_iterator(SectionRef(ret, this));
586 }
587 
589  DataRefImpl ret;
590  int numSections = COFFHeader->isImportLibrary()
591  ? 0 : COFFHeader->NumberOfSections;
592  ret.p = reinterpret_cast<uintptr_t>(SectionTable + numSections);
593  return section_iterator(SectionRef(ret, this));
594 }
595 
597  return getArch() == Triple::x86_64 ? 8 : 4;
598 }
599 
601  switch(COFFHeader->Machine) {
603  return "COFF-i386";
605  return "COFF-x86-64";
606  default:
607  return "COFF-<unknown arch>";
608  }
609 }
610 
611 unsigned COFFObjectFile::getArch() const {
612  switch(COFFHeader->Machine) {
614  return Triple::x86;
616  return Triple::x86_64;
617  default:
618  return Triple::UnknownArch;
619  }
620 }
621 
622 // This method is kept here because lld uses this. As soon as we make
623 // lld to use getCOFFHeader, this method will be removed.
625  return getCOFFHeader(Res);
626 }
627 
629  Res = COFFHeader;
630  return object_error::success;
631 }
632 
634  Res = PE32Header;
635  return object_error::success;
636 }
637 
639  const data_directory *&Res) const {
640  // Error if if there's no data directory or the index is out of range.
641  if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize)
643  Res = &DataDirectory[index];
644  return object_error::success;
645 }
646 
648  const coff_section *&Result) const {
649  // Check for special index values.
650  if (index == COFF::IMAGE_SYM_UNDEFINED ||
651  index == COFF::IMAGE_SYM_ABSOLUTE ||
652  index == COFF::IMAGE_SYM_DEBUG)
653  Result = NULL;
654  else if (index > 0 && index <= COFFHeader->NumberOfSections)
655  // We already verified the section table data, so no need to check again.
656  Result = SectionTable + (index - 1);
657  else
659  return object_error::success;
660 }
661 
662 error_code COFFObjectFile::getString(uint32_t offset,
663  StringRef &Result) const {
664  if (StringTableSize <= 4)
665  // Tried to get a string from an empty string table.
667  if (offset >= StringTableSize)
669  Result = StringRef(StringTable + offset);
670  return object_error::success;
671 }
672 
674  const coff_symbol *&Result) const {
675  if (index < COFFHeader->NumberOfSymbols)
676  Result = SymbolTable + index;
677  else
679  return object_error::success;
680 }
681 
683  StringRef &Res) const {
684  // Check for string table entry. First 4 bytes are 0.
685  if (symbol->Name.Offset.Zeroes == 0) {
686  uint32_t Offset = symbol->Name.Offset.Offset;
687  if (error_code ec = getString(Offset, Res))
688  return ec;
689  return object_error::success;
690  }
691 
692  if (symbol->Name.ShortName[7] == 0)
693  // Null terminated, let ::strlen figure out the length.
694  Res = StringRef(symbol->Name.ShortName);
695  else
696  // Not null terminated, use all 8 bytes.
697  Res = StringRef(symbol->Name.ShortName, 8);
698  return object_error::success;
699 }
700 
702  const coff_symbol *symbol) const {
703  const uint8_t *aux = NULL;
704 
705  if ( symbol->NumberOfAuxSymbols > 0 ) {
706  // AUX data comes immediately after the symbol in COFF
707  aux = reinterpret_cast<const uint8_t *>(symbol + 1);
708 # ifndef NDEBUG
709  // Verify that the aux symbol points to a valid entry in the symbol table.
710  uintptr_t offset = uintptr_t(aux) - uintptr_t(base());
711  if (offset < COFFHeader->PointerToSymbolTable
712  || offset >= COFFHeader->PointerToSymbolTable
713  + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
714  report_fatal_error("Aux Symbol data was outside of symbol table.");
715 
716  assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
717  == 0 && "Aux Symbol data did not point to the beginning of a symbol");
718 # endif
719  }
720  return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol));
721 }
722 
724  StringRef &Res) const {
725  StringRef Name;
726  if (Sec->Name[7] == 0)
727  // Null terminated, let ::strlen figure out the length.
728  Name = Sec->Name;
729  else
730  // Not null terminated, use all 8 bytes.
731  Name = StringRef(Sec->Name, 8);
732 
733  // Check for string table entry. First byte is '/'.
734  if (Name[0] == '/') {
735  uint32_t Offset;
736  if (Name.substr(1).getAsInteger(10, Offset))
738  if (error_code ec = getString(Offset, Name))
739  return ec;
740  }
741 
742  Res = Name;
743  return object_error::success;
744 }
745 
747  ArrayRef<uint8_t> &Res) const {
748  // The only thing that we need to verify is that the contents is contained
749  // within the file bounds. We don't need to make sure it doesn't cover other
750  // data, as there's nothing that says that is not allowed.
751  uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
752  uintptr_t ConEnd = ConStart + Sec->SizeOfRawData;
753  if (ConEnd > uintptr_t(Data->getBufferEnd()))
755  Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart),
756  Sec->SizeOfRawData);
757  return object_error::success;
758 }
759 
760 const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
761  return reinterpret_cast<const coff_relocation*>(Rel.p);
762 }
764  RelocationRef &Res) const {
765  Rel.p = reinterpret_cast<uintptr_t>(
766  reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
767  Res = RelocationRef(Rel, this);
768  return object_error::success;
769 }
771  uint64_t &Res) const {
772  report_fatal_error("getRelocationAddress not implemented in COFFObjectFile");
773 }
775  uint64_t &Res) const {
776  Res = toRel(Rel)->VirtualAddress;
777  return object_error::success;
778 }
780  const coff_relocation* R = toRel(Rel);
781  DataRefImpl Symb;
782  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
783  return symbol_iterator(SymbolRef(Symb, this));
784 }
786  uint64_t &Res) const {
787  const coff_relocation* R = toRel(Rel);
788  Res = R->Type;
789  return object_error::success;
790 }
791 
793  return toSec(It->getRawDataRefImpl());
794 }
795 
797  return toSymb(It->getRawDataRefImpl());
798 }
799 
801  relocation_iterator &It) const {
802  return toRel(It->getRawDataRefImpl());
803 }
804 
805 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
806  case COFF::enum: res = #enum; break;
807 
809  SmallVectorImpl<char> &Result) const {
810  const coff_relocation *reloc = toRel(Rel);
811  StringRef res;
812  switch (COFFHeader->Machine) {
814  switch (reloc->Type) {
832  default:
833  res = "Unknown";
834  }
835  break;
837  switch (reloc->Type) {
849  default:
850  res = "Unknown";
851  }
852  break;
853  default:
854  res = "Unknown";
855  }
856  Result.append(res.begin(), res.end());
857  return object_error::success;
858 }
859 
860 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
861 
863  SmallVectorImpl<char> &Result) const {
864  const coff_relocation *reloc = toRel(Rel);
865  const coff_symbol *symb = 0;
866  if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec;
867  DataRefImpl sym;
868  sym.p = reinterpret_cast<uintptr_t>(symb);
869  StringRef symname;
870  if (error_code ec = getSymbolName(sym, symname)) return ec;
871  Result.append(symname.begin(), symname.end());
872  return object_error::success;
873 }
874 
876  LibraryRef &Result) const {
877  report_fatal_error("getLibraryNext not implemented in COFFObjectFile");
878 }
879 
881  StringRef &Result) const {
882  report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
883 }
884 
886 operator==(const ImportDirectoryEntryRef &Other) const {
887  return ImportDirectoryPimpl == Other.ImportDirectoryPimpl;
888 }
889 
891  return reinterpret_cast<const import_directory_table_entry *>(Imp.p);
892 }
893 
896  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
897  Dir += 1;
898  DataRefImpl Next;
899  Next.p = reinterpret_cast<uintptr_t>(Dir);
900  Result = ImportDirectoryEntryRef(Next, OwningObject);
901  return object_error::success;
902 }
903 
906  Result = toImportEntry(ImportDirectoryPimpl);
907  return object_error::success;
908 }
909 
911  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
912  uintptr_t IntPtr = 0;
913  if (error_code ec = OwningObject->getRvaPtr(Dir->NameRVA, IntPtr))
914  return ec;
915  const char *Ptr = reinterpret_cast<const char *>(IntPtr);
916  Result = StringRef(Ptr);
917  return object_error::success;
918 }
919 
921  const import_lookup_table_entry32 *&Result) const {
922  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
923  uintptr_t IntPtr = 0;
924  if (error_code ec = OwningObject->getRvaPtr(
925  Dir->ImportLookupTableRVA, IntPtr))
926  return ec;
927  Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr);
928  return object_error::success;
929 }
930 
931 namespace llvm {
932 
934  error_code ec;
935  return new COFFObjectFile(Object, ec);
936  }
937 
938 } // end namespace llvm
bool operator==(const ImportDirectoryEntryRef &Other) const
support::ulittle16_t Machine
Definition: Object/COFF.h:53
#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum)
friend class SymbolRef
Definition: ObjectFile.h:286
friend class SectionRef
Definition: ObjectFile.h:302
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const
const uint8_t * base() const
Definition: ObjectFile.h:274
support::ulittle32_t VirtualAddress
Definition: Object/COFF.h:191
import_directory_iterator import_directory_end() const
virtual uint8_t getBytesInAddress() const
The number of bytes used to represent an address in this object file format.
error_code getNext(ImportDirectoryEntryRef &Result) const
StringRef substr(size_t Start, size_t N=npos) const
Definition: StringRef.h:392
virtual section_iterator begin_sections() const
support::ulittle16_t NumberOfSections
Definition: Object/COFF.h:54
error_code getDataDirectory(uint32_t index, const data_directory *&Res) const
support::little16_t SectionNumber
Definition: Object/COFF.h:172
support::ulittle32_t PointerToRelocations
Definition: Object/COFF.h:194
virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const
virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const
error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const
virtual library_iterator end_libraries_needed() const
virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const
support::ulittle8_t NumberOfAuxSymbols
Definition: Object/COFF.h:177
error_code getSection(int32_t index, const coff_section *&Res) const
error_code getImportLookupEntry(const import_lookup_table_entry32 *&Result) const
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
uint8_t getComplexType() const
Definition: Object/COFF.h:183
virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const
virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const
virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const
virtual unsigned getArch() const
support::ulittle16_t SizeOfOptionalHeader
Definition: Object/COFF.h:58
virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const
virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const
virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const
support::ulittle32_t ImportLookupTableRVA
Definition: Object/COFF.h:137
support::ulittle32_t VirtualSize
Definition: Object/COFF.h:190
virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const
virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Result) const
support::ulittle32_t NameRVA
Definition: Object/COFF.h:140
virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const
error_code getImportTableEntry(const import_directory_table_entry *&Result) const
virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const
virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:109
iterator begin() const
Definition: StringRef.h:97
content_iterator< SectionRef > section_iterator
Definition: ObjectFile.h:133
support::ulittle16_t Magic
Definition: Object/COFF.h:66
int memcmp(const void *s1, const void *s2, size_t n);
support::ulittle32_t Characteristics
Definition: Object/COFF.h:198
virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const
* if(!EatIfPresent(lltok::kw_thread_local)) return false
detail::packed_endian_specific_integral< uint8_t, little, unaligned > ulittle8_t
Definition: Endian.h:92
virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const
virtual StringRef getFileFormatName() const
content_iterator< SymbolRef > symbol_iterator
Definition: ObjectFile.h:87
The 32-bit PE header that follows the COFF header.
Definition: Object/COFF.h:65
virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Result) const
support::ulittle32_t RelativeVirtualAddress
Definition: Object/COFF.h:132
virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const
A function that returns a base type.
Definition: Support/COFF.h:205
support::ulittle16_t Type
Definition: Object/COFF.h:204
support::ulittle8_t StorageClass
Definition: Object/COFF.h:176
virtual section_iterator end_sections() const
virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const
support::ulittle32_t SizeOfRawData
Definition: Object/COFF.h:192
void append(in_iter in_start, in_iter in_end)
Definition: SmallVector.h:445
virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const
content_iterator< RelocationRef > relocation_iterator
Definition: ObjectFile.h:129
enable_if_c< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Definition: StringRef.h:337
content_iterator< ImportDirectoryEntryRef > import_directory_iterator
Definition: Object/COFF.h:26
support::ulittle32_t VirtualAddress
Definition: Object/COFF.h:202
const coff_symbol * getCOFFSymbol(symbol_iterator &It) const
const coff_relocation * getCOFFRelocation(relocation_iterator &It) const
support::ulittle32_t SymbolTableIndex
Definition: Object/COFF.h:203
virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, bool &Res) const
friend class ImportDirectoryEntryRef
Definition: Object/COFF.h:225
virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const
virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const
error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const
ArrayRef< uint8_t > getSymbolAuxData(const coff_symbol *symbol) const
import_directory_iterator import_directory_begin() const
content_iterator & increment(error_code &err)
Definition: ObjectFile.h:65
support::ulittle32_t PointerToRawData
Definition: Object/COFF.h:193
friend class RelocationRef
Definition: ObjectFile.h:325
union llvm::object::coff_symbol::@72 Name
error_code getPE32Header(const pe32_header *&Res) const
static const import_directory_table_entry * toImportEntry(DataRefImpl Imp)
detail::packed_endian_specific_integral< int16_t, little, unaligned > little16_t
Definition: Endian.h:103
error_code getSymbol(uint32_t index, const coff_symbol *&Res) const
const uint64_t UnknownAddressOrSize
Definition: ObjectFile.h:261
COFFObjectFile(MemoryBuffer *Object, error_code &ec)
support::ulittle32_t Value
Definition: Object/COFF.h:171
virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const
virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const
support::ulittle32_t Size
Definition: Object/COFF.h:133
detail::packed_endian_specific_integral< uint16_t, little, unaligned > ulittle16_t
Definition: Endian.h:94
size_t getBufferSize() const
Definition: MemoryBuffer.h:53
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const
virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const
virtual library_iterator begin_libraries_needed() const
virtual symbol_iterator begin_dynamic_symbols() const
const char * getBufferEnd() const
Definition: MemoryBuffer.h:52
error_code getCOFFHeader(const coff_file_header *&Res) const
const coff_section * getCOFFSection(section_iterator &It) const
virtual symbol_iterator end_symbols() const
support::ulittle16_t NumberOfRelocations
Definition: Object/COFF.h:196
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:96
virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const
static ObjectFile * createCOFFObjectFile(MemoryBuffer *Object)
virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const
virtual symbol_iterator begin_symbols() const
iterator end() const
Definition: StringRef.h:99
virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const
support::ulittle32_t NumberOfRvaAndSize
Definition: Object/COFF.h:95
virtual symbol_iterator end_dynamic_symbols() const
support::ulittle32_t NumberOfSymbols
Definition: Object/COFF.h:57
error_code getHeader(const coff_file_header *&Res) const
support::ulittle32_t PointerToSymbolTable
Definition: Object/COFF.h:56
COFF::SectionCharacteristics Characteristics
Definition: COFFYAML.cpp:196
MemoryBuffer * Data
Definition: Binary.h:35
virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const
Definition: Object/COFF.h:136
const T * data() const
Definition: ArrayRef.h:106
StringTableOffset Offset
Definition: Object/COFF.h:168
virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const
error_code getName(StringRef &Result) const
virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl< char > &Result) const
virtual StringRef getLoadName() const