[llvm] r361832 - [XCOFF] Implement parsing symbol table for xcoffobjfile and output as yaml format

Jason Liu via llvm-commits llvm-commits at lists.llvm.org
Tue May 28 07:37:59 PDT 2019


Author: jasonliu
Date: Tue May 28 07:37:59 2019
New Revision: 361832

URL: http://llvm.org/viewvc/llvm-project?rev=361832&view=rev
Log:
[XCOFF] Implement parsing symbol table for xcoffobjfile and output as yaml format

Summary:
This patch implement parsing symbol table for xcoffobjfile and
output as yaml format. Parsing auxiliary entries of a symbol
will be in a separate patch.

The XCOFF object file (aix_xcoff.o) used in the test comes from
-bash-4.2$ cat test.c
extern int i;
extern int TestforXcoff;
int main()
{
i++;
TestforXcoff--;
}

Patch by DiggerLin

Reviewers: sfertile, hubert.reinterpretcast, MaskRay, daltenty

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

Modified:
    llvm/trunk/include/llvm/BinaryFormat/XCOFF.h
    llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
    llvm/trunk/include/llvm/ObjectYAML/XCOFFYAML.h
    llvm/trunk/lib/Object/XCOFFObjectFile.cpp
    llvm/trunk/lib/ObjectYAML/XCOFFYAML.cpp
    llvm/trunk/test/tools/obj2yaml/Inputs/aix_xcoff.o
    llvm/trunk/test/tools/obj2yaml/aix_xcoff.test
    llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp
    llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp

Modified: llvm/trunk/include/llvm/BinaryFormat/XCOFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/XCOFF.h?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/XCOFF.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/XCOFF.h Tue May 28 07:37:59 2019
@@ -13,11 +13,14 @@
 #ifndef LLVM_BINARYFORMAT_XCOFF_H
 #define LLVM_BINARYFORMAT_XCOFF_H
 
+#include <cstdint>
+
 namespace llvm {
 namespace XCOFF {
 
 // Constants used in the XCOFF definition.
-enum { SectionNameSize = 8 };
+enum { SectionNameSize = 8, SymbolNameSize = 8 };
+enum ReservedSectionNum { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 };
 
 // Flags for defining the section type. Used for the s_flags field of
 // the section header structure. Defined in the system header `scnhdr.h`.
@@ -37,6 +40,75 @@ enum SectionTypeFlags {
   STYP_OVRFLO = 0x8000
 };
 
+// STORAGE CLASSES, n_sclass field of syment.
+// The values come from `storclass.h` and `dbxstclass.h`.
+enum StorageClass : uint8_t {
+  // Storage classes used for symbolic debugging symbols.
+  C_FILE = 103,  // File name
+  C_BINCL = 108, // Beginning of include file
+  C_EINCL = 109, // Ending of include file
+  C_GSYM = 128,  // Global variable
+  C_STSYM = 133, // Statically allocated symbol
+  C_BCOMM = 135, // Beginning of common block
+  C_ECOMM = 137, // End of common block
+  C_ENTRY = 141, // Alternate entry
+  C_BSTAT = 143, // Beginning of static block
+  C_ESTAT = 144, // End of static block
+  C_GTLS = 145,  // Global thread-local variable
+  C_STTLS = 146, // Static thread-local variable
+
+  // Storage classes used for DWARF symbols.
+  C_DWARF = 112, // DWARF section symbol
+
+  // Storage classes used for absolute symbols.
+  C_LSYM = 129,  // Automatic variable allocated on stack
+  C_PSYM = 130,  // Argument to subroutine allocated on stack
+  C_RSYM = 131,  // Register variable
+  C_RPSYM = 132, // Argument to function or procedure stored in register
+  C_ECOML = 136, // Local member of common block
+  C_FUN = 142,   // Function or procedure
+
+  // Storage classes used for undefined external symbols or
+  // symbols of general sections.
+  C_EXT = 2,       // External symbol
+  C_WEAKEXT = 111, // Weak external symbol
+
+  // Storage classes used for symbols of general sections.
+  C_NULL = 0,
+  C_STAT = 3,     // Static
+  C_BLOCK = 100,  // ".bb" or ".eb"
+  C_FCN = 101,    // ".bf" or ".ef"
+  C_HIDEXT = 107, // Un-named external symbol
+  C_INFO = 110,   // Comment string in .info section
+  C_DECL = 140,   // Declaration of object (type)
+
+  // Storage classes - Obsolete/Undocumented.
+  C_AUTO = 1,     // Automatic variable
+  C_REG = 4,      // Register variable
+  C_EXTDEF = 5,   // External definition
+  C_LABEL = 6,    // Label
+  C_ULABEL = 7,   // Undefined label
+  C_MOS = 8,      // Member of structure
+  C_ARG = 9,      // Function argument
+  C_STRTAG = 10,  // Structure tag
+  C_MOU = 11,     // Member of union
+  C_UNTAG = 12,   // Union tag
+  C_TPDEF = 13,   // Type definition
+  C_USTATIC = 14, // Undefined static
+  C_ENTAG = 15,   // Enumeration tag
+  C_MOE = 16,     // Member of enumeration
+  C_REGPARM = 17, // Register parameter
+  C_FIELD = 18,   // Bit field
+  C_EOS = 102,    // End of structure
+  C_LINE = 104,
+  C_ALIAS = 105,  // Duplicate tag
+  C_HIDDEN = 106, // Special storage class for external
+  C_EFCN = 255,   // Physical end of function
+
+  // Storage classes - reserved
+  C_TCSYM = 134 // Reserved
+};
+
 } // end namespace XCOFF
 } // end namespace llvm
 

