Fix LLD testsuite fallout from r253429
[oota-llvm.git] / tools / llvm-objdump / COFFDump.cpp
index 74d4e369597ce6d269be925a0be9d0c952a112f6..001e352c8d0b8f31cdd2067cfd782a0ea393ea20 100644 (file)
@@ -22,9 +22,9 @@
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/Win64EH.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
 #include <algorithm>
 #include <cstring>
+#include <system_error>
 
 using namespace llvm;
 using namespace object;
@@ -94,7 +94,7 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
 // slots is provided.
 static void printUnwindCode(ArrayRef<UnwindCode> UCs) {
   assert(UCs.size() >= getNumUsedSlots(UCs[0]));
-  outs() <<  format("    0x%02x: ", unsigned(UCs[0].u.CodeOffset))
+  outs() <<  format("      0x%02x: ", unsigned(UCs[0].u.CodeOffset))
          << getUnwindCodeTypeName(UCs[0].getUnwindOp());
   switch (UCs[0].getUnwindOp()) {
   case UOP_PushNonVol:
@@ -151,38 +151,38 @@ static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) {
              << " remaining in buffer";
       return ;
     }
-    printUnwindCode(ArrayRef<UnwindCode>(I, E));
+    printUnwindCode(makeArrayRef(I, E));
     I += UsedSlots;
   }
 }
 
 // Given a symbol sym this functions returns the address and section of it.
-static error_code resolveSectionAndAddress(const COFFObjectFile *Obj,
-                                           const SymbolRef &Sym,
-                                           const coff_section *&ResolvedSection,
-                                           uint64_t &ResolvedAddr) {
-  if (error_code EC = Sym.getAddress(ResolvedAddr))
+static std::error_code
+resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym,
+                         const coff_section *&ResolvedSection,
+                         uint64_t &ResolvedAddr) {
+  ErrorOr<uint64_t> ResolvedAddrOrErr = Sym.getAddress();
+  if (std::error_code EC = ResolvedAddrOrErr.getError())
     return EC;
-  section_iterator iter(Obj->section_begin());
-  if (error_code EC = Sym.getSection(iter))
+  ResolvedAddr = *ResolvedAddrOrErr;
+  ErrorOr<section_iterator> Iter = Sym.getSection();
+  if (std::error_code EC = Iter.getError())
     return EC;
-  ResolvedSection = Obj->getCOFFSection(iter);
-  return object_error::success;
+  ResolvedSection = Obj->getCOFFSection(**Iter);
+  return std::error_code();
 }
 
 // Given a vector of relocations for a section and an offset into this section
 // the function returns the symbol used for the relocation at the offset.
-static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
-                                uint64_t Offset, SymbolRef &Sym) {
+static std::error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
+                                     uint64_t Offset, SymbolRef &Sym) {
   for (std::vector<RelocationRef>::const_iterator I = Rels.begin(),
                                                   E = Rels.end();
                                                   I != E; ++I) {
-    uint64_t Ofs;
-    if (error_code EC = I->getOffset(Ofs))
-      return EC;
+    uint64_t Ofs = I->getOffset();
     if (Ofs == Offset) {
       Sym = *I->getSymbol();
-      return object_error::success;
+      return std::error_code();
     }
   }
   return object_error::parse_failed;
@@ -192,33 +192,34 @@ static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
 // the function resolves the symbol used for the relocation at the offset and
 // returns the section content and the address inside the content pointed to
 // by the symbol.
-static error_code getSectionContents(const COFFObjectFile *Obj,
-                                     const std::vector<RelocationRef> &Rels,
-                                     uint64_t Offset,
-                                     ArrayRef<uint8_t> &Contents,
-                                     uint64_t &Addr) {
+static std::error_code
+getSectionContents(const COFFObjectFile *Obj,
+                   const std::vector<RelocationRef> &Rels, uint64_t Offset,
+                   ArrayRef<uint8_t> &Contents, uint64_t &Addr) {
   SymbolRef Sym;
-  if (error_code EC = resolveSymbol(Rels, Offset, Sym))
+  if (std::error_code EC = resolveSymbol(Rels, Offset, Sym))
     return EC;
   const coff_section *Section;
-  if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
+  if (std::error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
     return EC;
-  if (error_code EC = Obj->getSectionContents(Section, Contents))
+  if (std::error_code EC = Obj->getSectionContents(Section, Contents))
     return EC;
-  return object_error::success;
+  return std::error_code();
 }
 
 // Given a vector of relocations for a section and an offset into this section
 // the function returns the name of the symbol used for the relocation at the
 // offset.
-static error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
-                                    uint64_t Offset, StringRef &Name) {
+static std::error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
+                                         uint64_t Offset, StringRef &Name) {
   SymbolRef Sym;
-  if (error_code EC = resolveSymbol(Rels, Offset, Sym))
+  if (std::error_code EC = resolveSymbol(Rels, Offset, Sym))
     return EC;
-  if (error_code EC = Sym.getName(Name))
+  ErrorOr<StringRef> NameOrErr = Sym.getName();
+  if (std::error_code EC = NameOrErr.getError())
     return EC;
-  return object_error::success;
+  Name = *NameOrErr;
+  return std::error_code();
 }
 
 static void printCOFFSymbolAddress(llvm::raw_ostream &Out,
@@ -240,12 +241,10 @@ printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
     return;
 
   const pe32_header *PE32Header;
-  if (error(Obj->getPE32Header(PE32Header)))
-    return;
+  error(Obj->getPE32Header(PE32Header));
   uint32_t ImageBase = PE32Header->ImageBase;
   uintptr_t IntPtr = 0;
-  if (error(Obj->getVaPtr(TableVA, IntPtr)))
-    return;
+  error(Obj->getVaPtr(TableVA, IntPtr));
   const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr;
   outs() << "SEH Table:";
   for (int I = 0; I < Count; ++I)
@@ -256,30 +255,22 @@ printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
 static void printLoadConfiguration(const COFFObjectFile *Obj) {
   // Skip if it's not executable.
   const pe32_header *PE32Header;
-  if (error(Obj->getPE32Header(PE32Header)))
-    return;
+  error(Obj->getPE32Header(PE32Header));
   if (!PE32Header)
     return;
 
-  const coff_file_header *Header;
-  if (error(Obj->getCOFFHeader(Header)))
-    return;
   // Currently only x86 is supported
-  if (Header->Machine != COFF::IMAGE_FILE_MACHINE_I386)
+  if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_I386)
     return;
 
   const data_directory *DataDir;
-  if (error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir)))
-    return;
+  error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir));
   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);
