This patch adds a new flag "-coff-imports" to llvm-readobj.
authorRui Ueyama <ruiu@google.com>
Thu, 2 Oct 2014 17:02:18 +0000 (17:02 +0000)
committerRui Ueyama <ruiu@google.com>
Thu, 2 Oct 2014 17:02:18 +0000 (17:02 +0000)
When the flag is given, the command prints out the COFF import table.

Currently only the import table directory will be printed.
I'm going to make another patch to print out the imported symbols.

The implementation of import directory entry iterator in
COFFObjectFile.cpp was buggy. This patch fixes that too.

http://reviews.llvm.org/D5569

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218891 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/COFF.h
lib/Object/COFFObjectFile.cpp
test/tools/llvm-readobj/Inputs/imports.exe.coff-i386 [new file with mode: 0644]
test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64 [new file with mode: 0644]
test/tools/llvm-readobj/imports.test [new file with mode: 0644]
tools/llvm-readobj/COFFDumper.cpp
tools/llvm-readobj/ObjDumper.h
tools/llvm-readobj/llvm-readobj.cpp

index d7beac307a414a4c466019cb0567973755b95f07..f7a578315c1284c77d406f530727894c76b0dbaf 100644 (file)
@@ -651,6 +651,8 @@ public:
   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 45de4341b3f00f09f79908d3b42324dadaf47ecb..d77238c6add7eda2fe121740f5e1814f727cdfc5 100644 (file)
@@ -491,8 +491,9 @@ std::error_code COFFObjectFile::initImportTablePtr() {
     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,36 @@ void ImportDirectoryEntryRef::moveNext() {
 
 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<const char *>(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))
+  uint32_t RVA = ImportTable[Index].ImportLookupTableRVA;
+  if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
     return EC;
   Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr);
   return object_error::success;
diff --git a/test/tools/llvm-readobj/Inputs/imports.exe.coff-i386 b/test/tools/llvm-readobj/Inputs/imports.exe.coff-i386
new file mode 100644 (file)
index 0000000..a42be04
Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/imports.exe.coff-i386 differ
diff --git a/test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64 b/test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64
new file mode 100644 (file)
index 0000000..e2abfd8
Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64 differ
diff --git a/test/tools/llvm-readobj/imports.test b/test/tools/llvm-readobj/imports.test
new file mode 100644 (file)
index 0000000..62f0d14
--- /dev/null
@@ -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 3d71d832f99b07bdc582d9d5eef8cbd8cc85959e..a3692af41fe44c81dd509731774f177e5ea9b8e0 100644 (file)
@@ -55,6 +55,7 @@ public:
   void printSymbols() override;
   void printDynamicSymbols() override;
   void printUnwindInfo() override;
+  void printCOFFImports() override;
 
 private:
   void printSymbol(const SymbolRef &Sym);
@@ -882,3 +883,17 @@ void COFFDumper::printUnwindInfo() {
   }
 }
 
+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 Addr;
+    if (error(I->getImportLookupTableRVA(Addr))) return;
+    W.printHex("ImportLookupTableRVA", Addr);
+    if (error(I->getImportAddressTableRVA(Addr))) return;
+    W.printHex("ImportAddressTableRVA", Addr);
+  }
+}
index 7adf76a694666e40b0f86b4df651a0c130f1c594..8f0c171233e5f135ecb6e9df0e6ef0264ee9d614 100644 (file)
@@ -43,6 +43,9 @@ public:
   // Only implemented for MIPS ELF at this time.
   virtual void printMipsPLTGOT() { }
 
+  // Only implemented for PE/COFF.
+  virtual void printCOFFImports() { }
+
 protected:
   StreamWriter& W;
 };
index a20164a3c23ff4a5a7dd8600e73bac89b8198337..31a011d2b9ef5d7d844d0504c4ea095751f9b881 100644 (file)
@@ -141,6 +141,10 @@ namespace opts {
   cl::opt<bool>
   MipsPLTGOT("mips-plt-got",
              cl::desc("Display the MIPS GOT and PLT GOT sections"));
+
+  // -coff-imports
+  cl::opt<bool>
+  COFFImports("coff-imports", cl::desc("Display the PE/COFF import table"));
 } // namespace opts
 
 static int ReturnValue = EXIT_SUCCESS;
@@ -266,6 +270,8 @@ static void dumpObject(const ObjectFile *Obj) {
   if (isMipsArch(Obj->getArch()) && Obj->isELF())
     if (opts::MipsPLTGOT)
       Dumper->printMipsPLTGOT();
+  if (opts::COFFImports)
+    Dumper->printCOFFImports();
 }