Modified: llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/XCOFFObjectFile.h?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/XCOFFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/XCOFFObjectFile.h Tue May 28 07:37:59 2019
@@ -61,16 +61,54 @@ struct XCOFFSectionHeader {
   support::big32_t Flags;
 };
 
+struct XCOFFSymbolEntry {
+  enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
+  typedef struct {
+    support::big32_t Magic; // Zero indicates name in string table.
+    support::ubig32_t Offset;
+  } NameInStrTblType;
+
+  typedef struct {
+    uint8_t LanguageId;
+    uint8_t CpuTypeId;
+  } CFileLanguageIdAndTypeIdType;
+
+  union {
+    char SymbolName[XCOFF::SymbolNameSize];
+    NameInStrTblType NameInStrTbl;
+  };
+
+  support::ubig32_t Value; // Symbol value; storage class-dependent.
+  support::big16_t SectionNumber;
+
+  union {
+    support::ubig16_t SymbolType;
+    CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
+  };
+
+  XCOFF::StorageClass StorageClass;
+  uint8_t NumberOfAuxEntries;
+};
+
+struct XCOFFStringTable {
+  uint32_t Size;
+  const char *Data;
+};
+
 class XCOFFObjectFile : public ObjectFile {
 private:
   const XCOFFFileHeader *FileHdrPtr = nullptr;
   const XCOFFSectionHeader *SectionHdrTablePtr = nullptr;
+  const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
+  XCOFFStringTable StringTable = {0, nullptr};
 
   size_t getFileHeaderSize() const;
   size_t getSectionHeaderSize() const;
 
   const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
-
+  static bool isReservedSectionNumber(int16_t SectionNumber);
+  std::error_code getSectionByNum(int16_t Num,
+                                  const XCOFFSectionHeader *&Result) const;
 
 public:
   void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -121,18 +159,27 @@ public:
   XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
 
   const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
+  const XCOFFSymbolEntry *getPointerToSymbolTable() const {
+    return SymbolTblPtr;
+  }
+
+  Expected<StringRef>
+  getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
 
+  const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
   uint16_t getMagic() const;
   uint16_t getNumberOfSections() const;
-  int32_t  getTimeStamp() const;
-  uint32_t  getSymbolTableOffset() const;
+  int32_t getTimeStamp() const;
+  uint32_t getSymbolTableOffset() const;
 
-  // Note that this value is signed and might return a negative value. Negative
-  // values are reserved for future use.
-  int32_t  getNumberOfSymbolTableEntries() const;
+  // Returns the value as encoded in the object file.
+  // Negative values are reserved for future use.
+  int32_t getRawNumberOfSymbolTableEntries() 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;
+  uint16_t getFlags() const { return FileHdrPtr->Flags; };
 }; // XCOFFObjectFile
 
 } // namespace object

