Retry submitting r186623: COFFDumper: Dump data directory entries.
authorRui Ueyama <ruiu@google.com>
Fri, 19 Jul 2013 23:23:29 +0000 (23:23 +0000)
committerRui Ueyama <ruiu@google.com>
Fri, 19 Jul 2013 23:23:29 +0000 (23:23 +0000)
The original change was rolled back in r186627 because of test
failures on the big endian machine. I believe I fixed the issue
so re-submitting.

llvm-svn: 186734

llvm/include/llvm/Object/COFF.h
llvm/lib/Object/COFFObjectFile.cpp
llvm/test/tools/llvm-readobj/Inputs/trivial.exe.coff-i386
llvm/test/tools/llvm-readobj/file-headers.test
llvm/tools/llvm-readobj/COFFDumper.cpp

index c7c5c7f..2190067 100644 (file)
@@ -198,6 +198,7 @@ class COFFObjectFile : public ObjectFile {
 private:
   const coff_file_header *COFFHeader;
   const pe32_header      *PE32Header;
+  const data_directory   *DataDirectory;
   const coff_section     *SectionTable;
   const coff_symbol      *SymbolTable;
   const char             *StringTable;
@@ -283,6 +284,7 @@ public:
   error_code getHeader(const coff_file_header *&Res) const;
   error_code getCOFFHeader(const coff_file_header *&Res) const;
   error_code getPE32Header(const pe32_header *&Res) const;
+  error_code getDataDirectory(uint32_t index, const data_directory *&Res) const;
   error_code getSection(int32_t index, const coff_section *&Res) const;
   error_code getSymbol(uint32_t index, const coff_symbol *&Res) const;
   template <typename T>
index 49317e9..f3f2532 100644 (file)
@@ -37,18 +37,19 @@ bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
   return true;
 }
 
-// Returns false if any bytes in [addr, addr + size) fall outsize of m.
-bool checkAddr(const MemoryBuffer *m,
-               error_code &ec,
-               uintptr_t addr,
-               uint64_t size) {
-  if (addr + size < addr ||
-      addr + size < size ||
-      addr + size > uintptr_t(m->getBufferEnd())) {
-    ec = object_error::unexpected_eof;
-    return false;
+// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
+// Returns unexpected_eof if error.
+template<typename T>
+error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr,
+                     const size_t Size = sizeof(T)) {
+  uintptr_t Addr = uintptr_t(Ptr);
+  if (Addr + Size < Addr ||
+      Addr + Size < Size ||
+      Addr + Size > uintptr_t(M->getBufferEnd())) {
+    return object_error::unexpected_eof;
   }
-  return true;
+  Obj = reinterpret_cast<const T *>(Addr);
+  return object_error::success;
 }
 }
 
@@ -432,6 +433,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
   : ObjectFile(Binary::ID_COFF, Object)
   , COFFHeader(0)
   , PE32Header(0)
+  , DataDirectory(0)
   , SectionTable(0)
   , SymbolTable(0)
   , StringTable(0)
@@ -461,48 +463,49 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
     hasPEHeader = true;
   }
 
-  COFFHeader = reinterpret_cast<const coff_file_header *>(base() + CurPtr);
-  if (!checkAddr(Data, ec, uintptr_t(COFFHeader), sizeof(coff_file_header)))
+  if ((ec = getObject(COFFHeader, Data, base() + CurPtr)))
     return;
   CurPtr += sizeof(coff_file_header);
 
   if (hasPEHeader) {
-    PE32Header = reinterpret_cast<const pe32_header *>(base() + CurPtr);
-    if (!checkAddr(Data, ec, uintptr_t(PE32Header), sizeof(pe32_header)))
+    if ((ec = getObject(PE32Header, Data, base() + CurPtr)))
       return;
-    // We only support PE32. If this is PE32 (not PE32+), the magic byte
-    // should be 0x10b. If this is not PE32, continue as if there's no PE
-    // header in this file.
-    if (PE32Header->Magic != 0x10b)
+    if (PE32Header->Magic != 0x10b) {
+      // We only support PE32. If this is PE32 (not PE32+), the magic byte
+      // should be 0x10b. If this is not PE32, continue as if there's no PE
+      // header in this file.
       PE32Header = 0;
-    // There may be optional data directory after PE header. Skip them.
+    } else if (PE32Header->NumberOfRvaAndSize > 0) {
+      const uint8_t *addr = base() + CurPtr + sizeof(pe32_header);
+      uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
+      if ((ec = getObject(DataDirectory, Data, addr, size)))
+        return;
+    }
     CurPtr += COFFHeader->SizeOfOptionalHeader;
   }
 
