[llvm] r365524 - [Object][XCOFF] Add support for 64-bit file header and section header dumping.

Sean Fertile via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 9 11:09:11 PDT 2019


Author: sfertile
Date: Tue Jul  9 11:09:11 2019
New Revision: 365524

URL: http://llvm.org/viewvc/llvm-project?rev=365524&view=rev
Log:
[Object][XCOFF] Add support for 64-bit file header and section header dumping.

Adds a readobj dumper for 32-bit and 64-bit section header tables, and extend
support for the file-header dumping to include 64-bit object files. Also
refactors the binary file parsing to be done in a helper function in an attempt
to cleanup error handeling.

Differential Revision: https://reviews.llvm.org/D63843

Added:
    llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o   (with props)
    llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test
Modified:
    llvm/trunk/include/llvm/BinaryFormat/Magic.h
    llvm/trunk/include/llvm/Object/Binary.h
    llvm/trunk/include/llvm/Object/ObjectFile.h
    llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
    llvm/trunk/lib/BinaryFormat/Magic.cpp
    llvm/trunk/lib/Object/Binary.cpp
    llvm/trunk/lib/Object/ObjectFile.cpp
    llvm/trunk/lib/Object/SymbolicFile.cpp
    llvm/trunk/lib/Object/XCOFFObjectFile.cpp
    llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test
    llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp
    llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp

Modified: llvm/trunk/include/llvm/BinaryFormat/Magic.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Magic.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Magic.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Magic.h Tue Jul  9 11:09:11 2019
@@ -46,6 +46,7 @@ struct file_magic {
     pecoff_executable,   ///< PECOFF executable file
     windows_resource,    ///< Windows compiled resource file (.res)
     xcoff_object_32,     ///< 32-bit XCOFF object file
+    xcoff_object_64,     ///< 64-bit XCOFF object file
     wasm_object,         ///< WebAssembly Object file
     pdb,                 ///< Windows PDB debug info file
   };

Modified: llvm/trunk/include/llvm/Object/Binary.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Binary.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Binary.h (original)
+++ llvm/trunk/include/llvm/Object/Binary.h Tue Jul  9 11:09:11 2019
@@ -51,7 +51,9 @@ protected:
     // Object and children.
     ID_StartObjects,
     ID_COFF,
+
     ID_XCOFF32, // AIX XCOFF 32-bit
+    ID_XCOFF64, // AIX XCOFF 64-bit
 
     ID_ELF32L, // ELF 32-bit, little endian
     ID_ELF32B, // ELF 32-bit, big endian
@@ -121,7 +123,7 @@ public:
     return TypeID == ID_COFF;
   }
 
-  bool isXCOFF() const { return TypeID == ID_XCOFF32; }
+  bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; }
 
   bool isWasm() const { return TypeID == ID_Wasm; }
 

Modified: llvm/trunk/include/llvm/Object/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ObjectFile.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ObjectFile.h Tue Jul  9 11:09:11 2019
@@ -359,7 +359,7 @@ public:
   createCOFFObjectFile(MemoryBufferRef Object);
 
   static Expected<std::unique_ptr<ObjectFile>>
-  createXCOFFObjectFile(MemoryBufferRef Object);
+  createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
 
   static Expected<std::unique_ptr<ObjectFile>>
   createELFObjectFile(MemoryBufferRef Object);