Modified: llvm/trunk/include/llvm/ObjectYAML/XCOFFYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/XCOFFYAML.h?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/XCOFFYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/XCOFFYAML.h Tue May 28 07:37:59 2019
@@ -12,8 +12,9 @@
 #ifndef LLVM_OBJECTYAML_XCOFFYAML_H
 #define LLVM_OBJECTYAML_XCOFFYAML_H
 
+#include "llvm/BinaryFormat/XCOFF.h"
 #include "llvm/ObjectYAML/YAML.h"
-#include <cstdint>
+#include <vector>
 
 namespace llvm {
 namespace XCOFFYAML {
@@ -28,14 +29,30 @@ struct FileHeader {
   llvm::yaml::Hex16 Flags;
 };
 
+struct Symbol {
+  StringRef SymbolName;
+  llvm::yaml::Hex32 Value; // Symbol value; storage class-dependent.
+  StringRef SectionName;
+  llvm::yaml::Hex16 Type;
+  XCOFF::StorageClass StorageClass;
+  uint8_t NumberOfAuxEntries; // Number of auxiliary entries
+};
+
 struct Object {
   FileHeader Header;
+  std::vector<Symbol> Symbols;
   Object();
 };
 } // namespace XCOFFYAML
-
+} // namespace llvm
+LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol)
+namespace llvm {
 namespace yaml {
 
+template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> {
+  static void enumeration(IO &IO, XCOFF::StorageClass &Value);
+};
+
 template <> struct MappingTraits<XCOFFYAML::FileHeader> {
   static void mapping(IO &IO, XCOFFYAML::FileHeader &H);
 };
@@ -44,6 +61,10 @@ template <> struct MappingTraits<XCOFFYA
   static void mapping(IO &IO, XCOFFYAML::Object &Obj);
 };
 
+template <> struct MappingTraits<XCOFFYAML::Symbol> {
+  static void mapping(IO &IO, XCOFFYAML::Symbol &S);
+};
+
 } // namespace yaml
 } // namespace llvm
 

Modified: llvm/trunk/lib/Object/XCOFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/XCOFFObjectFile.cpp?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/lib/Object/XCOFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/XCOFFObjectFile.cpp Tue May 28 07:37:59 2019
@@ -26,6 +26,17 @@ 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.
 template <typename T>
@@ -43,6 +54,12 @@ template <typename T> static const T *vi
   return reinterpret_cast<const T *>(in);
 }
 
+static StringRef generateStringRef(const char *Name, uint64_t Size) {
+  auto NulCharPtr = static_cast<const char *>(memchr(Name, '\0', Size));
+  return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
+                    : StringRef(Name, Size);
+}
+
 const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
   auto Sec = viewAs<XCOFFSectionHeader>(Ref.p);
 #ifndef NDEBUG
@@ -58,6 +75,12 @@ const XCOFFSectionHeader *XCOFFObjectFil
   return Sec;
 }
 
+const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
+  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.
@@ -69,15 +92,40 @@ size_t XCOFFObjectFile::getSectionHeader
   return sizeof(XCOFFSectionHeader);
 }
 
+uint16_t XCOFFObjectFile::getMagic() const { return FileHdrPtr->Magic; }
+
 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
-  llvm_unreachable("Not yet implemented!");
-  return;
+  const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
+
+  SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
+  Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
 }
 
 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