-  SectionTable =
-    reinterpret_cast<const coff_section *>(base() + CurPtr);
-  if (!checkAddr(Data, ec, uintptr_t(SectionTable),
-                 COFFHeader->NumberOfSections * sizeof(coff_section)))
+  if ((ec = getObject(SectionTable, Data, base() + CurPtr,
+                      COFFHeader->NumberOfSections * sizeof(coff_section))))
     return;
 
   if (COFFHeader->PointerToSymbolTable != 0) {
-    SymbolTable =
-      reinterpret_cast<const coff_symbol *>(base()
-                                            + COFFHeader->PointerToSymbolTable);
-    if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
-                   COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
+    if ((ec = getObject(SymbolTable, Data,
+                        base() + COFFHeader->PointerToSymbolTable,
+                        COFFHeader->NumberOfSymbols * sizeof(coff_symbol))))
       return;
 
-    // Find string table.
-    StringTable = reinterpret_cast<const char *>(base())
-                  + COFFHeader->PointerToSymbolTable
-                  + COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
-    if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
+    // Find string table. The first four byte of the string table contains the
+    // total size of the string table, including the size field itself. If the
+    // string table is empty, the value of the first four byte would be 4.
+    const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable
+        + COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
+    const ulittle32_t *StringTableSizePtr;
+    if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr)))
       return;
-
-    StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable);
-    if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize))
+    StringTableSize = *StringTableSizePtr;
+    if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize)))
       return;
+
     // Check that the string table is null terminated if has any in it.
     if (StringTableSize < 4
         || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
@@ -607,6 +610,15 @@ error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
   return object_error::success;
 }
 