Modified: llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/XCOFFObjectFile.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/XCOFFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/XCOFFObjectFile.h Tue Jul  9 11:09:11 2019
@@ -34,7 +34,7 @@
 namespace llvm {
 namespace object {
 
-struct XCOFFFileHeader {
+struct XCOFFFileHeader32 {
   support::ubig16_t Magic;
   support::ubig16_t NumberOfSections;
 
@@ -48,7 +48,21 @@ struct XCOFFFileHeader {
   support::ubig16_t Flags;
 };
 
-struct XCOFFSectionHeader {
+struct XCOFFFileHeader64 {
+  support::ubig16_t Magic;
+  support::ubig16_t NumberOfSections;
+
+  // Unix time value, value of 0 indicates no timestamp.
+  // Negative values are reserved.
+  support::big32_t TimeStamp;
+
+  support::ubig64_t SymbolTableOffset; // File offset to symbol table.
+  support::ubig16_t AuxHeaderSize;
+  support::ubig16_t Flags;
+  support::ubig32_t NumberOfSymTableEntries;
+};
+
+struct XCOFFSectionHeader32 {
   char Name[XCOFF::SectionNameSize];
   support::ubig32_t PhysicalAddress;
   support::ubig32_t VirtualAddress;
@@ -59,6 +73,24 @@ struct XCOFFSectionHeader {
   support::ubig16_t NumberOfRelocations;
   support::ubig16_t NumberOfLineNumbers;
   support::big32_t Flags;
+
+  StringRef getName() const;
+};
+
+struct XCOFFSectionHeader64 {
+  char Name[XCOFF::SectionNameSize];
+  support::ubig64_t PhysicalAddress;
+  support::ubig64_t VirtualAddress;
+  support::ubig64_t SectionSize;
+  support::big64_t FileOffsetToRawData;
+  support::big64_t FileOffsetToRelocationInfo;
+  support::big64_t FileOffsetToLineNumberInfo;
+  support::ubig32_t NumberOfRelocations;
+  support::ubig32_t NumberOfLineNumbers;
+  support::big32_t Flags;
+  char Padding[4];
+
+  StringRef getName() const;
 };
 
 struct XCOFFSymbolEntry {
@@ -97,20 +129,54 @@ struct XCOFFStringTable {
 
 class XCOFFObjectFile : public ObjectFile {
 private:
-  const XCOFFFileHeader *FileHdrPtr = nullptr;
-  const XCOFFSectionHeader *SectionHdrTablePtr = nullptr;
+  const void *FileHeader = nullptr;
+  const void *SectionHeaderTable = nullptr;
+
   const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
   XCOFFStringTable StringTable = {0, nullptr};
 
+  const XCOFFFileHeader32 *fileHeader32() const;
+  const XCOFFFileHeader64 *fileHeader64() const;
+
+  const XCOFFSectionHeader32 *sectionHeaderTable32() const;
+  const XCOFFSectionHeader64 *sectionHeaderTable64() const;
+
   size_t getFileHeaderSize() const;
   size_t getSectionHeaderSize() const;
 
-  const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
+  const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
+  const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
+  void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
+  uintptr_t getSectionHeaderTableAddress() const;
+
+  // This returns a pointer to the start of the storage for the name field of
+  // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
+  // null-terminated.
+  const char *getSectionNameInternal(DataRefImpl Sec) const;
+
+  int32_t getSectionFlags(DataRefImpl Sec) const;
+
   static bool isReservedSectionNumber(int16_t SectionNumber);
-  std::error_code getSectionByNum(int16_t Num,
-                                  const XCOFFSectionHeader *&Result) const;
+  Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
+
+  // Constructor and "create" factory function. The constructor is only a thin
+  // wrapper around the base constructor. The "create" function fills out the
+  // XCOFF-specific information and performs the error checking along the way.
+  XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
+  static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
+                                                           MemoryBufferRef MBR);
+
+  // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
+  // and an XCOFFStringTable if parsing succeeded.
+  static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
+                                                     uint64_t Offset);
+
+  // Make a friend so it can call the private 'create' function.
+  friend Expected<std::unique_ptr<ObjectFile>>
+  ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
 
 public:
+  // Interface inherited from base classes.
   void moveSymbolNext(DataRefImpl &Symb) const override;
   uint32_t getSymbolFlags(DataRefImpl Symb) const override;
   basic_symbol_iterator symbol_begin() const override;
@@ -156,10 +222,11 @@ public:
   Expected<uint64_t> getStartAddress() const override;
   bool isRelocatableObject() const override;
 
-  XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
+  // Below here is the non-inherited interface.
+  bool is64Bit() const;
 
-  const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
   const XCOFFSymbolEntry *getPointerToSymbolTable() const {
+    assert(!is64Bit() && "Symbol table handling not supported yet.");
     return SymbolTblPtr;
   }
 
@@ -167,19 +234,32 @@ public:
   getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
 
   const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
+
+  // File header related interfaces.
   uint16_t getMagic() const;
   uint16_t getNumberOfSections() const;
   int32_t getTimeStamp() const;
-  uint32_t getSymbolTableOffset() const;
 
-  // Returns the value as encoded in the object file.
-  // Negative values are reserved for future use.
-  int32_t getRawNumberOfSymbolTableEntries() const;
+  // Symbol table offset and entry count are handled differently between
+  // XCOFF32 and XCOFF64.
+  uint32_t getSymbolTableOffset32() const;
+  uint64_t getSymbolTableOffset64() const;
+
+  // Note that this value is signed and might return a negative value. Negative
+  // values are reserved for future use.
+  int32_t getRawNumberOfSymbolTableEntries32() const;
+
+  // The sanitized value appropriate to use as an index into the symbol table.
+  uint32_t getLogicalNumberOfSymbolTableEntries32() const;
+
+  uint32_t getNumberOfSymbolTableEntries64() const;
 
-  // Returns a sanitized value, useable as an index into the symbol table.
-  uint32_t getLogicalNumberOfSymbolTableEntries() const;
   uint16_t getOptionalHeaderSize() const;
-  uint16_t getFlags() const { return FileHdrPtr->Flags; };
+  uint16_t getFlags() const;
+
+  // Section header table related interfaces.
+  ArrayRef<XCOFFSectionHeader32> sections32() const;
+  ArrayRef<XCOFFSectionHeader64> sections64() const;
 }; // XCOFFObjectFile
 
 } // namespace object

Modified: llvm/trunk/lib/BinaryFormat/Magic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Magic.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Magic.cpp (original)
+++ llvm/trunk/lib/BinaryFormat/Magic.cpp Tue Jul  9 11:09:11 2019
@@ -66,6 +66,8 @@ file_magic llvm::identify_magic(StringRe
     // XCOFF format
     if (startswith(Magic, "\x01\xDF"))
       return file_magic::xcoff_object_32;
+    if (startswith(Magic, "\x01\xF7"))
+      return file_magic::xcoff_object_64;
     break;
 
   case 0xDE: // 0x0B17C0DE = BC wraper

Modified: llvm/trunk/lib/Object/Binary.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Binary.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Binary.cpp (original)
+++ llvm/trunk/lib/Object/Binary.cpp Tue Jul  9 11:09:11 2019
@@ -70,6 +70,7 @@ Expected<std::unique_ptr<Binary>> object
   case file_magic::pecoff_executable:
   case file_magic::bitcode:
   case file_magic::xcoff_object_32:
+  case file_magic::xcoff_object_64:
   case file_magic::wasm_object:
     return ObjectFile::createSymbolicFile(Buffer, Type, Context);
   case file_magic::macho_universal_binary:

Modified: llvm/trunk/lib/Object/ObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ObjectFile.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/ObjectFile.cpp Tue Jul  9 11:09:11 2019
@@ -150,7 +150,9 @@ ObjectFile::createObjectFile(MemoryBuffe
   case file_magic::pecoff_executable:
     return createCOFFObjectFile(Object);
   case file_magic::xcoff_object_32:
-    return createXCOFFObjectFile(Object);
+    return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);
+  case file_magic::xcoff_object_64:
+    return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
   case file_magic::wasm_object:
     return createWasmObjectFile(Object);
   }

Modified: llvm/trunk/lib/Object/SymbolicFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/SymbolicFile.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/SymbolicFile.cpp (original)
+++ llvm/trunk/lib/Object/SymbolicFile.cpp Tue Jul  9 11:09:11 2019
@@ -70,6 +70,7 @@ SymbolicFile::createSymbolicFile(MemoryB
   case file_magic::macho_kext_bundle:
   case file_magic::pecoff_executable:
   case file_magic::xcoff_object_32:
+  case file_magic::xcoff_object_64:
   case file_magic::wasm_object:
     return ObjectFile::createObjectFile(Object, Type);
   case file_magic::coff_import_library:

Modified: llvm/trunk/lib/Object/XCOFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/XCOFFObjectFile.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/XCOFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/XCOFFObjectFile.cpp Tue Jul  9 11:09:11 2019
@@ -22,32 +22,20 @@
 namespace llvm {
 namespace object {
 
-enum { XCOFF32FileHeaderSize = 20 };
-static_assert(sizeof(XCOFFFileHeader) == XCOFF32FileHeaderSize,
-              "Wrong size for XCOFF file header.");
-
-// Sets EC and returns false if there is less than 'Size' bytes left in the
-// buffer at 'Offset'.
-static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Offset,
-                      uint64_t Size) {
-  if (M.getBufferSize() < Offset + Size) {
-    EC = object_error::unexpected_eof;
-    return false;
-  }
-  return true;
-}
-
-// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
-// Returns unexpected_eof on error.
+// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
+// 'M'. Returns a pointer to the underlying object on success.
 template <typename T>
-static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
-                                 const void *Ptr,
-                                 const uint64_t Size = sizeof(T)) {
+static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
+                                     const uint64_t Size = sizeof(T)) {
   uintptr_t Addr = uintptr_t(Ptr);
   if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
-    return EC;
-  Obj = reinterpret_cast<const T *>(Addr);
-  return std::error_code();
+    return errorCodeToError(EC);
+  return reinterpret_cast<const T *>(Addr);
+}
+
+static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
+  return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
+                                     Offset);
 }
 
 template <typename T> static const T *viewAs(uintptr_t in) {
@@ -60,43 +48,69 @@ static StringRef generateStringRef(const
                     : StringRef(Name, Size);
 }
 
-const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
-  auto Sec = viewAs<XCOFFSectionHeader>(Ref.p);
-#ifndef NDEBUG
-  if (Sec < SectionHdrTablePtr ||
-      Sec >= (SectionHdrTablePtr + getNumberOfSections()))
+void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
+                                          uintptr_t TableAddress) const {
+  if (Addr < TableAddress)
+    report_fatal_error("Section header outside of section header table.");
+
+  uintptr_t Offset = Addr - TableAddress;
+  if (Offset >= getSectionHeaderSize() * getNumberOfSections())
     report_fatal_error("Section header outside of section header table.");
 
-  uintptr_t Offset = uintptr_t(Sec) - uintptr_t(SectionHdrTablePtr);
   if (Offset % getSectionHeaderSize() != 0)
     report_fatal_error(
         "Section header pointer does not point to a valid section header.");
+}
+
+const XCOFFSectionHeader32 *
+XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
+  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+#ifndef NDEBUG
+  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
 #endif
-  return Sec;
+  return viewAs<XCOFFSectionHeader32>(Ref.p);
+}
+
+const XCOFFSectionHeader64 *
+XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
+  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+#ifndef NDEBUG
+  checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
+#endif
+  return viewAs<XCOFFSectionHeader64>(Ref.p);
 }
 
 const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
+  assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
   assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
   auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
   return SymEntPtr;
 }
 
-// The next 2 functions are not exactly necessary yet, but they are useful to
-// abstract over the size difference between XCOFF32 and XCOFF64 structure
-// definitions.
-size_t XCOFFObjectFile::getFileHeaderSize() const {
-  return sizeof(XCOFFFileHeader);
+const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
+  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+  return static_cast<const XCOFFFileHeader32 *>(FileHeader);
 }
 
-size_t XCOFFObjectFile::getSectionHeaderSize() const {
-  return sizeof(XCOFFSectionHeader);
+const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
+  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+  return static_cast<const XCOFFFileHeader64 *>(FileHeader);
 }
 
-uint16_t XCOFFObjectFile::getMagic() const { return FileHdrPtr->Magic; }
+const XCOFFSectionHeader32 *
+XCOFFObjectFile::sectionHeaderTable32() const {
+  assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+  return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
+}
+
+const XCOFFSectionHeader64 *
+XCOFFObjectFile::sectionHeaderTable64() const {
+  assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+  return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
+}
 
 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
   const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
-
   SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
   Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
 }
