llvm-readobj: print COFF imported symbols
authorRui Ueyama <ruiu@google.com>
Thu, 2 Oct 2014 22:05:29 +0000 (22:05 +0000)
committerRui Ueyama <ruiu@google.com>
Thu, 2 Oct 2014 22:05:29 +0000 (22:05 +0000)
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
lib/Object/COFFObjectFile.cpp
test/tools/llvm-readobj/imports.test
tools/llvm-readobj/COFFDumper.cpp

index f7a578315c1284c77d406f530727894c76b0dbaf..b59e5de4bd1b014d589cd0cdaf54e4804a02c22f 100644 (file)
@@ -26,8 +26,10 @@ template <typename T> class ArrayRef;
 namespace object {
 class ImportDirectoryEntryRef;
 class ExportDirectoryEntryRef;
+class ImportedSymbolRef;
 typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
 typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator;
+typedef content_iterator<ImportedSymbolRef> 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 <typename IntTy>
+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<support::little32_t>
+    import_lookup_table_entry32;
+typedef import_lookup_table_entry<support::little64_t>
+    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
 
index d77238c6add7eda2fe121740f5e1814f727cdfc5..f533d5e21e64101b2a94bf4b49060b4bbf13b033 100644 (file)
@@ -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<const import_lookup_table_entry32 *>(Ptr);
+    return imported_symbol_iterator(ImportedSymbolRef(P, Index, OwningObject));
+  }
+  auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(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<ulittle32_t *>(IntPtr);
+    while (*Entry++)
+      ++Index;
+  } else {
+    auto *Entry = reinterpret_cast<ulittle64_t *>(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<const char *>(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<const ulittle16_t *>(IntPtr);
+  return object_error::success;
+}
+
 ErrorOr<std::unique_ptr<COFFObjectFile>>
 ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
   std::error_code EC;
index 62f0d1457c46bb6fccb6fecc2859d9bb0b17337d..ed2edfab9e9b62a36a4da4120440297eadc749d2 100644 (file)
@@ -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: }
index a3692af41fe44c81dd509731774f177e5ea9b8e0..3653afaec665fa9e635d0d4e365ffec3a7370543 100644 (file)
@@ -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);
+    }
   }
 }