1 //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file declares the COFFObjectFile class.
12 //===----------------------------------------------------------------------===//
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/COFF.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
26 using namespace object;
28 using support::ulittle8_t;
29 using support::ulittle16_t;
30 using support::ulittle32_t;
31 using support::little16_t;
33 // Returns false if size is greater than the buffer size. And sets ec.
34 static bool checkSize(const MemoryBuffer *M, std::error_code &EC,
36 if (M->getBufferSize() < Size) {
37 EC = object_error::unexpected_eof;
43 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
44 // Returns unexpected_eof if error.
46 static std::error_code getObject(const T *&Obj, const MemoryBuffer *M,
48 const size_t Size = sizeof(T)) {
49 uintptr_t Addr = uintptr_t(Ptr);
50 if (Addr + Size < Addr ||
52 Addr + Size > uintptr_t(M->getBufferEnd())) {
53 return object_error::unexpected_eof;
55 Obj = reinterpret_cast<const T *>(Addr);
56 return object_error::success;
59 // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without
61 static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) {
62 assert(Str.size() <= 6 && "String too long, possible overflow.");
67 while (!Str.empty()) {
69 if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25
70 CharVal = Str[0] - 'A';
71 else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51
72 CharVal = Str[0] - 'a' + 26;
73 else if (Str[0] >= '0' && Str[0] <= '9') // 52..61
74 CharVal = Str[0] - '0' + 52;
75 else if (Str[0] == '+') // 62
77 else if (Str[0] == '/') // 63
82 Value = (Value * 64) + CharVal;
86 if (Value > std::numeric_limits<uint32_t>::max())
89 Result = static_cast<uint32_t>(Value);
93 const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Ref) const {
94 const coff_symbol *Addr = reinterpret_cast<const coff_symbol*>(Ref.p);
97 // Verify that the symbol points to a valid entry in the symbol table.
98 uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base());
99 if (Offset < COFFHeader->PointerToSymbolTable
100 || Offset >= COFFHeader->PointerToSymbolTable
101 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
102 report_fatal_error("Symbol was outside of symbol table.");
104 assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
105 == 0 && "Symbol did not point to the beginning of a symbol");
111 const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const {
112 const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);
115 // Verify that the section points to a valid entry in the section table.
116 if (Addr < SectionTable
117 || Addr >= (SectionTable + COFFHeader->NumberOfSections))
118 report_fatal_error("Section was outside of section table.");
120 uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable);
121 assert(Offset % sizeof(coff_section) == 0 &&
122 "Section did not point to the beginning of a section");
128 void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const {
129 const coff_symbol *Symb = toSymb(Ref);
130 Symb += 1 + Symb->NumberOfAuxSymbols;
131 Ref.p = reinterpret_cast<uintptr_t>(Symb);
134 std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref,
135 StringRef &Result) const {
136 const coff_symbol *Symb = toSymb(Ref);
137 return getSymbolName(Symb, Result);
140 std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref,
141 uint64_t &Result) const {
142 const coff_symbol *Symb = toSymb(Ref);
143 const coff_section *Section = nullptr;
144 if (std::error_code EC = getSection(Symb->SectionNumber, Section))
147 if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
148 Result = UnknownAddressOrSize;
150 Result = Section->VirtualAddress + Symb->Value;
152 Result = Symb->Value;
153 return object_error::success;
156 std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref,
157 SymbolRef::Type &Result) const {
158 const coff_symbol *Symb = toSymb(Ref);
159 Result = SymbolRef::ST_Other;
160 if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
161 Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {
162 Result = SymbolRef::ST_Unknown;
163 } else if (Symb->isFunctionDefinition()) {
164 Result = SymbolRef::ST_Function;
166 uint32_t Characteristics = 0;
167 if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) {
168 const coff_section *Section = nullptr;
169 if (std::error_code EC = getSection(Symb->SectionNumber, Section))
171 Characteristics = Section->Characteristics;
173 if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
174 ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
175 Result = SymbolRef::ST_Data;
177 return object_error::success;
180 uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
181 const coff_symbol *Symb = toSymb(Ref);
182 uint32_t Result = SymbolRef::SF_None;
184 // TODO: Correctly set SF_FormatSpecific, SF_Common
186 if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {
187 if (Symb->Value == 0)
188 Result |= SymbolRef::SF_Undefined;
190 Result |= SymbolRef::SF_Common;
194 // TODO: This are certainly too restrictive.
195 if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
196 Result |= SymbolRef::SF_Global;
198 if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
199 Result |= SymbolRef::SF_Weak;
201 if (Symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE)
202 Result |= SymbolRef::SF_Absolute;
207 std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref,
208 uint64_t &Result) const {
209 // FIXME: Return the correct size. This requires looking at all the symbols
210 // in the same section as this symbol, and looking for either the next
211 // symbol, or the end of the section.
212 const coff_symbol *Symb = toSymb(Ref);
213 const coff_section *Section = nullptr;
214 if (std::error_code EC = getSection(Symb->SectionNumber, Section))
217 if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
218 Result = UnknownAddressOrSize;
220 Result = Section->SizeOfRawData - Symb->Value;
223 return object_error::success;
227 COFFObjectFile::getSymbolSection(DataRefImpl Ref,
228 section_iterator &Result) const {
229 const coff_symbol *Symb = toSymb(Ref);
230 if (COFF::isReservedSectionNumber(Symb->SectionNumber)) {
231 Result = section_end();
233 const coff_section *Sec = nullptr;
234 if (std::error_code EC = getSection(Symb->SectionNumber, Sec))
237 Ref.p = reinterpret_cast<uintptr_t>(Sec);
238 Result = section_iterator(SectionRef(Ref, this));
240 return object_error::success;
243 void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const {
244 const coff_section *Sec = toSec(Ref);
246 Ref.p = reinterpret_cast<uintptr_t>(Sec);
249 std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref,
250 StringRef &Result) const {
251 const coff_section *Sec = toSec(Ref);
252 return getSectionName(Sec, Result);
255 std::error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref,
256 uint64_t &Result) const {
257 const coff_section *Sec = toSec(Ref);
258 Result = Sec->VirtualAddress;
259 return object_error::success;
262 std::error_code COFFObjectFile::getSectionSize(DataRefImpl Ref,
263 uint64_t &Result) const {
264 const coff_section *Sec = toSec(Ref);
265 Result = Sec->SizeOfRawData;
266 return object_error::success;
269 std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref,
270 StringRef &Result) const {
271 const coff_section *Sec = toSec(Ref);
272 ArrayRef<uint8_t> Res;
273 std::error_code EC = getSectionContents(Sec, Res);
274 Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
278 std::error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref,
279 uint64_t &Res) const {
280 const coff_section *Sec = toSec(Ref);
282 return object_error::parse_failed;
283 Res = uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1);
284 return object_error::success;
287 std::error_code COFFObjectFile::isSectionText(DataRefImpl Ref,
288 bool &Result) const {
289 const coff_section *Sec = toSec(Ref);
290 Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
291 return object_error::success;
294 std::error_code COFFObjectFile::isSectionData(DataRefImpl Ref,
295 bool &Result) const {
296 const coff_section *Sec = toSec(Ref);
297 Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
298 return object_error::success;
301 std::error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref,
302 bool &Result) const {
303 const coff_section *Sec = toSec(Ref);
304 Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
305 return object_error::success;
309 COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref,
310 bool &Result) const {
311 // FIXME: Unimplemented
313 return object_error::success;
316 std::error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref,
317 bool &Result) const {
318 const coff_section *Sec = toSec(Ref);
319 Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
320 return object_error::success;
323 std::error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref,
324 bool &Result) const {
325 // FIXME: Unimplemented.
327 return object_error::success;
330 std::error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref,
331 bool &Result) const {
332 // FIXME: Unimplemented.
334 return object_error::success;
337 std::error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef,
339 bool &Result) const {
340 const coff_section *Sec = toSec(SecRef);
341 const coff_symbol *Symb = toSymb(SymbRef);
342 const coff_section *SymbSec = nullptr;
343 if (std::error_code EC = getSection(Symb->SectionNumber, SymbSec))
349 return object_error::success;
352 relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
353 const coff_section *Sec = toSec(Ref);
355 if (Sec->NumberOfRelocations == 0) {
358 auto begin = reinterpret_cast<const coff_relocation*>(
359 base() + Sec->PointerToRelocations);
360 if (Sec->hasExtendedRelocations()) {
361 // Skip the first relocation entry repurposed to store the number of
365 Ret.p = reinterpret_cast<uintptr_t>(begin);
367 return relocation_iterator(RelocationRef(Ret, this));
370 static uint32_t getNumberOfRelocations(const coff_section *Sec,
371 const uint8_t *base) {
372 // The field for the number of relocations in COFF section table is only
373 // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
374 // NumberOfRelocations field, and the actual relocation count is stored in the
375 // VirtualAddress field in the first relocation entry.
376 if (Sec->hasExtendedRelocations()) {
377 auto *FirstReloc = reinterpret_cast<const coff_relocation*>(
378 base + Sec->PointerToRelocations);
379 return FirstReloc->VirtualAddress;
381 return Sec->NumberOfRelocations;
384 relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
385 const coff_section *Sec = toSec(Ref);
387 if (Sec->NumberOfRelocations == 0) {
390 auto begin = reinterpret_cast<const coff_relocation*>(
391 base() + Sec->PointerToRelocations);
392 uint32_t NumReloc = getNumberOfRelocations(Sec, base());
393 Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc);
395 return relocation_iterator(RelocationRef(Ret, this));
398 // Initialize the pointer to the symbol table.
399 std::error_code COFFObjectFile::initSymbolTablePtr() {
400 if (std::error_code EC = getObject(
401 SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable,
402 COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
405 // Find string table. The first four byte of the string table contains the
406 // total size of the string table, including the size field itself. If the
407 // string table is empty, the value of the first four byte would be 4.
408 const uint8_t *StringTableAddr =
409 base() + COFFHeader->PointerToSymbolTable +
410 COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
411 const ulittle32_t *StringTableSizePtr;
412 if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
414 StringTableSize = *StringTableSizePtr;
415 if (std::error_code EC =
416 getObject(StringTable, Data, StringTableAddr, StringTableSize))
419 // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
420 // tools like cvtres write a size of 0 for an empty table instead of 4.
421 if (StringTableSize < 4)
424 // Check that the string table is null terminated if has any in it.
425 if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)
426 return object_error::parse_failed;
427 return object_error::success;
430 // Returns the file offset for the given VA.
431 std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
432 uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase
433 : (uint64_t)PE32PlusHeader->ImageBase;
434 uint64_t Rva = Addr - ImageBase;
435 assert(Rva <= UINT32_MAX);
436 return getRvaPtr((uint32_t)Rva, Res);
439 // Returns the file offset for the given RVA.
440 std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
441 for (const SectionRef &S : sections()) {
442 const coff_section *Section = getCOFFSection(S);
443 uint32_t SectionStart = Section->VirtualAddress;
444 uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
445 if (SectionStart <= Addr && Addr < SectionEnd) {
446 uint32_t Offset = Addr - SectionStart;
447 Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
448 return object_error::success;
451 return object_error::parse_failed;
454 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
456 std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
457 StringRef &Name) const {
458 uintptr_t IntPtr = 0;
459 if (std::error_code EC = getRvaPtr(Rva, IntPtr))
461 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
462 Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
463 Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
464 return object_error::success;
467 // Find the import table.
468 std::error_code COFFObjectFile::initImportTablePtr() {
469 // First, we get the RVA of the import table. If the file lacks a pointer to
470 // the import table, do nothing.
471 const data_directory *DataEntry;
472 if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
473 return object_error::success;
475 // Do nothing if the pointer to import table is NULL.
476 if (DataEntry->RelativeVirtualAddress == 0)
477 return object_error::success;
479 uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
480 NumberOfImportDirectory = DataEntry->Size /
481 sizeof(import_directory_table_entry);
483 // Find the section that contains the RVA. This is needed because the RVA is
484 // the import table's memory address which is different from its file offset.
485 uintptr_t IntPtr = 0;
486 if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
488 ImportDirectory = reinterpret_cast<
489 const import_directory_table_entry *>(IntPtr);
490 return object_error::success;
493 // Find the export table.
494 std::error_code COFFObjectFile::initExportTablePtr() {
495 // First, we get the RVA of the export table. If the file lacks a pointer to
496 // the export table, do nothing.
497 const data_directory *DataEntry;
498 if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
499 return object_error::success;
501 // Do nothing if the pointer to export table is NULL.
502 if (DataEntry->RelativeVirtualAddress == 0)
503 return object_error::success;
505 uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
506 uintptr_t IntPtr = 0;
507 if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
510 reinterpret_cast<const export_directory_table_entry *>(IntPtr);
511 return object_error::success;
514 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, std::error_code &EC,
516 : ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(nullptr),
517 PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr),
518 SectionTable(nullptr), SymbolTable(nullptr), StringTable(nullptr),
519 StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0),
520 ExportDirectory(nullptr) {
521 // Check that we at least have enough room for a header.
522 if (!checkSize(Data, EC, sizeof(coff_file_header))) return;
524 // The current location in the file where we are looking at.
527 // PE header is optional and is present only in executables. If it exists,
528 // it is placed right after COFF header.
529 bool HasPEHeader = false;
531 // Check if this is a PE/COFF file.
532 if (base()[0] == 0x4d && base()[1] == 0x5a) {
533 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
534 // PE signature to find 'normal' COFF header.
535 if (!checkSize(Data, EC, 0x3c + 8)) return;
536 CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c);
537 // Check the PE magic bytes. ("PE\0\0")
538 if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) {
539 EC = object_error::parse_failed;
542 CurPtr += 4; // Skip the PE magic bytes.
546 if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
548 CurPtr += sizeof(coff_file_header);
551 const pe32_header *Header;
552 if ((EC = getObject(Header, Data, base() + CurPtr)))
555 const uint8_t *DataDirAddr;
556 uint64_t DataDirSize;
557 if (Header->Magic == 0x10b) {
559 DataDirAddr = base() + CurPtr + sizeof(pe32_header);
560 DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
561 } else if (Header->Magic == 0x20b) {
562 PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
563 DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
564 DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
566 // It's neither PE32 nor PE32+.
567 EC = object_error::parse_failed;
570 if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
572 CurPtr += COFFHeader->SizeOfOptionalHeader;
575 if (COFFHeader->isImportLibrary())
578 if ((EC = getObject(SectionTable, Data, base() + CurPtr,
579 COFFHeader->NumberOfSections * sizeof(coff_section))))
582 // Initialize the pointer to the symbol table.
583 if (COFFHeader->PointerToSymbolTable != 0)
584 if ((EC = initSymbolTablePtr()))
587 // Initialize the pointer to the beginning of the import table.
588 if ((EC = initImportTablePtr()))
591 // Initialize the pointer to the export table.
592 if ((EC = initExportTablePtr()))
595 EC = object_error::success;
598 basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const {
600 Ret.p = reinterpret_cast<uintptr_t>(SymbolTable);
601 return basic_symbol_iterator(SymbolRef(Ret, this));
604 basic_symbol_iterator COFFObjectFile::symbol_end_impl() const {
605 // The symbol table ends where the string table begins.
607 Ret.p = reinterpret_cast<uintptr_t>(StringTable);
608 return basic_symbol_iterator(SymbolRef(Ret, this));
611 library_iterator COFFObjectFile::needed_library_begin() const {
613 report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
616 library_iterator COFFObjectFile::needed_library_end() const {
618 report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
621 StringRef COFFObjectFile::getLoadName() const {
622 // COFF does not have this field.
626 import_directory_iterator COFFObjectFile::import_directory_begin() const {
627 return import_directory_iterator(
628 ImportDirectoryEntryRef(ImportDirectory, 0, this));
631 import_directory_iterator COFFObjectFile::import_directory_end() const {
632 return import_directory_iterator(
633 ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this));
636 export_directory_iterator COFFObjectFile::export_directory_begin() const {
637 return export_directory_iterator(
638 ExportDirectoryEntryRef(ExportDirectory, 0, this));
641 export_directory_iterator COFFObjectFile::export_directory_end() const {
642 if (!ExportDirectory)
643 return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this));
644 ExportDirectoryEntryRef Ref(ExportDirectory,
645 ExportDirectory->AddressTableEntries, this);
646 return export_directory_iterator(Ref);
649 section_iterator COFFObjectFile::section_begin() const {
651 Ret.p = reinterpret_cast<uintptr_t>(SectionTable);
652 return section_iterator(SectionRef(Ret, this));
655 section_iterator COFFObjectFile::section_end() const {
657 int NumSections = COFFHeader->isImportLibrary()
658 ? 0 : COFFHeader->NumberOfSections;
659 Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections);
660 return section_iterator(SectionRef(Ret, this));
663 uint8_t COFFObjectFile::getBytesInAddress() const {
664 return getArch() == Triple::x86_64 ? 8 : 4;
667 StringRef COFFObjectFile::getFileFormatName() const {
668 switch(COFFHeader->Machine) {
669 case COFF::IMAGE_FILE_MACHINE_I386:
671 case COFF::IMAGE_FILE_MACHINE_AMD64:
672 return "COFF-x86-64";
673 case COFF::IMAGE_FILE_MACHINE_ARMNT:
676 return "COFF-<unknown arch>";
680 unsigned COFFObjectFile::getArch() const {
681 switch(COFFHeader->Machine) {
682 case COFF::IMAGE_FILE_MACHINE_I386:
684 case COFF::IMAGE_FILE_MACHINE_AMD64:
685 return Triple::x86_64;
686 case COFF::IMAGE_FILE_MACHINE_ARMNT:
687 return Triple::thumb;
689 return Triple::UnknownArch;
693 // This method is kept here because lld uses this. As soon as we make
694 // lld to use getCOFFHeader, this method will be removed.
695 std::error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
696 return getCOFFHeader(Res);
700 COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
702 return object_error::success;
705 std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
707 return object_error::success;
711 COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
712 Res = PE32PlusHeader;
713 return object_error::success;
717 COFFObjectFile::getDataDirectory(uint32_t Index,
718 const data_directory *&Res) const {
719 // Error if if there's no data directory or the index is out of range.
721 return object_error::parse_failed;
722 assert(PE32Header || PE32PlusHeader);
723 uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
724 : PE32PlusHeader->NumberOfRvaAndSize;
726 return object_error::parse_failed;
727 Res = &DataDirectory[Index];
728 return object_error::success;
731 std::error_code COFFObjectFile::getSection(int32_t Index,
732 const coff_section *&Result) const {
733 // Check for special index values.
734 if (COFF::isReservedSectionNumber(Index))
736 else if (Index > 0 && Index <= COFFHeader->NumberOfSections)
737 // We already verified the section table data, so no need to check again.
738 Result = SectionTable + (Index - 1);
740 return object_error::parse_failed;
741 return object_error::success;
744 std::error_code COFFObjectFile::getString(uint32_t Offset,
745 StringRef &Result) const {
746 if (StringTableSize <= 4)
747 // Tried to get a string from an empty string table.
748 return object_error::parse_failed;
749 if (Offset >= StringTableSize)
750 return object_error::unexpected_eof;
751 Result = StringRef(StringTable + Offset);
752 return object_error::success;
755 std::error_code COFFObjectFile::getSymbol(uint32_t Index,
756 const coff_symbol *&Result) const {
757 if (Index < COFFHeader->NumberOfSymbols)
758 Result = SymbolTable + Index;
760 return object_error::parse_failed;
761 return object_error::success;
764 std::error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol,
765 StringRef &Res) const {
766 // Check for string table entry. First 4 bytes are 0.
767 if (Symbol->Name.Offset.Zeroes == 0) {
768 uint32_t Offset = Symbol->Name.Offset.Offset;
769 if (std::error_code EC = getString(Offset, Res))
771 return object_error::success;
774 if (Symbol->Name.ShortName[7] == 0)
775 // Null terminated, let ::strlen figure out the length.
776 Res = StringRef(Symbol->Name.ShortName);
778 // Not null terminated, use all 8 bytes.
779 Res = StringRef(Symbol->Name.ShortName, 8);
780 return object_error::success;
783 ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData(
784 const coff_symbol *Symbol) const {
785 const uint8_t *Aux = nullptr;
787 if (Symbol->NumberOfAuxSymbols > 0) {
788 // AUX data comes immediately after the symbol in COFF
789 Aux = reinterpret_cast<const uint8_t *>(Symbol + 1);
791 // Verify that the Aux symbol points to a valid entry in the symbol table.
792 uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
793 if (Offset < COFFHeader->PointerToSymbolTable
794 || Offset >= COFFHeader->PointerToSymbolTable
795 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
796 report_fatal_error("Aux Symbol data was outside of symbol table.");
798 assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
799 == 0 && "Aux Symbol data did not point to the beginning of a symbol");
802 return ArrayRef<uint8_t>(Aux,
803 Symbol->NumberOfAuxSymbols * sizeof(coff_symbol));
806 std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
807 StringRef &Res) const {
809 if (Sec->Name[7] == 0)
810 // Null terminated, let ::strlen figure out the length.
813 // Not null terminated, use all 8 bytes.
814 Name = StringRef(Sec->Name, 8);
816 // Check for string table entry. First byte is '/'.
817 if (Name[0] == '/') {
819 if (Name[1] == '/') {
820 if (decodeBase64StringEntry(Name.substr(2), Offset))
821 return object_error::parse_failed;
823 if (Name.substr(1).getAsInteger(10, Offset))
824 return object_error::parse_failed;
826 if (std::error_code EC = getString(Offset, Name))
831 return object_error::success;
835 COFFObjectFile::getSectionContents(const coff_section *Sec,
836 ArrayRef<uint8_t> &Res) const {
837 // The only thing that we need to verify is that the contents is contained
838 // within the file bounds. We don't need to make sure it doesn't cover other
839 // data, as there's nothing that says that is not allowed.
840 uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
841 uintptr_t ConEnd = ConStart + Sec->SizeOfRawData;
842 if (ConEnd > uintptr_t(Data->getBufferEnd()))
843 return object_error::parse_failed;
844 Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart),
846 return object_error::success;
849 const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
850 return reinterpret_cast<const coff_relocation*>(Rel.p);
853 void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
854 Rel.p = reinterpret_cast<uintptr_t>(
855 reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
858 std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
859 uint64_t &Res) const {
860 report_fatal_error("getRelocationAddress not implemented in COFFObjectFile");
863 std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel,
864 uint64_t &Res) const {
865 Res = toRel(Rel)->VirtualAddress;
866 return object_error::success;
869 symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
870 const coff_relocation* R = toRel(Rel);
872 Ref.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
873 return symbol_iterator(SymbolRef(Ref, this));
876 std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
877 uint64_t &Res) const {
878 const coff_relocation* R = toRel(Rel);
880 return object_error::success;
884 COFFObjectFile::getCOFFSection(const SectionRef &Section) const {
885 return toSec(Section.getRawDataRefImpl());
889 COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const {
890 return toSymb(Symbol.getRawDataRefImpl());
893 const coff_relocation *
894 COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const {
895 return toRel(Reloc.getRawDataRefImpl());
898 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
899 case COFF::reloc_type: \
904 COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,
905 SmallVectorImpl<char> &Result) const {
906 const coff_relocation *Reloc = toRel(Rel);
908 switch (COFFHeader->Machine) {
909 case COFF::IMAGE_FILE_MACHINE_AMD64:
910 switch (Reloc->Type) {
911 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
912 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
913 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
914 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
915 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
916 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
917 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
918 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
919 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
920 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
921 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
922 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
923 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
924 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
925 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
926 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
927 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
932 case COFF::IMAGE_FILE_MACHINE_ARMNT:
933 switch (Reloc->Type) {
934 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
935 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
936 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
937 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24);
938 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11);
939 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN);
940 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24);
941 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11);
942 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION);
943 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL);
944 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A);
945 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T);
946 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T);
947 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
948 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
953 case COFF::IMAGE_FILE_MACHINE_I386:
954 switch (Reloc->Type) {
955 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
956 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
957 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
958 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
959 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
960 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
961 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
962 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
963 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
964 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
965 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
973 Result.append(Res.begin(), Res.end());
974 return object_error::success;
977 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
980 COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
981 SmallVectorImpl<char> &Result) const {
982 const coff_relocation *Reloc = toRel(Rel);
983 const coff_symbol *Symb = nullptr;
984 if (std::error_code EC = getSymbol(Reloc->SymbolTableIndex, Symb))
987 Sym.p = reinterpret_cast<uintptr_t>(Symb);
989 if (std::error_code EC = getSymbolName(Sym, SymName))
991 Result.append(SymName.begin(), SymName.end());
992 return object_error::success;
995 std::error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData,
996 LibraryRef &Result) const {
997 report_fatal_error("getLibraryNext not implemented in COFFObjectFile");
1000 std::error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData,
1001 StringRef &Result) const {
1002 report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
1005 bool ImportDirectoryEntryRef::
1006 operator==(const ImportDirectoryEntryRef &Other) const {
1007 return ImportTable == Other.ImportTable && Index == Other.Index;
1010 void ImportDirectoryEntryRef::moveNext() {
1014 std::error_code ImportDirectoryEntryRef::getImportTableEntry(
1015 const import_directory_table_entry *&Result) const {
1016 Result = ImportTable;
1017 return object_error::success;
1020 std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
1021 uintptr_t IntPtr = 0;
1022 if (std::error_code EC =
1023 OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr))
1025 Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1026 return object_error::success;
1029 std::error_code ImportDirectoryEntryRef::getImportLookupEntry(
1030 const import_lookup_table_entry32 *&Result) const {
1031 uintptr_t IntPtr = 0;
1032 if (std::error_code EC =
1033 OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr))
1035 Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr);
1036 return object_error::success;
1039 bool ExportDirectoryEntryRef::
1040 operator==(const ExportDirectoryEntryRef &Other) const {
1041 return ExportTable == Other.ExportTable && Index == Other.Index;
1044 void ExportDirectoryEntryRef::moveNext() {
1048 // Returns the name of the current export symbol. If the symbol is exported only
1049 // by ordinal, the empty string is set as a result.
1050 std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {
1051 uintptr_t IntPtr = 0;
1052 if (std::error_code EC =
1053 OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr))
1055 Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1056 return object_error::success;
1059 // Returns the starting ordinal number.
1061 ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const {
1062 Result = ExportTable->OrdinalBase;
1063 return object_error::success;
1066 // Returns the export ordinal of the current export symbol.
1067 std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const {
1068 Result = ExportTable->OrdinalBase + Index;
1069 return object_error::success;
1072 // Returns the address of the current export symbol.
1073 std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const {
1074 uintptr_t IntPtr = 0;
1075 if (std::error_code EC =
1076 OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr))
1078 const export_address_table_entry *entry =
1079 reinterpret_cast<const export_address_table_entry *>(IntPtr);
1080 Result = entry[Index].ExportRVA;
1081 return object_error::success;
1084 // Returns the name of the current export symbol. If the symbol is exported only
1085 // by ordinal, the empty string is set as a result.
1087 ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
1088 uintptr_t IntPtr = 0;
1089 if (std::error_code EC =
1090 OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr))
1092 const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr);
1094 uint32_t NumEntries = ExportTable->NumberOfNamePointers;
1096 for (const ulittle16_t *I = Start, *E = Start + NumEntries;
1097 I < E; ++I, ++Offset) {
1100 if (std::error_code EC =
1101 OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr))
1103 const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr);
1104 if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr))
1106 Result = StringRef(reinterpret_cast<const char *>(IntPtr));
1107 return object_error::success;
1110 return object_error::success;
1113 ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object,
1116 std::unique_ptr<COFFObjectFile> Ret(
1117 new COFFObjectFile(Object, EC, BufferOwned));
1120 return Ret.release();