+// Returns the file offset for the given VA.
+std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const {
+ uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase
+ : (uint64_t)PE32PlusHeader->ImageBase;
+ uint64_t Rva = Addr - ImageBase;
+ assert(Rva <= UINT32_MAX);
+ return getRvaPtr((uint32_t)Rva, Res);
+}
+
+// Returns the file offset for the given RVA.
+std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const {
+ for (const SectionRef &S : sections()) {
+ const coff_section *Section = getCOFFSection(S);
+ uint32_t SectionStart = Section->VirtualAddress;
+ uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
+ if (SectionStart <= Addr && Addr < SectionEnd) {
+ uint32_t Offset = Addr - SectionStart;
+ Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
+ return object_error::success;
+ }
+ }
+ return object_error::parse_failed;
+}
+
+// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
+// table entry.
+std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
+ StringRef &Name) const {
+ uintptr_t IntPtr = 0;
+ if (std::error_code EC = getRvaPtr(Rva, IntPtr))
+ return EC;
+ const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
+ Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
+ Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
+ return object_error::success;
+}
+
+// Find the import table.
+std::error_code COFFObjectFile::initImportTablePtr() {
+ // First, we get the RVA of the import table. If the file lacks a pointer to
+ // the import table, do nothing.
+ const data_directory *DataEntry;
+ if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
+ return object_error::success;
+
+ // Do nothing if the pointer to import table is NULL.
+ if (DataEntry->RelativeVirtualAddress == 0)
+ return object_error::success;
+
+ uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
+ NumberOfImportDirectory = DataEntry->Size /
+ sizeof(import_directory_table_entry);
+
+ // Find the section that contains the RVA. This is needed because the RVA is
+ // the import table's memory address which is different from its file offset.
+ uintptr_t IntPtr = 0;
+ if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
+ return EC;
+ ImportDirectory = reinterpret_cast<
+ const import_directory_table_entry *>(IntPtr);
+ return object_error::success;
+}
+
+// Find the export table.
+std::error_code COFFObjectFile::initExportTablePtr() {
+ // First, we get the RVA of the export table. If the file lacks a pointer to
+ // the export table, do nothing.
+ const data_directory *DataEntry;
+ if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry))
+ return object_error::success;
+
+ // Do nothing if the pointer to export table is NULL.
+ if (DataEntry->RelativeVirtualAddress == 0)
+ return object_error::success;
+
+ uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress;
+ uintptr_t IntPtr = 0;
+ if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr))
+ return EC;
+ ExportDirectory =
+ reinterpret_cast<const export_directory_table_entry *>(IntPtr);
+ return object_error::success;
+}
+
+COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
+ : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
+ PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr),
+ SectionTable(nullptr), SymbolTable(nullptr), StringTable(nullptr),
+ StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0),
+ ExportDirectory(nullptr) {