diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h index 32c0232f6e50..9c17559b40d7 100644 --- a/llvm/include/llvm/BinaryFormat/XCOFF.h +++ b/llvm/include/llvm/BinaryFormat/XCOFF.h @@ -13,11 +13,14 @@ #ifndef LLVM_BINARYFORMAT_XCOFF_H #define LLVM_BINARYFORMAT_XCOFF_H +#include + 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 diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h index 33a13bc2c101..d9f9d2724f15 100644 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -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 + 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 diff --git a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h index 078ab756695e..f99004e69762 100644 --- a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h +++ b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h @@ -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 +#include 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 Symbols; Object(); }; } // namespace XCOFFYAML - +} // namespace llvm +LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol) +namespace llvm { namespace yaml { +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, XCOFF::StorageClass &Value); +}; + template <> struct MappingTraits { static void mapping(IO &IO, XCOFFYAML::FileHeader &H); }; @@ -44,6 +61,10 @@ template <> struct MappingTraits { static void mapping(IO &IO, XCOFFYAML::Object &Obj); }; +template <> struct MappingTraits { + static void mapping(IO &IO, XCOFFYAML::Symbol &S); +}; + } // namespace yaml } // namespace llvm diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp index db57fbad0023..9a3e1783ab2c 100644 --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -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 @@ -43,6 +54,12 @@ template static const T *viewAs(uintptr_t in) { return reinterpret_cast(in); } +static StringRef generateStringRef(const char *Name, uint64_t Size) { + auto NulCharPtr = static_cast(memchr(Name, '\0', Size)); + return NulCharPtr ? StringRef(Name, NulCharPtr - Name) + : StringRef(Name, Size); +} + const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const { auto Sec = viewAs(Ref.p); #ifndef NDEBUG @@ -58,6 +75,12 @@ const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const { return Sec; } +const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const { + assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); + auto SymEntPtr = viewAs(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::getSectionHeaderSize() const { 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(SymEntPtr); } Expected 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("Symbol Name parse failed", + object_error::parse_failed); } Expected XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { @@ -87,9 +135,7 @@ Expected XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { } 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(DataRefImpl Symb) const { Expected 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(Sec); + + return section_iterator(SectionRef(SecDRI, this)); } void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { @@ -219,13 +277,16 @@ uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { } basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { - llvm_unreachable("Not yet implemented!"); - return basic_symbol_iterator(SymbolRef()); + DataRefImpl SymDRI; + SymDRI.p = reinterpret_cast(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( + SymbolTblPtr + getLogicalNumberOfSymbolTableEntries()); + return basic_symbol_iterator(SymbolRef(SymDRI, this)); } section_iterator XCOFFObjectFile::section_begin() const { @@ -243,7 +304,7 @@ section_iterator XCOFFObjectFile::section_end() const { 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 XCOFFObjectFile::getStartAddress() const { return 0; } +std::error_code +XCOFFObjectFile::getSectionByNum(int16_t Num, + const XCOFFSectionHeader *&Result) const { + if (Num > 0 && static_cast(Num) <= getNumberOfSections()) { + Result = SectionHdrTablePtr + (Num - 1); + return std::error_code(); + } + + return object_error::invalid_section_index; +} + +Expected +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(MemoryBufferRef Object, std::error_code &EC) 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); -uint16_t XCOFFObjectFile::getFlags() const { - return FileHdrPtr->Flags; + 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; + + StringTable.Data = reinterpret_cast(base() + CurPtr); + if (StringTable.Data[StringTable.Size - 1] != '\0') { + EC = object_error::string_table_non_null_end; + return; + } } Expected> diff --git a/llvm/lib/ObjectYAML/XCOFFYAML.cpp b/llvm/lib/ObjectYAML/XCOFFYAML.cpp index c3fe1bb868c5..982e6aecbb98 100644 --- a/llvm/lib/ObjectYAML/XCOFFYAML.cpp +++ b/llvm/lib/ObjectYAML/XCOFFYAML.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ObjectYAML/XCOFFYAML.h" +#include "llvm/BinaryFormat/XCOFF.h" #include namespace llvm { @@ -22,6 +23,62 @@ Object::Object() { memset(&Header, 0, sizeof(Header)); } namespace yaml { +void ScalarEnumerationTraits::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::mapping( IO &IO, XCOFFYAML::FileHeader &FileHdr) { IO.mapRequired("MagicNumber", FileHdr.Magic); @@ -33,9 +90,19 @@ void MappingTraits::mapping( IO.mapRequired("Flags", FileHdr.Flags); } +void MappingTraits::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::mapping(IO &IO, XCOFFYAML::Object &Obj) { IO.mapTag("!XCOFF", true); IO.mapRequired("FileHeader", Obj.Header); + IO.mapRequired("Symbols", Obj.Symbols); } } // namespace yaml diff --git a/llvm/test/tools/obj2yaml/Inputs/aix_xcoff.o b/llvm/test/tools/obj2yaml/Inputs/aix_xcoff.o index 3712f7f853e5..84383c4ce24c 100644 Binary files a/llvm/test/tools/obj2yaml/Inputs/aix_xcoff.o and b/llvm/test/tools/obj2yaml/Inputs/aix_xcoff.o differ diff --git a/llvm/test/tools/obj2yaml/aix_xcoff.test b/llvm/test/tools/obj2yaml/aix_xcoff.test index 1ad89e9c5d3c..b3e60dfd0580 100644 --- a/llvm/test/tools/obj2yaml/aix_xcoff.test +++ b/llvm/test/tools/obj2yaml/aix_xcoff.test @@ -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: ... diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp index 009b99c1f7bf..59293fe80eed 100644 --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -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 diff --git a/llvm/tools/obj2yaml/xcoff2yaml.cpp b/llvm/tools/obj2yaml/xcoff2yaml.cpp index 5ee9eafbcbef..bcacd2b8d551 100644 --- a/llvm/tools/obj2yaml/xcoff2yaml.cpp +++ b/llvm/tools/obj2yaml/xcoff2yaml.cpp @@ -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 &Symbols = YAMLObj.Symbols; + + for (const SymbolRef &S : Obj.symbols()) { + DataRefImpl SymbolDRI = S.getRawDataRefImpl(); + const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI); + XCOFFYAML::Symbol Sym; + + Expected SymNameRefOrErr = Obj.getSymbolName(SymbolDRI); + if (!SymNameRefOrErr) { + return errorToErrorCode(SymNameRefOrErr.takeError()); + } + Sym.SymbolName = SymNameRefOrErr.get(); + + Sym.Value = SymbolEntPtr->Value; + + Expected 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();