llvm-objdump/COFF: Print SEH table addresses.
[oota-llvm.git] / tools / llvm-objdump / COFFDump.cpp
index 9c380100e8cd81199b03ea58d206cc5f660ad280..91ca5ba7e2e1f84222f4953bd6459abc575fd4fa 100644 (file)
@@ -10,7 +10,7 @@
 /// \file
 /// \brief This file implements the COFF-specific dumper for llvm-objdump.
 /// It outputs the Win64 EH data structures as plain text.
-/// The encoding of the unwind codes is decribed in MSDN:
+/// The encoding of the unwind codes is described in MSDN:
 /// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
 ///
 //===----------------------------------------------------------------------===//
@@ -161,9 +161,11 @@ static error_code resolveSectionAndAddress(const COFFObjectFile *Obj,
                                            const SymbolRef &Sym,
                                            const coff_section *&ResolvedSection,
                                            uint64_t &ResolvedAddr) {
-  if (error_code ec = Sym.getAddress(ResolvedAddr)) return ec;
-  section_iterator iter(Obj->begin_sections());
-  if (error_code ec = Sym.getSection(iter)) return ec;
+  if (error_code EC = Sym.getAddress(ResolvedAddr))
+    return EC;
+  section_iterator iter(Obj->section_begin());
+  if (error_code EC = Sym.getSection(iter))
+    return EC;
   ResolvedSection = Obj->getCOFFSection(iter);
   return object_error::success;
 }
