From 3d49ad0cbcfb90a5a933cf72a9ca7473652d6a3c Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 2 Oct 2014 22:05:29 +0000 Subject: [PATCH] llvm-readobj: print COFF imported symbols This patch defines a new iterator for the imported symbols. Make a change to COFFDumper to use that iterator to print out imported symbols and its ordinals. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218915 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 43 +++++++++++-- lib/Object/COFFObjectFile.cpp | 90 ++++++++++++++++++++++++++++ test/tools/llvm-readobj/imports.test | 4 ++ tools/llvm-readobj/COFFDumper.cpp | 8 +++ 4 files changed, 141 insertions(+), 4 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index f7a578315c1..b59e5de4bd1 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -26,8 +26,10 @@ template class ArrayRef; namespace object { class ImportDirectoryEntryRef; class ExportDirectoryEntryRef; +class ImportedSymbolRef; typedef content_iterator import_directory_iterator; typedef content_iterator export_directory_iterator; +typedef content_iterator imported_symbol_iterator; /// The DOS compatible header at the front of all PE/COFF executables. struct dos_header { @@ -160,10 +162,11 @@ struct import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; -struct import_lookup_table_entry32 { - support::ulittle32_t data; +template +struct import_lookup_table_entry { + IntTy data; - bool isOrdinal() const { return data & 0x80000000; } + bool isOrdinal() const { return data < 0; } uint16_t getOrdinal() const { assert(isOrdinal() && "ILT entry is not an ordinal!"); @@ -172,10 +175,15 @@ struct import_lookup_table_entry32 { uint32_t getHintNameRVA() const { assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); - return data; + return data & 0xFFFFFFFF; } }; +typedef import_lookup_table_entry + import_lookup_table_entry32; +typedef import_lookup_table_entry + import_lookup_table_entry64; + struct export_directory_table_entry { support::ulittle32_t ExportFlags; support::ulittle32_t TimeDateStamp; @@ -650,6 +658,10 @@ public: bool operator==(const ImportDirectoryEntryRef &Other) const; void moveNext(); + + imported_symbol_iterator imported_symbol_begin() const; + imported_symbol_iterator imported_symbol_end() const; + std::error_code getName(StringRef &Result) const; std::error_code getImportLookupTableRVA(uint32_t &Result) const; std::error_code getImportAddressTableRVA(uint32_t &Result) const; @@ -688,6 +700,29 @@ private: uint32_t Index; const COFFObjectFile *OwningObject; }; + +class ImportedSymbolRef { +public: + ImportedSymbolRef() : OwningObject(nullptr) {} + ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} + ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} + + bool operator==(const ImportedSymbolRef &Other) const; + void moveNext(); + + std::error_code getSymbolName(StringRef &Result) const; + std::error_code getOrdinal(uint16_t &Result) const; + +private: + const import_lookup_table_entry32 *Entry32; + const import_lookup_table_entry64 *Entry64; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; } // end namespace object } // end namespace llvm diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index d77238c6add..f533d5e21e6 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -27,6 +27,7 @@ using namespace object; using support::ulittle16_t; using support::ulittle32_t; +using support::ulittle64_t; using support::little16_t; // Returns false if size is greater than the buffer size. And sets ec. @@ -1034,6 +1035,42 @@ std::error_code ImportDirectoryEntryRef::getImportTableEntry( return object_error::success; } +static imported_symbol_iterator +makeImportedSymbolIterator(const COFFObjectFile *OwningObject, + uintptr_t Ptr, int Index) { + if (OwningObject->getBytesInAddress() == 4) { + auto *P = reinterpret_cast(Ptr); + return imported_symbol_iterator(ImportedSymbolRef(P, Index, OwningObject)); + } + auto *P = reinterpret_cast(Ptr); + return imported_symbol_iterator(ImportedSymbolRef(P, Index, OwningObject)); +} + +imported_symbol_iterator +ImportDirectoryEntryRef::imported_symbol_begin() const { + uintptr_t IntPtr = 0; + OwningObject->getRvaPtr(ImportTable[Index].ImportLookupTableRVA, IntPtr); + return makeImportedSymbolIterator(OwningObject, IntPtr, 0); +} + +imported_symbol_iterator +ImportDirectoryEntryRef::imported_symbol_end() const { + uintptr_t IntPtr = 0; + OwningObject->getRvaPtr(ImportTable[Index].ImportLookupTableRVA, IntPtr); + // Forward the pointer to the last entry which is null. + int Index = 0; + if (OwningObject->getBytesInAddress() == 4) { + auto *Entry = reinterpret_cast(IntPtr); + while (*Entry++) + ++Index; + } else { + auto *Entry = reinterpret_cast(IntPtr); + while (*Entry++) + ++Index; + } + return makeImportedSymbolIterator(OwningObject, IntPtr, Index); +} + std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { uintptr_t IntPtr = 0; if (std::error_code EC = @@ -1139,6 +1176,59 @@ ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { return object_error::success; } +bool ImportedSymbolRef:: +operator==(const ImportedSymbolRef &Other) const { + return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 + && Index == Other.Index; +} + +void ImportedSymbolRef::moveNext() { + ++Index; +} + +std::error_code +ImportedSymbolRef::getSymbolName(StringRef &Result) const { + uint32_t RVA; + if (Entry32) { + // If a symbol is imported only by ordinal, it has no name. + if (Entry32[Index].isOrdinal()) + return object_error::success; + RVA = Entry32[Index].getHintNameRVA(); + } else { + if (Entry64[Index].isOrdinal()) + return object_error::success; + RVA = Entry64[Index].getHintNameRVA(); + } + uintptr_t IntPtr = 0; + if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) + return EC; + // +2 because the first two bytes is hint. + Result = StringRef(reinterpret_cast(IntPtr + 2)); + return object_error::success; +} + +std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { + uint32_t RVA; + if (Entry32) { + if (Entry32[Index].isOrdinal()) { + Result = Entry32[Index].getOrdinal(); + return object_error::success; + } + RVA = Entry32[Index].getHintNameRVA(); + } else { + if (Entry64[Index].isOrdinal()) { + Result = Entry64[Index].getOrdinal(); + return object_error::success; + } + RVA = Entry64[Index].getHintNameRVA(); + } + uintptr_t IntPtr = 0; + if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) + return EC; + Result = *reinterpret_cast(IntPtr); + return object_error::success; +} + ErrorOr> ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { std::error_code EC; diff --git a/test/tools/llvm-readobj/imports.test b/test/tools/llvm-readobj/imports.test index 62f0d1457c4..ed2edfab9e9 100644 --- a/test/tools/llvm-readobj/imports.test +++ b/test/tools/llvm-readobj/imports.test @@ -5,20 +5,24 @@ X86: Import { X86-NEXT: Name: KERNEL32.dll X86-NEXT: ImportLookupTableRVA: 0x204C X86-NEXT: ImportAddressTableRVA: 0x2000 +X86-NEXT: Symbol: ExitProcess (337) X86-NEXT: } X86-NEXT: Import { X86-NEXT: Name: USER32.dll X86-NEXT: ImportLookupTableRVA: 0x2054 X86-NEXT: ImportAddressTableRVA: 0x2008 +X86-NEXT: Symbol: MessageBoxA (582) X86-NEXT: } X64: Import { X64-NEXT: Name: KERNEL32.dll X64-NEXT: ImportLookupTableRVA: 0x2060 X64-NEXT: ImportAddressTableRVA: 0x2000 +X64-NEXT: Symbol: ExitProcess (343) X64-NEXT: } X64-NEXT: Import { X64-NEXT: Name: USER32.dll X64-NEXT: ImportLookupTableRVA: 0x2070 X64-NEXT: ImportAddressTableRVA: 0x2010 +X64-NEXT: Symbol: MessageBoxA (586) X64-NEXT: } diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index a3692af41fe..3653afaec66 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -895,5 +895,13 @@ void COFFDumper::printCOFFImports() { W.printHex("ImportLookupTableRVA", Addr); if (error(I->getImportAddressTableRVA(Addr))) return; W.printHex("ImportAddressTableRVA", Addr); + for (auto J = I->imported_symbol_begin(), F = I->imported_symbol_end(); + J != F; ++J) { + StringRef Sym; + if (error(J->getSymbolName(Sym))) return; + uint16_t Ordinal; + if (error(J->getOrdinal(Ordinal))) return; + W.printNumber("Symbol", Sym, Ordinal); + } } } -- 2.34.1