[llvm] r218933 - llvm-readobj: print COFF delay-load import table
Rui Ueyama
ruiu at google.com
Thu Oct 2 17:41:58 PDT 2014
Author: ruiu
Date: Thu Oct 2 19:41:58 2014
New Revision: 218933
URL: http://llvm.org/viewvc/llvm-project?rev=218933&view=rev
Log:
llvm-readobj: print COFF delay-load import table
This patch adds another iterator to access the delay-load import table
and use it from llvm-readobj.
http://reviews.llvm.org/D5594
Modified:
llvm/trunk/include/llvm/Object/COFF.h
llvm/trunk/lib/Object/COFFObjectFile.cpp
llvm/trunk/test/tools/llvm-readobj/Inputs/imports.exe.coff-i386
llvm/trunk/test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64
llvm/trunk/test/tools/llvm-readobj/imports.test
llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
Modified: llvm/trunk/include/llvm/Object/COFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=218933&r1=218932&r2=218933&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/COFF.h (original)
+++ llvm/trunk/include/llvm/Object/COFF.h Thu Oct 2 19:41:58 2014
@@ -25,9 +25,12 @@ template <typename T> class ArrayRef;
namespace object {
class ImportDirectoryEntryRef;
+class DelayImportDirectoryEntryRef;
class ExportDirectoryEntryRef;
class ImportedSymbolRef;
typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
+typedef content_iterator<DelayImportDirectoryEntryRef>
+ delay_import_directory_iterator;
typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator;
typedef content_iterator<ImportedSymbolRef> imported_symbol_iterator;
@@ -184,6 +187,18 @@ typedef import_lookup_table_entry<suppor
typedef import_lookup_table_entry<support::little64_t>
import_lookup_table_entry64;
+struct delay_import_directory_table_entry {
+ // dumpbin reports this field as "Characteristics" instead of "Attributes".
+ support::ulittle32_t Attributes;
+ support::ulittle32_t Name;
+ support::ulittle32_t ModuleHandle;
+ support::ulittle32_t DelayImportAddressTable;
+ support::ulittle32_t DelayImportNameTable;
+ support::ulittle32_t BoundDelayImportTable;
+ support::ulittle32_t UnloadDelayImportTable;
+ support::ulittle32_t TimeStamp;
+};
+
struct export_directory_table_entry {
support::ulittle32_t ExportFlags;
support::ulittle32_t TimeDateStamp;
@@ -440,6 +455,8 @@ private:
uint32_t StringTableSize;
const import_directory_table_entry *ImportDirectory;
uint32_t NumberOfImportDirectory;
+ const delay_import_directory_table_entry *DelayImportDirectory;
+ uint32_t NumberOfDelayImportDirectory;
const export_directory_table_entry *ExportDirectory;
std::error_code getString(uint32_t offset, StringRef &Res) const;
@@ -451,6 +468,7 @@ private:
std::error_code initSymbolTablePtr();
std::error_code initImportTablePtr();
+ std::error_code initDelayImportTablePtr();
std::error_code initExportTablePtr();
public:
@@ -582,6 +600,8 @@ public:
import_directory_iterator import_directory_begin() const;
import_directory_iterator import_directory_end() const;
+ delay_import_directory_iterator delay_import_directory_begin() const;
+ delay_import_directory_iterator delay_import_directory_end() const;
export_directory_iterator export_directory_begin() const;
export_directory_iterator export_directory_end() const;
@@ -677,6 +697,27 @@ private:
uint32_t Index;
const COFFObjectFile *OwningObject;
};
+
+class DelayImportDirectoryEntryRef {
+public:
+ DelayImportDirectoryEntryRef() : OwningObject(nullptr) {}
+ DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
+ uint32_t I, const COFFObjectFile *Owner)
+ : Table(T), Index(I), OwningObject(Owner) {}
+
+ bool operator==(const DelayImportDirectoryEntryRef &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;
+
+private:
+ const delay_import_directory_table_entry *Table;
+ uint32_t Index;
+ const COFFObjectFile *OwningObject;
+};
// The iterator for the export directory table entry.
class ExportDirectoryEntryRef {
Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=218933&r1=218932&r2=218933&view=diff
==============================================================================
--- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/COFFObjectFile.cpp Thu Oct 2 19:41:58 2014
@@ -506,6 +506,26 @@ std::error_code COFFObjectFile::initImpo
return object_error::success;
}
+// Initializes DelayImportDirectory and NumberOfDelayImportDirectory.
+std::error_code COFFObjectFile::initDelayImportTablePtr() {
+ const data_directory *DataEntry;
+ if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry))
+ return object_error::success;
+ if (DataEntry->RelativeVirtualAddress == 0)
+ return object_error::success;
+
+ uint32_t RVA = DataEntry->RelativeVirtualAddress;
+ NumberOfDelayImportDirectory = DataEntry->Size /
+ sizeof(delay_import_directory_table_entry) - 1;
+
+ uintptr_t IntPtr = 0;
+ if (std::error_code EC = getRvaPtr(RVA, IntPtr))
+ return EC;
+ DelayImportDirectory = reinterpret_cast<
+ const delay_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
@@ -533,6 +553,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuf
DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
ImportDirectory(nullptr), NumberOfImportDirectory(0),
+ DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
ExportDirectory(nullptr) {
// Check that we at least have enough room for a header.
if (!checkSize(Data, EC, sizeof(coff_file_header)))
@@ -631,6 +652,8 @@ COFFObjectFile::COFFObjectFile(MemoryBuf
// Initialize the pointer to the beginning of the import table.
if ((EC = initImportTablePtr()))
return;
+ if ((EC = initDelayImportTablePtr()))
+ return;
// Initialize the pointer to the export table.
if ((EC = initExportTablePtr()))
@@ -662,6 +685,19 @@ import_directory_iterator COFFObjectFile
ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this));
}
+delay_import_directory_iterator
+COFFObjectFile::delay_import_directory_begin() const {
+ return delay_import_directory_iterator(
+ DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this));
+}
+
+delay_import_directory_iterator
+COFFObjectFile::delay_import_directory_end() const {
+ return delay_import_directory_iterator(
+ DelayImportDirectoryEntryRef(
+ DelayImportDirectory, NumberOfDelayImportDirectory, this));
+}
+
export_directory_iterator COFFObjectFile::export_directory_begin() const {
return export_directory_iterator(
ExportDirectoryEntryRef(ExportDirectory, 0, this));
@@ -1036,30 +1072,30 @@ std::error_code ImportDirectoryEntryRef:
}
static imported_symbol_iterator
-makeImportedSymbolIterator(const COFFObjectFile *OwningObject,
+makeImportedSymbolIterator(const COFFObjectFile *Object,
uintptr_t Ptr, int Index) {
- if (OwningObject->getBytesInAddress() == 4) {
+ if (Object->getBytesInAddress() == 4) {
auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
- return imported_symbol_iterator(ImportedSymbolRef(P, Index, OwningObject));
+ return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
}
auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
- return imported_symbol_iterator(ImportedSymbolRef(P, Index, OwningObject));
+ return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object));
}
-imported_symbol_iterator
-ImportDirectoryEntryRef::imported_symbol_begin() const {
+static imported_symbol_iterator
+importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) {
uintptr_t IntPtr = 0;
- OwningObject->getRvaPtr(ImportTable[Index].ImportLookupTableRVA, IntPtr);
- return makeImportedSymbolIterator(OwningObject, IntPtr, 0);
+ Object->getRvaPtr(RVA, IntPtr);
+ return makeImportedSymbolIterator(Object, IntPtr, 0);
}
-imported_symbol_iterator
-ImportDirectoryEntryRef::imported_symbol_end() const {
+static imported_symbol_iterator
+importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) {
uintptr_t IntPtr = 0;
- OwningObject->getRvaPtr(ImportTable[Index].ImportLookupTableRVA, IntPtr);
+ Object->getRvaPtr(RVA, IntPtr);
// Forward the pointer to the last entry which is null.
int Index = 0;
- if (OwningObject->getBytesInAddress() == 4) {
+ if (Object->getBytesInAddress() == 4) {
auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
while (*Entry++)
++Index;
@@ -1068,7 +1104,19 @@ ImportDirectoryEntryRef::imported_symbol
while (*Entry++)
++Index;
}
- return makeImportedSymbolIterator(OwningObject, IntPtr, Index);
+ return makeImportedSymbolIterator(Object, IntPtr, Index);
+}
+
+imported_symbol_iterator
+ImportDirectoryEntryRef::imported_symbol_begin() const {
+ return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA,
+ OwningObject);
+}
+
+imported_symbol_iterator
+ImportDirectoryEntryRef::imported_symbol_end() const {
+ return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA,
+ OwningObject);
}
std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
@@ -1102,6 +1150,35 @@ std::error_code ImportDirectoryEntryRef:
return object_error::success;
}
+bool DelayImportDirectoryEntryRef::
+operator==(const DelayImportDirectoryEntryRef &Other) const {
+ return Table == Other.Table && Index == Other.Index;
+}
+
+void DelayImportDirectoryEntryRef::moveNext() {
+ ++Index;
+}
+
+imported_symbol_iterator
+DelayImportDirectoryEntryRef::imported_symbol_begin() const {
+ return importedSymbolBegin(Table[Index].DelayImportNameTable,
+ OwningObject);
+}
+
+imported_symbol_iterator
+DelayImportDirectoryEntryRef::imported_symbol_end() const {
+ return importedSymbolEnd(Table[Index].DelayImportNameTable,
+ OwningObject);
+}
+
+std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const {
+ uintptr_t IntPtr = 0;
+ if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr))
+ return EC;
+ Result = StringRef(reinterpret_cast<const char *>(IntPtr));
+ return object_error::success;
+}
+
bool ExportDirectoryEntryRef::
operator==(const ExportDirectoryEntryRef &Other) const {
return ExportTable == Other.ExportTable && Index == Other.Index;
Modified: llvm/trunk/test/tools/llvm-readobj/Inputs/imports.exe.coff-i386
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/imports.exe.coff-i386?rev=218933&r1=218932&r2=218933&view=diff
==============================================================================
Binary files - no diff available.
Modified: llvm/trunk/test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64?rev=218933&r1=218932&r2=218933&view=diff
==============================================================================
Binary files - no diff available.
Modified: llvm/trunk/test/tools/llvm-readobj/imports.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/imports.test?rev=218933&r1=218932&r2=218933&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/imports.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/imports.test Thu Oct 2 19:41:58 2014
@@ -3,42 +3,62 @@ RUN: llvm-readobj --coff-imports %p/Inpu
X86: Import {
X86-NEXT: Name: KERNEL32.dll
-X86-NEXT: ImportLookupTableRVA: 0x2070
+X86-NEXT: ImportLookupTableRVA: 0x2108
X86-NEXT: ImportAddressTableRVA: 0x2000
X86-NEXT: Symbol: ExitProcess (337)
+X86-NEXT: Symbol: GetProcAddress (669)
+X86-NEXT: Symbol: FreeLibrary (414)
+X86-NEXT: Symbol: GetLastError (592)
+X86-NEXT: Symbol: RaiseException (1087)
+X86-NEXT: Symbol: LoadLibraryExA (934)
X86-NEXT: }
X86-NEXT: Import {
X86-NEXT: Name: USER32.dll
-X86-NEXT: ImportLookupTableRVA: 0x2078
-X86-NEXT: ImportAddressTableRVA: 0x2008
+X86-NEXT: ImportLookupTableRVA: 0x2124
+X86-NEXT: ImportAddressTableRVA: 0x201C
X86-NEXT: Symbol: MessageBoxA (582)
X86-NEXT: }
X86-NEXT: Import {
X86-NEXT: Name: mydll.dll
-X86-NEXT: ImportLookupTableRVA: 0x2080
-X86-NEXT: ImportAddressTableRVA: 0x2010
+X86-NEXT: ImportLookupTableRVA: 0x212C
+X86-NEXT: ImportAddressTableRVA: 0x2024
+X86-NEXT: Symbol: Func1 (0)
X86-NEXT: Symbol: Func2 (1)
X86-NEXT: Symbol: (3)
-X86-NEXT: Symbol: Func1 (0)
+X86-NEXT: }
+X86-NEXT: DelayImport {
+X86-NEXT: Name: lazyload.dll
+X86-NEXT: Symbol: Func5 (0)
+X86-NEXT: Symbol: Func4 (0)
X86-NEXT: }
X64: Import {
X64-NEXT: Name: KERNEL32.dll
-X64-NEXT: ImportLookupTableRVA: 0x2090
+X64-NEXT: ImportLookupTableRVA: 0x2170
X64-NEXT: ImportAddressTableRVA: 0x2000
X64-NEXT: Symbol: ExitProcess (343)
+X64-NEXT: Symbol: GetProcAddress (676)
+X64-NEXT: Symbol: FreeLibrary (420)
+X64-NEXT: Symbol: GetLastError (598)
+X64-NEXT: Symbol: RaiseException (1091)
+X64-NEXT: Symbol: LoadLibraryExA (937)
X64-NEXT: }
X64-NEXT: Import {
X64-NEXT: Name: USER32.dll
-X64-NEXT: ImportLookupTableRVA: 0x20A0
-X64-NEXT: ImportAddressTableRVA: 0x2010
+X64-NEXT: ImportLookupTableRVA: 0x21A8
+X64-NEXT: ImportAddressTableRVA: 0x2038
X64-NEXT: Symbol: MessageBoxA (586)
X64-NEXT: }
X64-NEXT: Import {
X64-NEXT: Name: mydll.dll
-X64-NEXT: ImportLookupTableRVA: 0x20B0
-X64-NEXT: ImportAddressTableRVA: 0x2020
+X64-NEXT: ImportLookupTableRVA: 0x21B8
+X64-NEXT: ImportAddressTableRVA: 0x2048
+X64-NEXT: Symbol: Func1 (0)
X64-NEXT: Symbol: Func2 (1)
X64-NEXT: Symbol: (3)
-X64-NEXT: Symbol: Func1 (0)
+X64-NEXT: }
+X64-NEXT: DelayImport {
+X64-NEXT: Name: lazyload.dll
+X64-NEXT: Symbol: Func5 (0)
+X64-NEXT: Symbol: Func4 (0)
X64-NEXT: }
Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=218933&r1=218932&r2=218933&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Thu Oct 2 19:41:58 2014
@@ -75,6 +75,9 @@ private:
std::error_code resolveSymbolName(const coff_section *Section,
uint64_t Offset, StringRef &Name);
+ void printImportedSymbols(imported_symbol_iterator I,
+ imported_symbol_iterator E);
+
typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
const llvm::object::COFFObjectFile *Obj;
@@ -883,7 +886,19 @@ void COFFDumper::printUnwindInfo() {
}
}
+void COFFDumper::printImportedSymbols(imported_symbol_iterator I,
+ imported_symbol_iterator E) {
+ for (; I != E; ++I) {
+ StringRef Sym;
+ if (error(I->getSymbolName(Sym))) return;
+ uint16_t Ordinal;
+ if (error(I->getOrdinal(Ordinal))) return;
+ W.printNumber("Symbol", Sym, Ordinal);
+ }
+}
+
void COFFDumper::printCOFFImports() {
+ // Regular imports
for (auto I = Obj->import_directory_begin(), E = Obj->import_directory_end();
I != E; ++I) {
DictScope Import(W, "Import");
@@ -895,13 +910,17 @@ 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);
- }
+ printImportedSymbols(I->imported_symbol_begin(), I->imported_symbol_end());
+ }
+
+ // Delay imports
+ for (auto I = Obj->delay_import_directory_begin(),
+ E = Obj->delay_import_directory_end();
+ I != E; ++I) {
+ DictScope Import(W, "DelayImport");
+ StringRef Name;
+ if (error(I->getName(Name))) return;
+ W.printString("Name", Name);
+ printImportedSymbols(I->imported_symbol_begin(), I->imported_symbol_end());
}
}
More information about the llvm-commits
mailing list