-  StringRef Result;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
+
+  if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
+    return generateStringRef(SymEntPtr->SymbolName, XCOFF::SymbolNameSize);
+
+  // A storage class value with the high-order bit on indicates that the name is
+  // a symbolic debugger stabstring.
+  if (SymEntPtr->StorageClass & 0x80)
+    return StringRef("Unimplemented Debug Name");
+
+  uint32_t Offset = SymEntPtr->NameInStrTbl.Offset;
+  // The byte offset is relative to the start of the string table
+  // or .debug section. A byte offset value of 0 is a null or zero-length symbol
+  // name. A byte offset in the range 1 to 3 (inclusive) points into the length
+  // field; as a soft-error recovery mechanism, we treat such cases as having an
+  // offset of 0.
+  if (Offset < 4)
+    return StringRef(nullptr, 0);
+
+  if (StringTable.Data != nullptr && StringTable.Size > Offset)
+    return (StringTable.Data + Offset);
+
+  return make_error<GenericBinaryError>("Symbol Name parse failed",
+                                        object_error::parse_failed);
 }
 
 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
@@ -87,9 +135,7 @@ Expected<uint64_t> XCOFFObjectFile::getS
 }
 
 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
-  uint64_t Result = 0;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  return toSymbolEntry(Symb)->Value;
 }
 
 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
@@ -106,8 +152,20 @@ XCOFFObjectFile::getSymbolType(DataRefIm
 
 Expected<section_iterator>
 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
-  llvm_unreachable("Not yet implemented!");
-  return section_iterator(SectionRef());
+  const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
+  int16_t SectNum = SymEntPtr->SectionNumber;
+
+  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);
+
+  return section_iterator(SectionRef(SecDRI, this));
 }
 
 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
@@ -219,13 +277,16 @@ uint32_t XCOFFObjectFile::getSymbolFlags
 }
 
 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
-  llvm_unreachable("Not yet implemented!");
-  return basic_symbol_iterator(SymbolRef());
+  DataRefImpl SymDRI;
+  SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
+  return basic_symbol_iterator(SymbolRef(SymDRI, this));
 }
 
 basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
-  llvm_unreachable("Not yet implemented!");
-  return basic_symbol_iterator(SymbolRef());
+  DataRefImpl SymDRI;
+  SymDRI.p = reinterpret_cast<uintptr_t>(
+      SymbolTblPtr + getLogicalNumberOfSymbolTableEntries());
+  return basic_symbol_iterator(SymbolRef(SymDRI, this));
 }
 
 section_iterator XCOFFObjectFile::section_begin() const {
@@ -243,7 +304,7 @@ section_iterator XCOFFObjectFile::sectio
 
 uint8_t XCOFFObjectFile::getBytesInAddress() const {
   // Only support 32-bit object files for now ...
-  assert(getFileHeaderSize() ==  XCOFF32FileHeaderSize);
+  assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
   return 4;
 }
 
@@ -274,6 +335,67 @@ 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();
+  }
+
+  return object_error::invalid_section_index;
+}
+
+Expected<StringRef>
+XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
+  int16_t SectionNum = SymEntPtr->SectionNumber;
+
+  switch (SectionNum) {
+  case XCOFF::N_DEBUG:
+    return "N_DEBUG";
+  case XCOFF::N_ABS:
+    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);
+  }
+  }
+}
+
+bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) {
+  return (SectionNumber <= 0 && SectionNumber >= -2);
+}
+
+uint16_t XCOFFObjectFile::getNumberOfSections() const {
+  return FileHdrPtr->NumberOfSections;
+}
+
+int32_t XCOFFObjectFile::getTimeStamp() const { return FileHdrPtr->TimeStamp; }
+
+uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
+  return FileHdrPtr->SymbolTableOffset;
+}
+
+int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries() const {
+  return FileHdrPtr->NumberOfSymTableEntries;
+}
+
+uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries() const {
+  return (FileHdrPtr->NumberOfSymTableEntries >= 0
+              ? FileHdrPtr->NumberOfSymTableEntries
+              : 0);
+}
+
+uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
+  return FileHdrPtr->AuxHeaderSize;
+}
+
 XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
     : ObjectFile(Binary::ID_XCOFF32, Object) {
 
@@ -293,37 +415,39 @@ XCOFFObjectFile::XCOFFObjectFile(MemoryB
                         getNumberOfSections() * getSectionHeaderSize())))
       return;
   }