+  error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr));
 
+  auto *LoadConf = reinterpret_cast<const coff_load_configuration32 *>(IntPtr);
   outs() << "Load configuration:"
          << "\n  Timestamp: " << LoadConf->TimeDateStamp
          << "\n  Major Version: " << LoadConf->MajorVersion
@@ -328,7 +319,7 @@ static void printImportTables(const COFFObjectFile *Obj) {
     const import_lookup_table_entry32 *entry;
     if (I->getImportLookupEntry(entry))
       return;
-    for (; entry->data; ++entry) {
+    for (; entry->Data; ++entry) {
       if (entry->isOrdinal()) {
         outs() << format("      % 6d\n", entry->getOrdinal());
         continue;
@@ -383,26 +374,21 @@ static void printExportTable(const COFFObjectFile *Obj) {
 static bool getPDataSection(const COFFObjectFile *Obj,
                             std::vector<RelocationRef> &Rels,
                             const RuntimeFunction *&RFStart, int &NumRFs) {
-  for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
-       SI != SE; ++SI) {
+  for (const SectionRef &Section : Obj->sections()) {
     StringRef Name;
-    if (error(SI->getName(Name)))
-      continue;
+    error(Section.getName(Name));
     if (Name != ".pdata")
       continue;
 
-    const coff_section *Pdata = Obj->getCOFFSection(SI);
-    for (relocation_iterator RI = SI->relocation_begin(),
-                             RE = SI->relocation_end();
-         RI != RE; ++RI)
-      Rels.push_back(*RI);
+    const coff_section *Pdata = Obj->getCOFFSection(Section);
+    for (const RelocationRef &Reloc : Section.relocations())
+      Rels.push_back(Reloc);
 
     // Sort relocations by address.
     std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
 
     ArrayRef<uint8_t> Contents;
-    if (error(Obj->getSectionContents(Pdata, Contents)))
-      continue;
+    error(Obj->getSectionContents(Pdata, Contents));
     if (Contents.empty())
       continue;
 
@@ -413,12 +399,76 @@ static bool getPDataSection(const COFFObjectFile *Obj,
   return false;
 }
 
+static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) {
+  // The casts to int are required in order to output the value as number.
+  // Without the casts the value would be interpreted as char data (which
+  // results in garbage output).
+  outs() << "    Version: " << static_cast<int>(UI->getVersion()) << "\n";
+  outs() << "    Flags: " << static_cast<int>(UI->getFlags());
+  if (UI->getFlags()) {
+    if (UI->getFlags() & UNW_ExceptionHandler)
+      outs() << " UNW_ExceptionHandler";
+    if (UI->getFlags() & UNW_TerminateHandler)
+      outs() << " UNW_TerminateHandler";
+    if (UI->getFlags() & UNW_ChainInfo)
+      outs() << " UNW_ChainInfo";
+  }
+  outs() << "\n";
+  outs() << "    Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n";
+  outs() << "    Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n";
+  // Maybe this should move to output of UOP_SetFPReg?
+  if (UI->getFrameRegister()) {
+    outs() << "    Frame register: "
+           << getUnwindRegisterName(UI->getFrameRegister()) << "\n";
+    outs() << "    Frame offset: " << 16 * UI->getFrameOffset() << "\n";
+  } else {
+    outs() << "    No frame pointer used\n";
+  }
+  if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
+    // FIXME: Output exception handler data
+  } else if (UI->getFlags() & UNW_ChainInfo) {
+    // FIXME: Output chained unwind info
+  }
+
+  if (UI->NumCodes)
+    outs() << "    Unwind Codes:\n";
+
+  printAllUnwindCodes(makeArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
+
+  outs() << "\n";
+  outs().flush();
+}
+
+/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
+/// pointing to an executable file.
 static void printRuntimeFunction(const COFFObjectFile *Obj,
-                                 const RuntimeFunction &RF,
-                                 uint64_t SectionOffset,
-                                 const std::vector<RelocationRef> &Rels) {
-  outs() << "Function Table:\n";
+                                 const RuntimeFunction &RF) {
+  if (!RF.StartAddress)
+    return;
+  outs() << "Function Table:\n"
+         << format("  Start Address: 0x%04x\n",
+                   static_cast<uint32_t>(RF.StartAddress))
+         << format("  End Address: 0x%04x\n",
+                   static_cast<uint32_t>(RF.EndAddress))
+         << format("  Unwind Info Address: 0x%04x\n",
+                   static_cast<uint32_t>(RF.UnwindInfoOffset));
+  uintptr_t addr;
+  if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr))
+    return;
+  printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr));
+}
 
+/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
+/// pointing to an object file. Unlike executable, fields in RuntimeFunction
+/// struct are filled with zeros, but instead there are relocations pointing to
+/// them so that the linker will fill targets' RVAs to the fields at link
+/// time. This function interprets the relocations to find the data to be used
+/// in the resulting executable.
+static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
+                                     const RuntimeFunction &RF,
+                                     uint64_t SectionOffset,
+                                     const std::vector<RelocationRef> &Rels) {
+  outs() << "Function Table:\n";
   outs() << "  Start Address: ";
   printCOFFSymbolAddress(outs(), Rels,
                          SectionOffset +
@@ -442,11 +492,10 @@ static void printRuntimeFunction(const COFFObjectFile *Obj,
 
   ArrayRef<uint8_t> XContents;
   uint64_t UnwindInfoOffset = 0;
-  if (error(getSectionContents(
+  error(getSectionContents(
           Obj, Rels, SectionOffset +
                          /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
-          XContents, UnwindInfoOffset)))
-    return;
+          XContents, UnwindInfoOffset));
   if (XContents.empty())
     return;
 
@@ -454,54 +503,13 @@ static void printRuntimeFunction(const COFFObjectFile *Obj,
   if (UnwindInfoOffset > XContents.size())
     return;
 
-  const Win64EH::UnwindInfo *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(
-      XContents.data() + UnwindInfoOffset);
-
-  // The casts to int are required in order to output the value as number.
-  // Without the casts the value would be interpreted as char data (which
-  // results in garbage output).
-  outs() << "  Version: " << static_cast<int>(UI->getVersion()) << "\n";
-  outs() << "  Flags: " << static_cast<int>(UI->getFlags());
-  if (UI->getFlags()) {
-    if (UI->getFlags() & UNW_ExceptionHandler)
-      outs() << " UNW_ExceptionHandler";
-    if (UI->getFlags() & UNW_TerminateHandler)
-      outs() << " UNW_TerminateHandler";
-    if (UI->getFlags() & UNW_ChainInfo)
-      outs() << " UNW_ChainInfo";
-  }
-  outs() << "\n";
-  outs() << "  Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n";
-  outs() << "  Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n";
-  // Maybe this should move to output of UOP_SetFPReg?
-  if (UI->getFrameRegister()) {
-    outs() << "  Frame register: "
-           << getUnwindRegisterName(UI->getFrameRegister()) << "\n";
-    outs() << "  Frame offset: " << 16 * UI->getFrameOffset() << "\n";
-  } else {
-    outs() << "  No frame pointer used\n";
-  }
-  if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
-    // FIXME: Output exception handler data
-  } else if (UI->getFlags() & UNW_ChainInfo) {
-    // FIXME: Output chained unwind info
-  }
-
-  if (UI->NumCodes)
-    outs() << "  Unwind Codes:\n";
-
-  printAllUnwindCodes(ArrayRef<UnwindCode>(&UI->UnwindCodes[0], UI->NumCodes));
-
-  outs() << "\n\n";
-  outs().flush();
+  auto *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(XContents.data() +
+                                                           UnwindInfoOffset);
+  printWin64EHUnwindInfo(UI);
 }
 
 void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
-  const coff_file_header *Header;
-  if (error(Obj->getCOFFHeader(Header)))
-    return;
-
-  if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
+  if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_AMD64) {
     errs() << "Unsupported image machine type "
               "(currently only AMD64 is supported).\n";
     return;
@@ -514,10 +522,17 @@ void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
     return;
   ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs);
 
+  bool IsExecutable = Rels.empty();
+  if (IsExecutable) {
+    for (const RuntimeFunction &RF : RFs)
+      printRuntimeFunction(Obj, RF);
+    return;
+  }
+
   for (const RuntimeFunction &RF : RFs) {
     uint64_t SectionOffset =
         std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
-    printRuntimeFunction(Obj, RF, SectionOffset, Rels);
+    printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels);
   }
 }