diff options
Diffstat (limited to 'llvm/lib/Object/COFFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/COFFObjectFile.cpp | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index dc8a718c7a3..4ad2e99629d 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -445,9 +445,27 @@ error_code COFFObjectFile::initImportTablePtr() { return ec; ImportDirectory = reinterpret_cast< const import_directory_table_entry *>(IntPtr); + return object_error::success; +} - // It's an error if there's no section containing the Import Table RVA. - return object_error::parse_failed; +// Find the export table. +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 (error_code EC = getRvaPtr(ExportTableRva, IntPtr)) + return EC; + ExportDirectory = reinterpret_cast<const export_directory_table_entry *>(IntPtr); + return object_error::success; } COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) @@ -460,7 +478,8 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) , StringTable(0) , StringTableSize(0) , ImportDirectory(0) - , NumberOfImportDirectory(0) { + , NumberOfImportDirectory(0) + , ExportDirectory(0) { // Check that we at least have enough room for a header. if (!checkSize(Data, ec, sizeof(coff_file_header))) return; @@ -521,6 +540,10 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) if ((ec = initImportTablePtr())) return; + // Initialize the pointer to the export table. + if ((ec = initExportTablePtr())) + return; + ec = object_error::success; } @@ -572,6 +595,19 @@ import_directory_iterator COFFObjectFile::import_directory_end() const { ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); } +export_directory_iterator COFFObjectFile::export_directory_begin() const { + return export_directory_iterator( + ExportDirectoryEntryRef(ExportDirectory, 0, this)); +} + +export_directory_iterator COFFObjectFile::export_directory_end() const { + if (ExportDirectory == 0) + return export_directory_iterator(ExportDirectoryEntryRef(0, 0, this)); + ExportDirectoryEntryRef ref(ExportDirectory, + ExportDirectory->AddressTableEntries, this); + return export_directory_iterator(ref); +} + section_iterator COFFObjectFile::begin_sections() const { DataRefImpl ret; ret.p = reinterpret_cast<uintptr_t>(SectionTable); @@ -910,6 +946,62 @@ error_code ImportDirectoryEntryRef::getImportLookupEntry( return object_error::success; } +bool ExportDirectoryEntryRef:: +operator==(const ExportDirectoryEntryRef &Other) const { + return ExportTable == Other.ExportTable && Index == Other.Index; +} + +error_code +ExportDirectoryEntryRef::getNext(ExportDirectoryEntryRef &Result) const { + Result = ExportDirectoryEntryRef(ExportTable, Index + 1, OwningObject); + return object_error::success; +} + +// Returns the export ordinal of the current export symbol. +error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { + Result = ExportTable->OrdinalBase + Index; + return object_error::success; +} + +// Returns the address of the current export symbol. +error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { + uintptr_t IntPtr = 0; + if (error_code EC = OwningObject->getRvaPtr( + ExportTable->ExportAddressTableRVA, IntPtr)) + return EC; + const export_address_table_entry *entry = reinterpret_cast<const export_address_table_entry *>(IntPtr); + Result = entry[Index].ExportRVA; + return object_error::success; +} + +// Returns the name of the current export symbol. If the symbol is exported only +// by ordinal, the empty string is set as a result. +error_code ExportDirectoryEntryRef::getName(StringRef &Result) const { + uintptr_t IntPtr = 0; + if (error_code EC = OwningObject->getRvaPtr( + ExportTable->OrdinalTableRVA, IntPtr)) + return EC; + const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); + + uint32_t NumEntries = ExportTable->NumberOfNamePointers; + int Offset = 0; + for (const ulittle16_t *I = Start, *E = Start + NumEntries; + I < E; ++I, ++Offset) { + if (*I != Index) + continue; + if (error_code EC = OwningObject->getRvaPtr( + ExportTable->NamePointerRVA, IntPtr)) + return EC; + const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); + if (error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) + return EC; + Result = StringRef(reinterpret_cast<const char *>(IntPtr)); + return object_error::success; + } + Result = ""; + return object_error::success; +} + namespace llvm { ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { error_code ec; |