-}
 
-uint16_t XCOFFObjectFile::getMagic() const {
-  return FileHdrPtr->Magic;
-}
+  if (getLogicalNumberOfSymbolTableEntries() == 0)
+    return;
 
-uint16_t XCOFFObjectFile::getNumberOfSections() const {
-  return FileHdrPtr->NumberOfSections;
-}
+  // Get pointer to the symbol table.
+  CurPtr = FileHdrPtr->SymbolTableOffset;
+  uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
+                             getLogicalNumberOfSymbolTableEntries();
 
-int32_t XCOFFObjectFile::getTimeStamp() const {
-  return FileHdrPtr->TimeStamp;
-}
+  if ((EC = getObject(SymbolTblPtr, Data, base() + CurPtr, SymbolTableSize)))
+    return;
 
-uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
-  return FileHdrPtr->SymbolTableOffset;
-}
+  // Move pointer to the string table.
+  CurPtr += SymbolTableSize;
 
-int32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() 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 FileHdrPtr->NumberOfSymTableEntries;
-}
+  if (CurPtr + 4 > Data.getBufferSize())
+    return;
 
-uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
-  return FileHdrPtr->AuxHeaderSize;
-}
+  StringTable.Size = support::endian::read32be(base() + CurPtr);
+
+  if (StringTable.Size <= 4)
+    return;
+
+  // Check for whether the String table has the size indicated by length
+  // field
+  if (!checkSize(Data, EC, CurPtr, StringTable.Size))
+    return;
 
-uint16_t XCOFFObjectFile::getFlags() const {
-  return FileHdrPtr->Flags;
+  StringTable.Data = reinterpret_cast<const char *>(base() + CurPtr);
+  if (StringTable.Data[StringTable.Size - 1] != '\0') {
+    EC = object_error::string_table_non_null_end;
+    return;
+  }
 }
 
 Expected<std::unique_ptr<ObjectFile>>