@@ -158,14 +172,11 @@ XCOFFObjectFile::getSymbolSection(DataRe
   if (isReservedSectionNumber(SectNum))
     return section_end();
 
-  const XCOFFSectionHeader *Sec;
-  if (std::error_code EC = getSectionByNum(SectNum, Sec))
-    return errorCodeToError(EC);
-
-  DataRefImpl SecDRI;
-  SecDRI.p = reinterpret_cast<uintptr_t>(Sec);
+  Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
+  if (!ExpSec)
+    return ExpSec.takeError();
 
-  return section_iterator(SectionRef(SecDRI, this));
+  return section_iterator(SectionRef(ExpSec.get(), this));
 }
 
 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
@@ -174,25 +185,26 @@ void XCOFFObjectFile::moveSectionNext(Da
 }
 
 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
-  const char *Name = toSection(Sec)->Name;
-  auto NulCharPtr =
-      static_cast<const char *>(memchr(Name, '\0', XCOFF::SectionNameSize));
-  return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
-                    : StringRef(Name, XCOFF::SectionNameSize);
+  return generateStringRef(getSectionNameInternal(Sec), XCOFF::SectionNameSize);
 }
 
 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
-  return toSection(Sec)->VirtualAddress;
+  return is64Bit() ? toSection64(Sec)->VirtualAddress
+                   : toSection32(Sec)->VirtualAddress;
 }
 
 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
   // Section numbers in XCOFF are numbered beginning at 1. A section number of
   // zero is used to indicate that a symbol is being imported or is undefined.
-  return toSection(Sec) - SectionHdrTablePtr + 1;
+  if (is64Bit())
+    return toSection64(Sec) - sectionHeaderTable64() + 1;
+  else
+    return toSection32(Sec) - sectionHeaderTable32() + 1;
 }
 
 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
-  return toSection(Sec)->SectionSize;
+  return is64Bit() ? toSection64(Sec)->SectionSize
+                   : toSection32(Sec)->SectionSize;
 }
 
 Expected<ArrayRef<uint8_t>>