+error_code COFFObjectFile::getDataDirectory(uint32_t index,
+                                            const data_directory *&Res) const {
+  // Error if if there's no data directory or the index is out of range.
+  if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize)
+    return object_error::parse_failed;
+  Res = &DataDirectory[index];
+  return object_error::success;
+}
+
 error_code COFFObjectFile::getSection(int32_t index,
                                       const coff_section *&Result) const {
   // Check for special index values.
index 3009f90..1558d24 100644 (file)
Binary files a/llvm/test/tools/llvm-readobj/Inputs/trivial.exe.coff-i386 and b/llvm/test/tools/llvm-readobj/Inputs/trivial.exe.coff-i386 differ
index 1082dcc..b900e36 100644 (file)
@@ -107,8 +107,8 @@ PE32-NEXT: Arch: i386
 PE32-NEXT: AddressSize: 32bit
 PE32-NEXT: ImageFileHeader {
 PE32-NEXT:   Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
-PE32-NEXT:   SectionCount: 1
-PE32-NEXT:   TimeDateStamp: 2013-05-24 21:24:34 (0x519FDA92)
+PE32-NEXT:   SectionCount: 3
+PE32-NEXT:   TimeDateStamp: 2013-07-16 00:39:15 (0x51E49633)
 PE32-NEXT:   PointerToSymbolTable: 0x0
 PE32-NEXT:   SymbolCount: 0
 PE32-NEXT:   OptionalHeaderSize: 224
@@ -118,10 +118,10 @@ PE32-NEXT:     IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
 PE32-NEXT:   ]
 PE32-NEXT: }
 PE32-NEXT: ImageOptionalHeader {
-PE32-NEXT:   MajorLinkerVersion: 10
+PE32-NEXT:   MajorLinkerVersion: 11
 PE32-NEXT:   MinorLinkerVersion: 0
 PE32-NEXT:   SizeOfCode: 512
-PE32-NEXT:   SizeOfInitializedData: 0
+PE32-NEXT:   SizeOfInitializedData: 1024
 PE32-NEXT:   SizeOfUninitializedData: 0
 PE32-NEXT:   AddressOfEntryPoint: 0x1000
 PE32-NEXT:   BaseOfCode: 0x1000
@@ -129,15 +129,15 @@ PE32-NEXT:   BaseOfData: 0x2000
 PE32-NEXT:   ImageBase: 0x400000
 PE32-NEXT:   SectionAlignment: 4096
 PE32-NEXT:   FileAlignment: 512
-PE32-NEXT:   MajorOperatingSystemVersion: 5
-PE32-NEXT:   MinorOperatingSystemVersion: 1
+PE32-NEXT:   MajorOperatingSystemVersion: 6
+PE32-NEXT:   MinorOperatingSystemVersion: 0
 PE32-NEXT:   MajorImageVersion: 0
 PE32-NEXT:   MinorImageVersion: 0
-PE32-NEXT:   MajorSubsystemVersion: 5
-PE32-NEXT:   MinorSubsystemVersion: 1
-PE32-NEXT:   SizeOfImage: 8192
-PE32-NEXT:   SizeOfHeaders: 512
-PE32-NEXT:   Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI (0x2)
+PE32-NEXT:   MajorSubsystemVersion: 6
+PE32-NEXT:   MinorSubsystemVersion: 0
+PE32-NEXT:   SizeOfImage: 16384
+PE32-NEXT:   SizeOfHeaders: 1024
+PE32-NEXT:   Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
 PE32-NEXT:   Subsystem [ (0x8140)
 PE32-NEXT:     IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
 PE32-NEXT:     IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
@@ -148,4 +148,38 @@ PE32-NEXT:   SizeOfStackCommit: 4096
 PE32-NEXT:   SizeOfHeapReserve: 1048576
 PE32-NEXT:   SizeOfHeapCommit: 4096
 PE32-NEXT:   NumberOfRvaAndSize: 16
+PE32-NEXT:   DataDirectory {
+PE32-NEXT:     ExportTableRVA: 0x0
+PE32-NEXT:     ExportTableSize: 0x0
+PE32-NEXT:     ImportTableRVA: 0x0
+PE32-NEXT:     ImportTableSize: 0x0
+PE32-NEXT:     ResourceTableRVA: 0x0
+PE32-NEXT:     ResourceTableSize: 0x0
+PE32-NEXT:     ExceptionTableRVA: 0x0
+PE32-NEXT:     ExceptionTableSize: 0x0
+PE32-NEXT:     CertificateTableRVA: 0x0
+PE32-NEXT:     CertificateTableSize: 0x0
+PE32-NEXT:     BaseRelocationTableRVA: 0x3000
+PE32-NEXT:     BaseRelocationTableSize: 0xC
+PE32-NEXT:     DebugRVA: 0x0
+PE32-NEXT:     DebugSize: 0x0
+PE32-NEXT:     ArchitectureRVA: 0x0
+PE32-NEXT:     ArchitectureSize: 0x0
+PE32-NEXT:     GlobalPtrRVA: 0x0
+PE32-NEXT:     GlobalPtrSize: 0x0
+PE32-NEXT:     TLSTableRVA: 0x0
+PE32-NEXT:     TLSTableSize: 0x0
+PE32-NEXT:     LoadConfigTableRVA: 0x0
+PE32-NEXT:     LoadConfigTableSize: 0x0
+PE32-NEXT:     BoundImportRVA: 0x0
+PE32-NEXT:     BoundImportSize: 0x0
+PE32-NEXT:     IATRVA: 0x0
+PE32-NEXT:     IATSize: 0x0
+PE32-NEXT:     DelayImportDescriptorRVA: 0x0
+PE32-NEXT:     DelayImportDescriptorSize: 0x0
+PE32-NEXT:     CLRRuntimeHeaderRVA: 0x0
+PE32-NEXT:     CLRRuntimeHeaderSize: 0x0
+PE32-NEXT:     ReservedRVA: 0x0
+PE32-NEXT:     ReservedSize: 0x0
+PE32-NEXT:   }
 PE32-NEXT: }
index 1ceb8fc..2f309e3 100644 (file)
@@ -60,6 +60,8 @@ private:
 
   void printRelocation(section_iterator SecI, relocation_iterator RelI);
 
+  void printDataDirectory(uint32_t Index, const std::string &FieldName);
+
   void printX64UnwindInfo();
 
   void printRuntimeFunction(
@@ -560,6 +562,14 @@ void COFFDumper::cacheRelocations() {
   }
 }
 
+void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
+  const data_directory *Data;
+  if (Obj->getDataDirectory(Index, Data))
+    return;
+  W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
+  W.printHex(FieldName + "Size", Data->Size);
+}
+
 void COFFDumper::printFileHeaders() {
   // Print COFF header
   const coff_file_header *COFFHeader = 0;
@@ -621,6 +631,20 @@ void COFFDumper::printFileHeaders() {
     W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve);
     W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit);
     W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize);
+
+    if (PEHeader->NumberOfRvaAndSize > 0) {
+      DictScope D(W, "DataDirectory");
+      static const char * const directory[] = {
+        "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
+        "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
+        "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
+        "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
+      };
+
+      for (uint32_t i = 0; i < PEHeader->NumberOfRvaAndSize; ++i) {
+        printDataDirectory(i, directory[i]);
+      }
+    }
   }
 }