[llvm] r222289 - llvm-readobj: teach it how to dump COFF base relocation table

Rui Ueyama ruiu at google.com
Tue Nov 18 16:18:08 PST 2014


Author: ruiu
Date: Tue Nov 18 18:18:07 2014
New Revision: 222289

URL: http://llvm.org/viewvc/llvm-project?rev=222289&view=rev
Log:
llvm-readobj: teach it how to dump COFF base relocation table

Added:
    llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386   (with props)
    llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test
Modified:
    llvm/trunk/include/llvm/Object/COFF.h
    llvm/trunk/lib/Object/COFFObjectFile.cpp
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
    llvm/trunk/tools/llvm-readobj/ObjDumper.h
    llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp

Modified: llvm/trunk/include/llvm/Object/COFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/COFF.h (original)
+++ llvm/trunk/include/llvm/Object/COFF.h Tue Nov 18 18:18:07 2014
@@ -28,11 +28,13 @@ class ImportDirectoryEntryRef;
 class DelayImportDirectoryEntryRef;
 class ExportDirectoryEntryRef;
 class ImportedSymbolRef;
+class BaseRelocRef;
 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;
+typedef content_iterator<BaseRelocRef> base_reloc_iterator;
 
 /// The DOS compatible header at the front of all PE/COFF executables.
 struct dos_header {
@@ -459,6 +461,17 @@ struct coff_runtime_function_x64 {
   support::ulittle32_t UnwindInformation;
 };
 
+struct coff_base_reloc_block_header {
+  support::ulittle32_t PageRVA;
+  support::ulittle32_t BlockSize;
+};
+
+struct coff_base_reloc_block_entry {
+  support::ulittle16_t Data;
+  int getType() const { return Data >> 12; }
+  int getOffset() const { return Data & ((1 << 12) - 1); }
+};
+
 class COFFObjectFile : public ObjectFile {
 private:
   friend class ImportDirectoryEntryRef;
@@ -478,6 +491,8 @@ private:
   const delay_import_directory_table_entry *DelayImportDirectory;
   uint32_t NumberOfDelayImportDirectory;
   const export_directory_table_entry *ExportDirectory;
+  const coff_base_reloc_block_header *BaseRelocHeader;
+  const coff_base_reloc_block_header *BaseRelocEnd;
 
   std::error_code getString(uint32_t offset, StringRef &Res) const;
 
@@ -490,6 +505,7 @@ private:
   std::error_code initImportTablePtr();
   std::error_code initDelayImportTablePtr();
   std::error_code initExportTablePtr();
+  std::error_code initBaseRelocPtr();
 
 public:
   uintptr_t getSymbolTable() const {
@@ -621,11 +637,14 @@ public:
   delay_import_directory_iterator delay_import_directory_end() const;
   export_directory_iterator export_directory_begin() const;
   export_directory_iterator export_directory_end() const;
+  base_reloc_iterator base_reloc_begin() const;
+  base_reloc_iterator base_reloc_end() const;
 
   iterator_range<import_directory_iterator> import_directories() const;
   iterator_range<delay_import_directory_iterator>
       delay_import_directories() const;
   iterator_range<export_directory_iterator> export_directories() const;
+  iterator_range<base_reloc_iterator> base_relocs() const;
 
   const dos_header *getDOSHeader() const {
     if (!PE32Header && !PE32PlusHeader)
@@ -798,6 +817,26 @@ private:
   uint32_t Index;
   const COFFObjectFile *OwningObject;
 };
+
+class BaseRelocRef {
+public:
+  BaseRelocRef() : OwningObject(nullptr) {}
+  BaseRelocRef(const coff_base_reloc_block_header *Header,
+               const COFFObjectFile *Owner)
+      : Header(Header), Index(0), OwningObject(Owner) {}
+
+  bool operator==(const BaseRelocRef &Other) const;
+  void moveNext();
+
+  std::error_code getType(uint8_t &Type) const;
+  std::error_code getRVA(uint32_t &Result) const;
+
+private:
+  const coff_base_reloc_block_header *Header;
+  uint32_t Index;
+  const COFFObjectFile *OwningObject;
+};
+
 } // end namespace object
 } // end namespace llvm
 

Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/COFFObjectFile.cpp Tue Nov 18 18:18:07 2014
@@ -598,6 +598,23 @@ std::error_code COFFObjectFile::initExpo
   return object_error::success;
 }
 
+std::error_code COFFObjectFile::initBaseRelocPtr() {
+  const data_directory *DataEntry;
+  if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
+    return object_error::success;
+  if (DataEntry->RelativeVirtualAddress == 0)
+    return object_error::success;
+
+  uintptr_t IntPtr = 0;
+  if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
+    return EC;
+  BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
+      IntPtr);
+  BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
+      IntPtr + DataEntry->Size);
+  return object_error::success;
+}
+
 COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
     : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
       COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
@@ -605,7 +622,8 @@ COFFObjectFile::COFFObjectFile(MemoryBuf
       SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
       ImportDirectory(nullptr), NumberOfImportDirectory(0),
       DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
-      ExportDirectory(nullptr) {
+      ExportDirectory(nullptr), BaseRelocHeader(nullptr),
+      BaseRelocEnd(nullptr) {
   // Check that we at least have enough room for a header.
   if (!checkSize(Data, EC, sizeof(coff_file_header)))
     return;
@@ -717,6 +735,10 @@ COFFObjectFile::COFFObjectFile(MemoryBuf
   if ((EC = initExportTablePtr()))
     return;
 
+  // Initialize the pointer to the base relocation table.
+  if ((EC = initBaseRelocPtr()))
+    return;
+
   EC = object_error::success;
 }
 
@@ -783,6 +805,14 @@ section_iterator COFFObjectFile::section
   return section_iterator(SectionRef(Ret, this));
 }
 
+base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
+  return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
+}
+
+base_reloc_iterator COFFObjectFile::base_reloc_end() const {
+  return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
+}
+
 uint8_t COFFObjectFile::getBytesInAddress() const {
   return getArch() == Triple::x86_64 ? 8 : 4;
 }
@@ -829,6 +859,10 @@ COFFObjectFile::export_directories() con
   return make_range(export_directory_begin(), export_directory_end());
 }
 
+iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
+  return make_range(base_reloc_begin(), base_reloc_end());
+}
+
 std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
   Res = PE32Header;
   return object_error::success;
@@ -1448,3 +1482,37 @@ ObjectFile::createCOFFObjectFile(MemoryB
     return EC;
   return std::move(Ret);
 }
+
+bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
+  return Header == Other.Header && Index == Other.Index;
+}
+
+void BaseRelocRef::moveNext() {
+  // Header->BlockSize is the size of the current block, including the
+  // size of the header itself.
+  uint32_t Size = sizeof(*Header) +
+      sizeof(coff_base_reloc_block_entry) * Index;
+  if (Size == Header->BlockSize) {
+    // .reloc contains a list of base relocation blocks. Each block
+    // consists of the header followed by entries. The header contains
+    // how many entories will follow. When we reach the end of the
+    // current block, proceed to the next block.
+    Header = reinterpret_cast<const coff_base_reloc_block_header *>(
+        reinterpret_cast<const uint8_t *>(Header) + Size);
+    Index = 0;
+  } else {
+    ++Index;
+  }
+}
+
+std::error_code BaseRelocRef::getType(uint8_t &Type) const {
+  auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
+  Type = Entry[Index].getType();
+  return object_error::success;
+}
+
+std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
+  auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
+  Result = Header->PageRVA + Entry[Index].getOffset();
+  return object_error::success;
+}

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386?rev=222289&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test?rev=222289&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test Tue Nov 18 18:18:07 2014
@@ -0,0 +1,20 @@
+RUN: llvm-readobj -coff-basereloc %p/Inputs/basereloc.obj.coff-i386 | FileCheck %s
+
+CHECK: Format: COFF-i386
+CHECK: Arch: i386
+CHECK: AddressSize: 32bit
+CHECK: BaseReloc [
+CHECK:   Entry {
+CHECK:     Type: HIGHLOW
+CHECK:     Address: 0x1004
+CHECK:   }
+CHECK:   Entry {
+CHECK:     Type: HIGHLOW
+CHECK:     Address: 0x100A
+CHECK:   }
+CHECK:   Entry {
+CHECK:     Type: HIGHLOW
+CHECK:     Address: 0x1010
+CHECK:   }
+CHECK: ]
+

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Tue Nov 18 18:18:07 2014
@@ -57,6 +57,7 @@ public:
   void printUnwindInfo() override;
   void printCOFFImports() override;
   void printCOFFDirectives() override;
+  void printCOFFBaseReloc() override;
 
 private:
   void printSymbol(const SymbolRef &Sym);
@@ -1076,3 +1077,33 @@ void COFFDumper::printCOFFDirectives() {
     W.printString("Directive(s)", Contents);
   }
 }
+
+static StringRef getBaseRelocTypeName(uint8_t Type) {
+  switch (Type) {
+  case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE";
+  case COFF::IMAGE_REL_BASED_HIGH: return "HIGH";
+  case COFF::IMAGE_REL_BASED_LOW: return "LOW";
+  case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW";
+  case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";
+  case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";
+  default: return "unknown";
+  }
+}
+
+void COFFDumper::printCOFFBaseReloc() {
+  ListScope D(W, "BaseReloc");
+  for (const BaseRelocRef &I : Obj->base_relocs()) {
+    uint8_t Type;
+    uint32_t RVA;
+    if (error(I.getRVA(RVA)))
+      continue;
+    if (error(I.getType(Type)))
+      continue;
+    // IMAGE_REL_BASED_ABSOLUTE is a NOP entry.
+    if (Type == COFF::IMAGE_REL_BASED_ABSOLUTE)
+      continue;
+    DictScope Import(W, "Entry");
+    W.printString("Type", getBaseRelocTypeName(Type));
+    W.printHex("Address", RVA);
+  }
+}

Modified: llvm/trunk/tools/llvm-readobj/ObjDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ObjDumper.h?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ObjDumper.h (original)
+++ llvm/trunk/tools/llvm-readobj/ObjDumper.h Tue Nov 18 18:18:07 2014
@@ -46,6 +46,7 @@ public:
   // Only implemented for PE/COFF.
   virtual void printCOFFImports() { }
   virtual void printCOFFDirectives() { }
+  virtual void printCOFFBaseReloc() { }
 
 protected:
   StreamWriter& W;

Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Tue Nov 18 18:18:07 2014
@@ -149,7 +149,12 @@ namespace opts {
   // -coff-directives
   cl::opt<bool>
   COFFDirectives("coff-directives",
-                 cl::desc("Display the contents PE/COFF .drectve section"));
+                 cl::desc("Display the PE/COFF .drectve section"));
+
+  // -coff-basereloc
+  cl::opt<bool>
+  COFFBaseRelocs("coff-basereloc",
+                 cl::desc("Display the PE/COFF .reloc section"));
 } // namespace opts
 
 static int ReturnValue = EXIT_SUCCESS;
@@ -279,6 +284,8 @@ static void dumpObject(const ObjectFile
     Dumper->printCOFFImports();
   if (opts::COFFDirectives)
     Dumper->printCOFFDirectives();
+  if (opts::COFFBaseRelocs)
+    Dumper->printCOFFBaseReloc();
 }
 
 





More information about the llvm-commits mailing list