Index: include/llvm/Object/COFF.h =================================================================== --- include/llvm/Object/COFF.h +++ include/llvm/Object/COFF.h @@ -651,6 +651,8 @@ bool operator==(const ImportDirectoryEntryRef &Other) const; void moveNext(); std::error_code getName(StringRef &Result) const; + std::error_code getImportLookupTableRVA(uint32_t &Result) const; + std::error_code getImportAddressTableRVA(uint32_t &Result) const; std::error_code getImportTableEntry(const import_directory_table_entry *&Result) const; Index: lib/Object/COFFObjectFile.cpp =================================================================== --- lib/Object/COFFObjectFile.cpp +++ lib/Object/COFFObjectFile.cpp @@ -491,8 +491,9 @@ return object_error::success; uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; + // -1 because the last entry is the null entry. NumberOfImportDirectory = DataEntry->Size / - sizeof(import_directory_table_entry); + sizeof(import_directory_table_entry) - 1; // 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. @@ -1029,24 +1030,34 @@ std::error_code ImportDirectoryEntryRef::getImportTableEntry( const import_directory_table_entry *&Result) const { - Result = ImportTable; + Result = ImportTable + Index; return object_error::success; } std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { uintptr_t IntPtr = 0; if (std::error_code EC = - OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) + OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) return EC; Result = StringRef(reinterpret_cast(IntPtr)); return object_error::success; } +std::error_code ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { + Result = ImportTable[Index].ImportLookupTableRVA; + return object_error::success; +} + +std::error_code ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { + Result = ImportTable[Index].ImportAddressTableRVA; + return object_error::success; +} + std::error_code ImportDirectoryEntryRef::getImportLookupEntry( const import_lookup_table_entry32 *&Result) const { uintptr_t IntPtr = 0; if (std::error_code EC = - OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr)) + OwningObject->getRvaPtr(ImportTable[Index].ImportLookupTableRVA, IntPtr)) return EC; Result = reinterpret_cast(IntPtr); return object_error::success; Index: test/tools/llvm-readobj/imports.test =================================================================== --- test/tools/llvm-readobj/imports.test +++ test/tools/llvm-readobj/imports.test @@ -0,0 +1,24 @@ +RUN: llvm-readobj --coff-imports %p/Inputs/imports.exe.coff-i386 | FileCheck -check-prefix=X86 %s +RUN: llvm-readobj --coff-imports %p/Inputs/imports.exe.coff-x86-64 | FileCheck -check-prefix=X64 %s + +X86: Import { +X86-NEXT: Name: KERNEL32.dll +X86-NEXT: ImportLookupTableRVA: 0x204C +X86-NEXT: ImportAddressTableRVA: 0x2000 +X86-NEXT: } +X86-NEXT: Import { +X86-NEXT: Name: USER32.dll +X86-NEXT: ImportLookupTableRVA: 0x2054 +X86-NEXT: ImportAddressTableRVA: 0x2008 +X86-NEXT: } + +X64: Import { +X64-NEXT: Name: KERNEL32.dll +X64-NEXT: ImportLookupTableRVA: 0x2060 +X64-NEXT: ImportAddressTableRVA: 0x2000 +X64-NEXT: } +X64-NEXT: Import { +X64-NEXT: Name: USER32.dll +X64-NEXT: ImportLookupTableRVA: 0x2070 +X64-NEXT: ImportAddressTableRVA: 0x2010 +X64-NEXT: } Index: tools/llvm-readobj/COFFDumper.cpp =================================================================== --- tools/llvm-readobj/COFFDumper.cpp +++ tools/llvm-readobj/COFFDumper.cpp @@ -55,6 +55,7 @@ void printSymbols() override; void printDynamicSymbols() override; void printUnwindInfo() override; + void printCOFFImports() override; private: void printSymbol(const SymbolRef &Sym); @@ -882,3 +883,17 @@ } } +void COFFDumper::printCOFFImports() { + for (auto I = Obj->import_directory_begin(), E = Obj->import_directory_end(); + I != E; ++I) { + DictScope Import(W, "Import"); + StringRef name; + if (error(I->getName(name))) return; + W.printString("Name", name); + uint32_t addr1, addr2; + if (error(I->getImportLookupTableRVA(addr1))) return; + if (error(I->getImportAddressTableRVA(addr2))) return; + W.printHex("ImportLookupTableRVA", addr1); + W.printHex("ImportAddressTableRVA", addr2); + } +} Index: tools/llvm-readobj/ObjDumper.h =================================================================== --- tools/llvm-readobj/ObjDumper.h +++ tools/llvm-readobj/ObjDumper.h @@ -43,6 +43,9 @@ // Only implemented for MIPS ELF at this time. virtual void printMipsPLTGOT() { } + // Only implemented for PE/COFF. + virtual void printCOFFImports() { } + protected: StreamWriter& W; }; Index: tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- tools/llvm-readobj/llvm-readobj.cpp +++ tools/llvm-readobj/llvm-readobj.cpp @@ -141,6 +141,10 @@ cl::opt MipsPLTGOT("mips-plt-got", cl::desc("Display the MIPS GOT and PLT GOT sections")); + + // -coff-imports + cl::opt + COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); } // namespace opts static int ReturnValue = EXIT_SUCCESS; @@ -266,6 +270,8 @@ if (isMipsArch(Obj->getArch()) && Obj->isELF()) if (opts::MipsPLTGOT) Dumper->printMipsPLTGOT(); + if (opts::COFFImports) + Dumper->printCOFFImports(); }