@@ -176,7 +178,8 @@ static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
                                                   E = Rels.end();
                                                   I != E; ++I) {
     uint64_t Ofs;
-    if (error_code ec = I->getOffset(Ofs)) return ec;
+    if (error_code EC = I->getOffset(Ofs))
+      return EC;
     if (Ofs == Offset) {
       Sym = *I->getSymbol();
       break;
@@ -197,9 +200,10 @@ static error_code getSectionContents(const COFFObjectFile *Obj,
   SymbolRef Sym;
   if (error_code ec = resolveSymbol(Rels, Offset, Sym)) return ec;
   const coff_section *Section;
-  if (error_code ec = resolveSectionAndAddress(Obj, Sym, Section, Addr))
-    return ec;
-  if (error_code ec = Obj->getSectionContents(Section, Contents)) return ec;
+  if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
+    return EC;
+  if (error_code EC = Obj->getSectionContents(Section, Contents))
+    return EC;
   return object_error::success;
 }
 
@@ -209,8 +213,10 @@ static error_code getSectionContents(const COFFObjectFile *Obj,
 static error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
                                     uint64_t Offset, StringRef &Name) {
   SymbolRef Sym;
-  if (error_code ec = resolveSymbol(Rels, Offset, Sym)) return ec;
-  if (error_code ec = Sym.getName(Name)) return ec;
+  if (error_code EC = resolveSymbol(Rels, Offset, Sym))
+    return EC;
+  if (error_code EC = Sym.getName(Name))
+    return EC;
   return object_error::success;
 }
 
@@ -218,8 +224,8 @@ static void printCOFFSymbolAddress(llvm::raw_ostream &Out,
                                    const std::vector<RelocationRef> &Rels,
                                    uint64_t Offset, uint32_t Disp) {
   StringRef Sym;
-  if (error_code ec = resolveSymbolName(Rels, Offset, Sym)) {
-    error(ec);
+  if (error_code EC = resolveSymbolName(Rels, Offset, Sym)) {
+    error(EC);
     return ;
   }
   Out << Sym;
@@ -227,23 +233,81 @@ static void printCOFFSymbolAddress(llvm::raw_ostream &Out,
     Out << format(" + 0x%04x", Disp);
 }
 
+static void
+printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
+  if (Count == 0)
+    return;
+
+  const pe32_header *PE32Header;
+  if (error(Obj->getPE32Header(PE32Header)))
+    return;
+  uint32_t ImageBase = PE32Header->ImageBase;
+  uintptr_t IntPtr = 0;
+  if (error(Obj->getVaPtr(TableVA, IntPtr)))
+    return;
+  const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr;
+  outs() << "SEH Table:";
+  for (int I = 0; I < Count; ++I)
+    outs() << format(" 0x%x", P[I] + ImageBase);
+  outs() << "\n\n";
+}
+
+static void printLoadConfiguration(const COFFObjectFile *Obj) {
+  const coff_file_header *Header;
+  if (error(Obj->getCOFFHeader(Header)))
+    return;
+  // Currently only x86 is supported
+  if (Header->Machine != COFF::IMAGE_FILE_MACHINE_I386)
+    return;
+
+  const data_directory *DataDir;
+  if (error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir)))
+    return;
+  uintptr_t IntPtr = 0;
+  if (DataDir->RelativeVirtualAddress == 0)
+    return;
+  if (error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr)))
+    return;
+
+  const coff_load_configuration32 *LoadConf =
+      reinterpret_cast<const coff_load_configuration32 *>(IntPtr);
+
+  outs() << "Load configuration:"
+         << "\n  Timestamp: " << LoadConf->TimeDateStamp
+         << "\n  Major Version: " << LoadConf->MajorVersion
+         << "\n  Minor Version: " << LoadConf->MinorVersion
+         << "\n  GlobalFlags Clear: " << LoadConf->GlobalFlagsClear
+         << "\n  GlobalFlags Set: " << LoadConf->GlobalFlagsSet
+         << "\n  Critical Section Default Timeout: " << LoadConf->CriticalSectionDefaultTimeout
+         << "\n  Decommit Free Block Threshold: " << LoadConf->DeCommitFreeBlockThreshold
+         << "\n  Decommit Total Free Threshold: " << LoadConf->DeCommitTotalFreeThreshold
+         << "\n  Lock Prefix Table: " << LoadConf->LockPrefixTable
+         << "\n  Maximum Allocation Size: " << LoadConf->MaximumAllocationSize
+         << "\n  Virtual Memory Threshold: " << LoadConf->VirtualMemoryThreshold
+         << "\n  Process Affinity Mask: " << LoadConf->ProcessAffinityMask
+         << "\n  Process Heap Flags: " << LoadConf->ProcessHeapFlags
+         << "\n  CSD Version: " << LoadConf->CSDVersion
+         << "\n  Security Cookie: " << LoadConf->SecurityCookie
+         << "\n  SEH Table: " << LoadConf->SEHandlerTable
+         << "\n  SEH Count: " << LoadConf->SEHandlerCount
+         << "\n\n";
+  printSEHTable(Obj, LoadConf->SEHandlerTable, LoadConf->SEHandlerCount);
+  outs() << "\n";
+}
+
 // Prints import tables. The import table is a table containing the list of
 // DLL name and symbol names which will be linked by the loader.
 static void printImportTables(const COFFObjectFile *Obj) {
-  import_directory_iterator i = Obj->import_directory_begin();
-  import_directory_iterator e = Obj->import_directory_end();
-  if (i == e)
+  import_directory_iterator I = Obj->import_directory_begin();
+  import_directory_iterator E = Obj->import_directory_end();
+  if (I == E)
     return;
   outs() << "The Import Tables:\n";
-  error_code ec;
-  for (; i != e; i = i.increment(ec)) {
-    if (ec)
-      return;
-
+  for (; I != E; I = ++I) {
     const import_directory_table_entry *Dir;
     StringRef Name;
-    if (i->getImportTableEntry(Dir)) return;
-    if (i->getName(Name)) return;
+    if (I->getImportTableEntry(Dir)) return;
+    if (I->getName(Name)) return;
 
     outs() << format("  lookup %08x time %08x fwd %08x name %08x addr %08x\n\n",
                      static_cast<uint32_t>(Dir->ImportLookupTableRVA),
@@ -254,7 +318,7 @@ static void printImportTables(const COFFObjectFile *Obj) {
     outs() << "    DLL Name: " << Name << "\n";
     outs() << "    Hint/Ord  Name\n";
     const import_lookup_table_entry32 *entry;
-    if (i->getImportLookupEntry(entry))
+    if (I->getImportLookupEntry(entry))
       return;
     for (; entry->data; ++entry) {
       if (entry->isOrdinal()) {
@@ -271,6 +335,41 @@ static void printImportTables(const COFFObjectFile *Obj) {
   }
 }
 
+// Prints export tables. The export table is a table containing the list of
+// exported symbol from the DLL.
+static void printExportTable(const COFFObjectFile *Obj) {
+  outs() << "Export Table:\n";
+  export_directory_iterator I = Obj->export_directory_begin();
+  export_directory_iterator E = Obj->export_directory_end();
+  if (I == E)
+    return;
+  StringRef DllName;
+  uint32_t OrdinalBase;
+  if (I->getDllName(DllName))
+    return;
+  if (I->getOrdinalBase(OrdinalBase))
+    return;
+  outs() << " DLL name: " << DllName << "\n";
+  outs() << " Ordinal base: " << OrdinalBase << "\n";
+  outs() << " Ordinal      RVA  Name\n";
+  for (; I != E; I = ++I) {
+    uint32_t Ordinal;
+    if (I->getOrdinal(Ordinal))
+      return;
+    uint32_t RVA;
+    if (I->getExportRVA(RVA))
+      return;
+    outs() << format("    % 4d %# 8x", Ordinal, RVA);
+
+    StringRef Name;
+    if (I->getSymbolName(Name))
+      continue;
+    if (!Name.empty())
+      outs() << "  " << Name;
+    outs() << "\n";
+  }
+}
+
 void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
   const coff_file_header *Header;
   if (error(Obj->getCOFFHeader(Header))) return;
@@ -283,12 +382,8 @@ void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
 
   const coff_section *Pdata = 0;
 
-  error_code ec;
-  for (section_iterator SI = Obj->begin_sections(),
-                        SE = Obj->end_sections();
-                        SI != SE; SI.increment(ec)) {
-    if (error(ec)) return;
-
+  for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
+       SI != SE; ++SI) {
     StringRef Name;
     if (error(SI->getName(Name))) continue;
 
@@ -296,12 +391,10 @@ void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
 
     Pdata = Obj->getCOFFSection(SI);
     std::vector<RelocationRef> Rels;
-    for (relocation_iterator RI = SI->begin_relocations(),
-                             RE = SI->end_relocations();
-                             RI != RE; RI.increment(ec)) {
-      if (error(ec)) break;
+    for (relocation_iterator RI = SI->relocation_begin(),
+                             RE = SI->relocation_end();
+         RI != RE; ++RI)
       Rels.push_back(*RI);
-    }
 
     // Sort relocations by address.
     std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
@@ -399,5 +492,8 @@ void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
 }
 
 void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) {
-  printImportTables(dyn_cast<const COFFObjectFile>(Obj));
+  const COFFObjectFile *file = dyn_cast<const COFFObjectFile>(Obj);
+  printLoadConfiguration(file);
+  printImportTables(file);
+  printExportTable(file);
 }