@@ -213,16 +225,16 @@ bool XCOFFObjectFile::isSectionCompresse
 }
 
 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
-  return toSection(Sec)->Flags & XCOFF::STYP_TEXT;
+  return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
 }
 
 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
-  unsigned Flags = toSection(Sec)->Flags;
+  uint32_t Flags = getSectionFlags(Sec);
   return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
 }
 
 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
-  unsigned Flags = toSection(Sec)->Flags;
+  uint32_t Flags = getSectionFlags(Sec);
   return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
 }
 
@@ -277,45 +289,41 @@ uint32_t XCOFFObjectFile::getSymbolFlags
 }
 
 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
+  assert(!is64Bit() && "64-bit support not implemented yet.");
   DataRefImpl SymDRI;
   SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
   return basic_symbol_iterator(SymbolRef(SymDRI, this));
 }
 
 basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
+  assert(!is64Bit() && "64-bit support not implemented yet.");
   DataRefImpl SymDRI;
   SymDRI.p = reinterpret_cast<uintptr_t>(
-      SymbolTblPtr + getLogicalNumberOfSymbolTableEntries());
+      SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
   return basic_symbol_iterator(SymbolRef(SymDRI, this));
 }
 
 section_iterator XCOFFObjectFile::section_begin() const {
   DataRefImpl DRI;
-  DRI.p = reinterpret_cast<uintptr_t>(SectionHdrTablePtr);
+  DRI.p = getSectionHeaderTableAddress();
   return section_iterator(SectionRef(DRI, this));
 }
 
 section_iterator XCOFFObjectFile::section_end() const {
   DataRefImpl DRI;
-  DRI.p =
-      reinterpret_cast<uintptr_t>(SectionHdrTablePtr + getNumberOfSections());
+  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
+                        getNumberOfSections() * getSectionHeaderSize());
   return section_iterator(SectionRef(DRI, this));
 }
 
-uint8_t XCOFFObjectFile::getBytesInAddress() const {
-  // Only support 32-bit object files for now ...
-  assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
-  return 4;
-}
+uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
 
 StringRef XCOFFObjectFile::getFileFormatName() const {
-  assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
-  return "aixcoff-rs6000";
+  return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
 }
 
 Triple::ArchType XCOFFObjectFile::getArch() const {
-  assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
-  return Triple::ppc;
+  return is64Bit() ? Triple::ppc64 : Triple::ppc;
 }
 
 SubtargetFeatures XCOFFObjectFile::getFeatures() const {
@@ -335,19 +343,36 @@ Expected<uint64_t> XCOFFObjectFile::getS
   return 0;
 }
 
-std::error_code
-XCOFFObjectFile::getSectionByNum(int16_t Num,
-                                 const XCOFFSectionHeader *&Result) const {
-  if (Num > 0 && static_cast<uint16_t>(Num) <= getNumberOfSections()) {
-    Result = SectionHdrTablePtr + (Num - 1);
-    return std::error_code();
-  }
+size_t XCOFFObjectFile::getFileHeaderSize() const {
+  return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
+}
 
-  return object_error::invalid_section_index;
+size_t XCOFFObjectFile::getSectionHeaderSize() const {
+  return is64Bit() ? sizeof(XCOFFSectionHeader64) :
+                     sizeof(XCOFFSectionHeader32);
+}
+
+bool XCOFFObjectFile::is64Bit() const {
+  return Binary::ID_XCOFF64 == getType();
+}
+
+uint16_t XCOFFObjectFile::getMagic() const {
+  return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
+}
+
+Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
+  if (Num <= 0 || Num > getNumberOfSections())
+    return errorCodeToError(object_error::invalid_section_index);
+
+  DataRefImpl DRI;
+  DRI.p = getWithOffset(getSectionHeaderTableAddress(),
+                        getSectionHeaderSize() * (Num - 1));
+  return DRI;
 }
 
 Expected<StringRef>
 XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
+  assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
   int16_t SectionNum = SymEntPtr->SectionNumber;
 
   switch (SectionNum) {
@@ -357,14 +382,12 @@ XCOFFObjectFile::getSymbolSectionName(co
     return "N_ABS";
   case XCOFF::N_UNDEF:
     return "N_UNDEF";
-  default: {
-    const XCOFFSectionHeader *SectHeaderPtr;
-    std::error_code EC;
-    if ((EC = getSectionByNum(SectionNum, SectHeaderPtr)))
-      return errorCodeToError(EC);
-    else
-      return generateStringRef(SectHeaderPtr->Name, XCOFF::SectionNameSize);
-  }
+  default:
+    Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
+    if (SecRef)
+      return generateStringRef(getSectionNameInternal(SecRef.get()),
+                               XCOFF::SectionNameSize);
+    return SecRef.takeError();
   }
 }
 
@@ -373,99 +396,180 @@ bool XCOFFObjectFile::isReservedSectionN
 }
 
 uint16_t XCOFFObjectFile::getNumberOfSections() const {
-  return FileHdrPtr->NumberOfSections;
+  return is64Bit() ? fileHeader64()->NumberOfSections
+                   : fileHeader32()->NumberOfSections;
 }
 
-int32_t XCOFFObjectFile::getTimeStamp() const { return FileHdrPtr->TimeStamp; }
+int32_t XCOFFObjectFile::getTimeStamp() const {
+  return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
+}
 
-uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
-  return FileHdrPtr->SymbolTableOffset;
+uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
+  return is64Bit() ? fileHeader64()->AuxHeaderSize
+                   : fileHeader32()->AuxHeaderSize;
 }
 
-int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries() const {
-  return FileHdrPtr->NumberOfSymTableEntries;
+uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
+  return fileHeader32()->SymbolTableOffset;
 }
 
-uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries() const {
-  return (FileHdrPtr->NumberOfSymTableEntries >= 0
-              ? FileHdrPtr->NumberOfSymTableEntries
+int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
+  // As far as symbol table size is concerned, if this field is negative it is
+  // to be treated as a 0. However since this field is also used for printing we
+  // don't want to truncate any negative values.
+  return fileHeader32()->NumberOfSymTableEntries;
+}
+
+uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
+  return (fileHeader32()->NumberOfSymTableEntries >= 0
+              ? fileHeader32()->NumberOfSymTableEntries
               : 0);
 }
 
-uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
-  return FileHdrPtr->AuxHeaderSize;
+uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
+  return fileHeader64()->SymbolTableOffset;
 }
 
-XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
-    : ObjectFile(Binary::ID_XCOFF32, Object) {
+uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
+  return fileHeader64()->NumberOfSymTableEntries;
+}
 
-  // Current location within the file.
-  uint64_t CurPtr = 0;
+uint16_t XCOFFObjectFile::getFlags() const {
+  return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
+}
 
-  if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr)))
-    return;
+const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
+  return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
+}
 
-  CurPtr += getFileHeaderSize();
-  // TODO FIXME we don't have support for an optional header yet, so just skip
-  // past it.
-  CurPtr += FileHdrPtr->AuxHeaderSize;
+uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
+  return reinterpret_cast<uintptr_t>(SectionHeaderTable);
+}
 
-  if (getNumberOfSections() != 0) {
-    if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr,
-                        getNumberOfSections() * getSectionHeaderSize())))
-      return;
-  }
+int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
+  return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
+}
 
-  if (getLogicalNumberOfSymbolTableEntries() == 0)
-    return;
+XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
+    : ObjectFile(Type, Object) {
+  assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
+}
 
-  // Get pointer to the symbol table.
-  CurPtr = FileHdrPtr->SymbolTableOffset;
-  uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
-                             getLogicalNumberOfSymbolTableEntries();
+ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
+  assert(is64Bit() && "64-bit interface called for non 64-bit file.");
+  const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
+  return ArrayRef<XCOFFSectionHeader64>(TablePtr,
+                                        TablePtr + getNumberOfSections());
+}
 
-  if ((EC = getObject(SymbolTblPtr, Data, base() + CurPtr, SymbolTableSize)))
-    return;
+ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
+  assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
+  const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
+  return ArrayRef<XCOFFSectionHeader32>(TablePtr,
+                                        TablePtr + getNumberOfSections());
+}
+
+Expected<XCOFFStringTable>
+XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
+  // If there is a string table, then the buffer must contain at least 4 bytes
+  // for the string table's size. Not having a string table is not an error.
+  if (auto EC = Binary::checkOffset(
+          Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4))
+    return XCOFFStringTable{0, nullptr};
+
+  // Read the size out of the buffer.
+  uint32_t Size = support::endian::read32be(Obj->base() + Offset);
 
-  // Move pointer to the string table.
-  CurPtr += SymbolTableSize;
+  // If the size is less then 4, then the string table is just a size and no
+  // string data.
+  if (Size <= 4)
+    return XCOFFStringTable{4, nullptr};
 
-  if (CurPtr + 4 > Data.getBufferSize())
-    return;
+  auto StringTableOrErr =
+      getObject<char>(Obj->Data, Obj->base() + Offset, Size);
+  if (Error E = StringTableOrErr.takeError())
+    return std::move(E);
 
-  StringTable.Size = support::endian::read32be(base() + CurPtr);
+  const char *StringTablePtr = StringTableOrErr.get();
+  if (StringTablePtr[Size - 1] != '\0')
+    return errorCodeToError(object_error::string_table_non_null_end);
+
+  return XCOFFStringTable{Size, StringTablePtr};
+}
 
-  if (StringTable.Size <= 4)
-    return;
+Expected<std::unique_ptr<XCOFFObjectFile>>
+XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
+  // Can't use make_unique because of the private constructor.
+  std::unique_ptr<XCOFFObjectFile> Obj;
+  Obj.reset(new XCOFFObjectFile(Type, MBR));
 
-  // Check for whether the String table has the size indicated by length
-  // field
-  if (!checkSize(Data, EC, CurPtr, StringTable.Size))
-    return;
+  uint64_t CurOffset = 0;
+  const auto *Base = Obj->base();
+  MemoryBufferRef Data = Obj->Data;
+
+  // Parse file header.
+  auto FileHeaderOrErr =
+      getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
+  if (Error E = FileHeaderOrErr.takeError())
+    return std::move(E);
+  Obj->FileHeader = FileHeaderOrErr.get();
+
+  CurOffset += Obj->getFileHeaderSize();
+  // TODO FIXME we don't have support for an optional header yet, so just skip
+  // past it.
+  CurOffset += Obj->getOptionalHeaderSize();
 
-  StringTable.Data = reinterpret_cast<const char *>(base() + CurPtr);
-  if (StringTable.Data[StringTable.Size - 1] != '\0') {
-    EC = object_error::string_table_non_null_end;
-    return;
+  // Parse the section header table if it is present.
+  if (Obj->getNumberOfSections()) {
+    auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
+                                           Obj->getNumberOfSections() *
+                                               Obj->getSectionHeaderSize());
+    if (Error E = SecHeadersOrErr.takeError())
+      return std::move(E);
+    Obj->SectionHeaderTable = SecHeadersOrErr.get();
   }
+
+  // 64-bit object supports only file header and section headers for now.
+  if (Obj->is64Bit())
+    return std::move(Obj);
+
+  // If there is no symbol table we are done parsing the memory buffer.
+  if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
+    return std::move(Obj);
+
+  // Parse symbol table.
+  CurOffset = Obj->fileHeader32()->SymbolTableOffset;
+  uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
+                             Obj->getLogicalNumberOfSymbolTableEntries32();
+  auto SymTableOrErr =
+      getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
+  if (Error E = SymTableOrErr.takeError())
+    return std::move(E);
+  Obj->SymbolTblPtr = SymTableOrErr.get();
+  CurOffset += SymbolTableSize;
+
+  // Parse String table.
+  Expected<XCOFFStringTable> StringTableOrErr =
+      parseStringTable(Obj.get(), CurOffset);
+  if (Error E = StringTableOrErr.takeError())
+    return std::move(E);
+  Obj->StringTable = StringTableOrErr.get();
+
+  return std::move(Obj);
 }
 
 Expected<std::unique_ptr<ObjectFile>>
-ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) {
-  StringRef Data = Object.getBuffer();
-  file_magic Type = identify_magic(Data);
-  std::error_code EC;
-  std::unique_ptr<ObjectFile> Ret;
-
-  if (Type == file_magic::xcoff_object_32) {
-    Ret.reset(new XCOFFObjectFile(Object, EC));
-  } else {
-    llvm_unreachable("Encountered an unexpected binary file type!");
-  }
+ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
+                                  unsigned FileType) {
+  return XCOFFObjectFile::create(FileType, MemBufRef);
+}
 
-  if (EC)
-    return errorCodeToError(EC);
-  return std::move(Ret);
+StringRef XCOFFSectionHeader32::getName() const {
+  return generateStringRef(Name, XCOFF::SectionNameSize);
+}
+
+StringRef XCOFFSectionHeader64::getName() const {
+  return generateStringRef(Name, XCOFF::SectionNameSize);
 }
 
 } // namespace object

Added: llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o?rev=365524&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test Tue Jul  9 11:09:11 2019
@@ -1,5 +1,8 @@
 # RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic.o | \
 # RUN: FileCheck --check-prefix=FILEHEADER %s
+#
+# RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-64.o | \
+# RUN: FileCheck --check-prefix=FILEHEADER64 %s
 
 # RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-neg-time.o | \
 # RUN: FileCheck --check-prefix=NEGTIME %s
@@ -21,6 +24,20 @@
 # FILEHEADER-NEXT:   Flags: 0x0
 # FILEHEADER-NEXT: }
 
+# FILEHEADER64:     File: {{.*}}xcoff-basic-64.o
+# FILEHEADER64-NEXT:  Format: aix5coff64-rs6000
+# FILEHEADER64-NEXT:  Arch: powerpc64
+# FILEHEADER64-NEXT:  AddressSize: 64bit
+# FILEHEADER64-NEXT:  FileHeader {
+# FILEHEADER64-NEXT:    Magic: 0x1F7
+# FILEHEADER64-NEXT:    NumberOfSections: 5
+# FILEHEADER64-NEXT:    TimeStamp: 2019-03-18T20:03:47Z (0x5C8FF9A3)
+# FILEHEADER64-NEXT:    SymbolTableOffset: 0x54C
+# FILEHEADER64-NEXT:    SymbolTableEntries: 58
+# FILEHEADER64-NEXT:    OptionalHeaderSize: 0x0
+# FILEHEADER64-NEXT:    Flags: 0x0
+# FILEHEADER64-NEXT:  }
+
 # NEGTIME:     File: {{.*}}xcoff-basic-neg-time.o
 # NEGTIME-NEXT:  Format: aixcoff-rs6000
 # NEGTIME-NEXT:  Arch: powerpc