Modified: llvm/trunk/lib/ObjectYAML/XCOFFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/XCOFFYAML.cpp?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/XCOFFYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/XCOFFYAML.cpp Tue May 28 07:37:59 2019
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ObjectYAML/XCOFFYAML.h"
+#include "llvm/BinaryFormat/XCOFF.h"
 #include <string.h>
 
 namespace llvm {
@@ -22,6 +23,62 @@ Object::Object() { memset(&Header, 0, si
 
 namespace yaml {
 
+void ScalarEnumerationTraits<XCOFF::StorageClass>::enumeration(
+    IO &IO, XCOFF::StorageClass &Value) {
+#define ECase(X) IO.enumCase(Value, #X, XCOFF::X)
+  ECase(C_NULL);
+  ECase(C_AUTO);
+  ECase(C_EXT);
+  ECase(C_STAT);
+  ECase(C_REG);
+  ECase(C_EXTDEF);
+  ECase(C_LABEL);
+  ECase(C_ULABEL);
+  ECase(C_MOS);
+  ECase(C_ARG);
+  ECase(C_STRTAG);
+  ECase(C_MOU);
+  ECase(C_UNTAG);
+  ECase(C_TPDEF);
+  ECase(C_USTATIC);
+  ECase(C_ENTAG);
+  ECase(C_MOE);
+  ECase(C_REGPARM);
+  ECase(C_FIELD);
+  ECase(C_BLOCK);
+  ECase(C_FCN);
+  ECase(C_EOS);
+  ECase(C_FILE);
+  ECase(C_LINE);
+  ECase(C_ALIAS);
+  ECase(C_HIDDEN);
+  ECase(C_HIDEXT);
+  ECase(C_BINCL);
+  ECase(C_EINCL);
+  ECase(C_INFO);
+  ECase(C_WEAKEXT);
+  ECase(C_DWARF);
+  ECase(C_GSYM);
+  ECase(C_LSYM);
+  ECase(C_PSYM);
+  ECase(C_RSYM);
+  ECase(C_RPSYM);
+  ECase(C_STSYM);
+  ECase(C_TCSYM);
+  ECase(C_BCOMM);
+  ECase(C_ECOML);
+  ECase(C_ECOMM);
+  ECase(C_DECL);
+  ECase(C_ENTRY);
+  ECase(C_FUN);
+  ECase(C_BSTAT);
+  ECase(C_ESTAT);
+  ECase(C_GTLS);
+  ECase(C_STTLS);
+  ECase(C_EFCN);
+#undef ECase
+}
+
 void MappingTraits<XCOFFYAML::FileHeader>::mapping(
     IO &IO, XCOFFYAML::FileHeader &FileHdr) {
   IO.mapRequired("MagicNumber", FileHdr.Magic);
@@ -33,9 +90,19 @@ void MappingTraits<XCOFFYAML::FileHeader
   IO.mapRequired("Flags", FileHdr.Flags);
 }
 
+void MappingTraits<XCOFFYAML::Symbol>::mapping(IO &IO, XCOFFYAML::Symbol &S) {
+  IO.mapRequired("Name", S.SymbolName);
+  IO.mapRequired("Value", S.Value);
+  IO.mapRequired("Section", S.SectionName);
+  IO.mapRequired("Type", S.Type);
+  IO.mapRequired("StorageClass", S.StorageClass);
+  IO.mapRequired("NumberOfAuxEntries", S.NumberOfAuxEntries);
+}
+
 void MappingTraits<XCOFFYAML::Object>::mapping(IO &IO, XCOFFYAML::Object &Obj) {
   IO.mapTag("!XCOFF", true);
   IO.mapRequired("FileHeader", Obj.Header);
+  IO.mapRequired("Symbols", Obj.Symbols);
 }
 
 } // namespace yaml

Modified: llvm/trunk/test/tools/obj2yaml/Inputs/aix_xcoff.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/obj2yaml/Inputs/aix_xcoff.o?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
Binary files - no diff available.

Modified: llvm/trunk/test/tools/obj2yaml/aix_xcoff.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/obj2yaml/aix_xcoff.test?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/test/tools/obj2yaml/aix_xcoff.test (original)
+++ llvm/trunk/test/tools/obj2yaml/aix_xcoff.test Tue May 28 07:37:59 2019
@@ -2,10 +2,79 @@
 # Test that we can parse the XCOFF object file correctly.
 # CHECK: --- !XCOFF
 # CHECK-NEXT: FileHeader:
-# CHECK-NEXT: MagicNumber:     0x01DF
-# CHECK-NEXT: NumberOfSections: 2
-# CHECK-NEXT: CreationTime:    1548692020
-# CHECK-NEXT: OffsetToSymbolTable: 0x00000108
-# CHECK-NEXT: EntriesInSymbolTable: 18
-# CHECK-NEXT: AuxiliaryHeaderSize: 0
-# CHECK-NEXT: Flags:           0x0000
+# CHECK-NEXT:   MagicNumber:     0x01DF
+# CHECK-NEXT:   NumberOfSections: 2
+# CHECK-NEXT:   CreationTime:    1552337792
+# CHECK-NEXT:   OffsetToSymbolTable: 0x0000013A
+# CHECK-NEXT:   EntriesInSymbolTable: 22
+# CHECK-NEXT:   AuxiliaryHeaderSize: 0
+# CHECK-NEXT:   Flags:           0x0000
+
+# CHECK: Symbols:
+# CHECK-NEXT:   - Name:      .file
+# CHECK-NEXT:     Value:     0x00000000
+# CHECK-NEXT:     Section: N_DEBUG
+# CHECK-NEXT:     Type:      0x0003
+# CHECK-NEXT:     StorageClass:    C_FILE
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      i
+# CHECK-NEXT:     Value:     0x00000000
+# CHECK-NEXT:     Section: N_UNDEF
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_EXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      TestforXcoff
+# CHECK-NEXT:     Value:     0x00000000
+# CHECK-NEXT:     Section: N_UNDEF
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_EXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      .text
+# CHECK-NEXT:     Value:     0x00000000
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_HIDEXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      .main
+# CHECK-NEXT:     Value:     0x00000000
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_EXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      main
+# CHECK-NEXT:     Value:     0x00000060
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_HIDEXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      main
+# CHECK-NEXT:     Value:     0x00000060
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_EXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      .data
+# CHECK-NEXT:     Value:     0x00000070
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_HIDEXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      TOC
+# CHECK-NEXT:     Value:     0x00000074
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_HIDEXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      i
+# CHECK-NEXT:     Value:     0x00000074
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_HIDEXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT:   - Name:      TestforXcoff
+# CHECK-NEXT:     Value:     0x00000078
+# CHECK-NEXT:     Section: .data
+# CHECK-NEXT:     Type:      0x0000
+# CHECK-NEXT:     StorageClass:    C_HIDEXT
+# CHECK-NEXT:     NumberOfAuxEntries: 1
+# CHECK-NEXT: ...

Modified: llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp Tue May 28 07:37:59 2019
@@ -66,7 +66,7 @@ void XCOFFDumper::printFileHeaders() {
   }
 
   W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset());
-  int32_t SymTabEntries = Obj.getNumberOfSymbolTableEntries();
+  int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries();
   if (SymTabEntries >= 0)
     W.printNumber("SymbolTableEntries", SymTabEntries);
   else

Modified: llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp?rev=361832&r1=361831&r2=361832&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp Tue May 28 07:37:59 2019
@@ -19,15 +19,20 @@ class XCOFFDumper {
   const object::XCOFFObjectFile &Obj;
   XCOFFYAML::Object YAMLObj;
   void dumpHeader();
+  std::error_code dumpSymbols();
 
 public:
-  XCOFFDumper(const object::XCOFFObjectFile &obj);
+  XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {}
+  std::error_code dump();
   XCOFFYAML::Object &getYAMLObj() { return YAMLObj; }
 };
 } // namespace
 
-XCOFFDumper::XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {
+std::error_code XCOFFDumper::dump() {
+  std::error_code EC;
   dumpHeader();
+  EC = dumpSymbols();
+  return EC;
 }
 
 void XCOFFDumper::dumpHeader() {
@@ -42,9 +47,45 @@ void XCOFFDumper::dumpHeader() {
   YAMLObj.Header.Flags = FileHdrPtr->Flags;
 }
 
+std::error_code XCOFFDumper::dumpSymbols() {
+  std::vector<XCOFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
+
+  for (const SymbolRef &S : Obj.symbols()) {
+    DataRefImpl SymbolDRI = S.getRawDataRefImpl();
+    const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
+    XCOFFYAML::Symbol Sym;
+
+    Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI);
+    if (!SymNameRefOrErr) {
+      return errorToErrorCode(SymNameRefOrErr.takeError());
+    }
+    Sym.SymbolName = SymNameRefOrErr.get();
+
+    Sym.Value = SymbolEntPtr->Value;
+
+    Expected<StringRef> SectionNameRefOrErr =
+        Obj.getSymbolSectionName(SymbolEntPtr);
+    if (!SectionNameRefOrErr)
+      return errorToErrorCode(SectionNameRefOrErr.takeError());
+
+    Sym.SectionName = SectionNameRefOrErr.get();
+
+    Sym.Type = SymbolEntPtr->SymbolType;
+    Sym.StorageClass = SymbolEntPtr->StorageClass;
+    Sym.NumberOfAuxEntries = SymbolEntPtr->NumberOfAuxEntries;
+    Symbols.push_back(Sym);
+  }
+
+  return std::error_code();
+}
+
 std::error_code xcoff2yaml(raw_ostream &Out,
                            const object::XCOFFObjectFile &Obj) {
   XCOFFDumper Dumper(Obj);
+
+  if (std::error_code EC = Dumper.dump())
+    return EC;
+
   yaml::Output Yout(Out);
   Yout << Dumper.getYAMLObj();
 




More information about the llvm-commits mailing list