Added: llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test?rev=365524&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test Tue Jul  9 11:09:11 2019
@@ -0,0 +1,164 @@
+# RUN: llvm-readobj --section-headers %p/Inputs/xcoff-basic.o | \
+# RUN: FileCheck --check-prefix=SEC32 %s
+
+# RUN: llvm-readobj --section-headers %p/Inputs/xcoff-basic-64.o | \
+# RUN: FileCheck --check-prefix=SEC64 %s
+
+# SEC32:     File: {{.*}}xcoff-basic.o
+# SEC32-NEXT:  Format: aixcoff-rs6000
+# SEC32-NEXT:  Arch: powerpc
+# SEC32-NEXT:  AddressSize: 32bit
+# SEC32-NEXT:  Sections [
+# SEC32-NEXT:    Section {
+# SEC32-NEXT:      Index: 1
+# SEC32-NEXT:      Name: .text
+# SEC32-NEXT:      PhysicalAddress: 0x0
+# SEC32-NEXT:      VirtualAddress: 0x0
+# SEC32-NEXT:      Size: 0x100
+# SEC32-NEXT:      RawDataOffset: 0x200
+# SEC32-NEXT:      RelocationPointer: 0x3D8
+# SEC32-NEXT:      LineNumberPointer: 0x4E6
+# SEC32-NEXT:      NumberOfRelocations: 8
+# SEC32-NEXT:      NumberOfLineNumbers: 12
+# SEC32-NEXT:      Type: STYP_TEXT (0x20)
+# SEC32-NEXT:    }
+# SEC32-NEXT:    Section {
+# SEC32-NEXT:      Index: 2
+# SEC32-NEXT:      Name: .data
+# SEC32-NEXT:      PhysicalAddress: 0x100
+# SEC32-NEXT:      VirtualAddress: 0x100
+# SEC32-NEXT:      Size: 0x68
+# SEC32-NEXT:      RawDataOffset: 0x300
+# SEC32-NEXT:      RelocationPointer: 0x428
+# SEC32-NEXT:      LineNumberPointer: 0x0
+# SEC32-NEXT:      NumberOfRelocations: 19
+# SEC32-NEXT:      NumberOfLineNumbers: 0
+# SEC32-NEXT:      Type: STYP_DATA (0x40)
+# SEC32-NEXT:    }
+# SEC32-NEXT:    Section {
+# SEC32-NEXT:      Index: 3
+# SEC32-NEXT:      Name: .bss
+# SEC32-NEXT:      PhysicalAddress: 0x168
+# SEC32-NEXT:      VirtualAddress: 0x168
+# SEC32-NEXT:      Size: 0x4
+# SEC32-NEXT:      RawDataOffset: 0x0
+# SEC32-NEXT:      RelocationPointer: 0x0
+# SEC32-NEXT:      LineNumberPointer: 0x0
+# SEC32-NEXT:      NumberOfRelocations: 0
+# SEC32-NEXT:      NumberOfLineNumbers: 0
+# SEC32-NEXT:      Type: STYP_BSS (0x80)
+# SEC32-NEXT:    }
+# SEC32-NEXT:    Section {
+# SEC32-NEXT:      Index: 4
+# SEC32-NEXT:      Name: .tdata
+# SEC32-NEXT:      PhysicalAddress: 0x0
+# SEC32-NEXT:      VirtualAddress: 0x0
+# SEC32-NEXT:      Size: 0x4
+# SEC32-NEXT:      RawDataOffset: 0x368
+# SEC32-NEXT:      RelocationPointer: 0x47A
+# SEC32-NEXT:      LineNumberPointer: 0x0
+# SEC32-NEXT:      NumberOfRelocations: 0
+# SEC32-NEXT:      NumberOfLineNumbers: 0
+# SEC32-NEXT:      Type: STYP_TDATA (0x400)
+# SEC32-NEXT:    }
+# SEC32-NEXT:    Section {
+# SEC32-NEXT:      Index: 5
+# SEC32-NEXT:      Name: .tbss
+# SEC32-NEXT:      PhysicalAddress: 0x4
+# SEC32-NEXT:      VirtualAddress: 0x4
+# SEC32-NEXT:      Size: 0x8
+# SEC32-NEXT:      RawDataOffset: 0x0
+# SEC32-NEXT:      RelocationPointer: 0x0
+# SEC32-NEXT:      LineNumberPointer: 0x0
+# SEC32-NEXT:      NumberOfRelocations: 0
+# SEC32-NEXT:      NumberOfLineNumbers: 0
+# SEC32-NEXT:      Type: STYP_TBSS (0x800)
+# SEC32-NEXT:    }
+# SEC32-NEXT:    Section {
+# SEC32-NEXT:      Index: 6
+# SEC32-NEXT:      Name: .debug
+# SEC32-NEXT:      PhysicalAddress: 0x0
+# SEC32-NEXT:      VirtualAddress: 0x0
+# SEC32-NEXT:      Size: 0x6C
+# SEC32-NEXT:      RawDataOffset: 0x36C
+# SEC32-NEXT:      RelocationPointer: 0x0
+# SEC32-NEXT:      LineNumberPointer: 0x0
+# SEC32-NEXT:      NumberOfRelocations: 0
+# SEC32-NEXT:      NumberOfLineNumbers: 0
+# SEC32-NEXT:      Type: STYP_DEBUG (0x2000)
+# SEC32-NEXT:    }
+# SEC32-NEXT:  ]
+
+
+# SEC64:     File: {{.*}}xcoff-basic-64.o
+# SEC64-NEXT:  Format: aix5coff64-rs6000
+# SEC64-NEXT:  Arch: powerpc64
+# SEC64-NEXT:  AddressSize: 64bit
+# SEC64-NEXT:  Sections [
+# SEC64-NEXT:    Section {
+# SEC64-NEXT:      Index: 1
+# SEC64-NEXT:      Name: .text
+# SEC64-NEXT:      PhysicalAddress: 0x0
+# SEC64-NEXT:      VirtualAddress: 0x0
+# SEC64-NEXT:      Size: 0x100
+# SEC64-NEXT:      RawDataOffset: 0x200
+# SEC64-NEXT:      RelocationPointer: 0x3C4
+# SEC64-NEXT:      LineNumberPointer: 0x0
+# SEC64-NEXT:      NumberOfRelocations: 9
+# SEC64-NEXT:      NumberOfLineNumbers: 0
+# SEC64-NEXT:      Type: STYP_TEXT (0x20)
+# SEC64-NEXT:    }
+# SEC64-NEXT:    Section {
+# SEC64-NEXT:      Index: 2
+# SEC64-NEXT:      Name: .data
+# SEC64-NEXT:      PhysicalAddress: 0x100
+# SEC64-NEXT:      VirtualAddress: 0x100
+# SEC64-NEXT:      Size: 0xC0
+# SEC64-NEXT:      RawDataOffset: 0x300
+# SEC64-NEXT:      RelocationPointer: 0x442
+# SEC64-NEXT:      LineNumberPointer: 0x0
+# SEC64-NEXT:      NumberOfRelocations: 19
+# SEC64-NEXT:      NumberOfLineNumbers: 0
+# SEC64-NEXT:      Type: STYP_DATA (0x40)
+# SEC64-NEXT:    }
+# SEC64-NEXT:    Section {
+# SEC64-NEXT:      Index: 3
+# SEC64-NEXT:      Name: .bss
+# SEC64-NEXT:      PhysicalAddress: 0x1C0
+# SEC64-NEXT:      VirtualAddress: 0x1C0
+# SEC64-NEXT:      Size: 0x8
+# SEC64-NEXT:      RawDataOffset: 0x0
+# SEC64-NEXT:      RelocationPointer: 0x0
+# SEC64-NEXT:      LineNumberPointer: 0x0
+# SEC64-NEXT:      NumberOfRelocations: 0
+# SEC64-NEXT:      NumberOfLineNumbers: 0
+# SEC64-NEXT:      Type: STYP_BSS (0x80)
+# SEC64-NEXT:    }
+# SEC64-NEXT:    Section {
+# SEC64-NEXT:      Index: 4
+# SEC64-NEXT:      Name: .tdata
+# SEC64-NEXT:      PhysicalAddress: 0x0
+# SEC64-NEXT:      VirtualAddress: 0x0
+# SEC64-NEXT:      Size: 0x4
+# SEC64-NEXT:      RawDataOffset: 0x3C0
+# SEC64-NEXT:      RelocationPointer: 0x54C
+# SEC64-NEXT:      LineNumberPointer: 0x0
+# SEC64-NEXT:      NumberOfRelocations: 0
+# SEC64-NEXT:      NumberOfLineNumbers: 0
+# SEC64-NEXT:      Type: STYP_TDATA (0x400)
+# SEC64-NEXT:    }
+# SEC64-NEXT:    Section {
+# SEC64-NEXT:      Index: 5
+# SEC64-NEXT:      Name: .tbss
+# SEC64-NEXT:      PhysicalAddress: 0x4
+# SEC64-NEXT:      VirtualAddress: 0x4
+# SEC64-NEXT:      Size: 0x8
+# SEC64-NEXT:      RawDataOffset: 0x0
+# SEC64-NEXT:      RelocationPointer: 0x0
+# SEC64-NEXT:      LineNumberPointer: 0x0
+# SEC64-NEXT:      NumberOfRelocations: 0
+# SEC64-NEXT:      NumberOfLineNumbers: 0
+# SEC64-NEXT:      Type: STYP_TBSS (0x800)
+# SEC64-NEXT:    }
+# SEC64-NEXT:  ]
+

Modified: llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp Tue Jul  9 11:09:11 2019
@@ -36,7 +36,12 @@ public:
   void printNeededLibraries() override;
 
 private:
+  template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
+
   const XCOFFObjectFile &Obj;
+
+  // Least significant 3 bits are reserved.
+  static constexpr unsigned SectionFlagsReservedMask = 0x7;
 };
 } // anonymous namespace
 
@@ -65,12 +70,20 @@ void XCOFFDumper::printFileHeaders() {
                TimeStamp);
   }
 
-  W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset());
-  int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries();
-  if (SymTabEntries >= 0)
-    W.printNumber("SymbolTableEntries", SymTabEntries);
-  else
-    W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
+  // The number of symbol table entries is an unsigned value in 64-bit objects
+  // and a signed value (with negative values being 'reserved') in 32-bit
+  // objects.
+  if (Obj.is64Bit()) {
+    W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
+    W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
+  } else {
+    W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
+    int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
+    if (SymTabEntries >= 0)
+      W.printNumber("SymbolTableEntries", SymTabEntries);
+    else
+      W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
+  }
 
   W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
   W.printHex("Flags", Obj.getFlags());
@@ -80,7 +93,10 @@ void XCOFFDumper::printFileHeaders() {
 }
 
 void XCOFFDumper::printSectionHeaders() {
-  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+  if (Obj.is64Bit())
+    printSectionHeaders(Obj.sections64());
+  else
+    printSectionHeaders(Obj.sections32());
 }
 
 void XCOFFDumper::printRelocations() {
@@ -107,6 +123,59 @@ void XCOFFDumper::printNeededLibraries()
   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
 }
 
+static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
+#define ECase(X)                                                               \
+  { #X, XCOFF::X }
+    ECase(STYP_PAD),    ECase(STYP_DWARF), ECase(STYP_TEXT),
+    ECase(STYP_DATA),   ECase(STYP_BSS),   ECase(STYP_EXCEPT),
+    ECase(STYP_INFO),   ECase(STYP_TDATA), ECase(STYP_TBSS),
+    ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
+    ECase(STYP_OVRFLO)
+#undef ECase
+};
+
+template <typename T>
+void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
+  ListScope Group(W, "Sections");
+
+  uint16_t Index = 1;
+  for (const T &Sec : Sections) {
+    DictScope SecDS(W, "Section");
+
+    W.printNumber("Index", Index++);
+    W.printString("Name", Sec.getName());
+
+    W.printHex("PhysicalAddress", Sec.PhysicalAddress);
+    W.printHex("VirtualAddress", Sec.VirtualAddress);
+    W.printHex("Size", Sec.SectionSize);
+    W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
+    W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
+    W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
+
+    // TODO Need to add overflow handling when NumberOfX == _OVERFLOW_MARKER
+    // in 32-bit object files.
+    W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
+    W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
+
+    // The most significant 16-bits represent the DWARF section subtype. For
+    // now we just dump the section type flags.
+    uint16_t Flags = Sec.Flags & 0xffffu;
+    if (Flags & SectionFlagsReservedMask)
+      W.printHex("Flags", "Reserved", Flags);
+    else
+      W.printEnum("Type", Flags, makeArrayRef(SectionTypeFlagsNames));
+  }
+
+  if (opts::SectionRelocations)
+    report_fatal_error("Dumping section relocations is unimplemented");
+
+  if (opts::SectionSymbols)
+    report_fatal_error("Dumping symbols is unimplemented");
+
+  if (opts::SectionData)
+    report_fatal_error("Dumping section data is unimplemented");
+}
+
 namespace llvm {
 std::error_code createXCOFFDumper(const object::ObjectFile *Obj,
                                   ScopedPrinter &Writer,

Modified: llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp Tue Jul  9 11:09:11 2019
@@ -29,22 +29,25 @@ public:
 } // namespace
 
 std::error_code XCOFFDumper::dump() {
-  std::error_code EC;
   dumpHeader();
-  EC = dumpSymbols();
-  return EC;
+  return dumpSymbols();
 }
 
 void XCOFFDumper::dumpHeader() {
-  const XCOFFFileHeader *FileHdrPtr = Obj.getFileHeader();
 
-  YAMLObj.Header.Magic = FileHdrPtr->Magic;
-  YAMLObj.Header.NumberOfSections = FileHdrPtr->NumberOfSections;
-  YAMLObj.Header.TimeStamp = FileHdrPtr->TimeStamp;
-  YAMLObj.Header.SymbolTableOffset = FileHdrPtr->SymbolTableOffset;
-  YAMLObj.Header.NumberOfSymTableEntries = FileHdrPtr->NumberOfSymTableEntries;
-  YAMLObj.Header.AuxHeaderSize = FileHdrPtr->AuxHeaderSize;
-  YAMLObj.Header.Flags = FileHdrPtr->Flags;
+  YAMLObj.Header.Magic = Obj.getMagic();
+  YAMLObj.Header.NumberOfSections = Obj.getNumberOfSections();
+  YAMLObj.Header.TimeStamp = Obj.getTimeStamp();
+
+  // TODO FIXME only dump 32 bit header for now.
+  if (Obj.is64Bit())
+    report_fatal_error("64-bit XCOFF files not supported yet.");
+  YAMLObj.Header.SymbolTableOffset = Obj.getSymbolTableOffset32();
+
+  YAMLObj.Header.NumberOfSymTableEntries =
+      Obj.getRawNumberOfSymbolTableEntries32();
+  YAMLObj.Header.AuxHeaderSize = Obj.getOptionalHeaderSize();
+  YAMLObj.Header.Flags = Obj.getFlags();
 }
 
 std::error_code XCOFFDumper::dumpSymbols() {




More information about the llvm-commits mailing list