[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

llvm-svn: 361832
This commit is contained in:
Jason Liu 2019-05-28 14:37:59 +00:00
parent 71f8f745b4
commit 9212206d25
9 changed files with 500 additions and 59 deletions

View File

@ -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

View File

@ -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

View File

@ -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<XCOFFYAML::Object> {
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

View File

@ -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 *viewAs(uintptr_t in) {
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 *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<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::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<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::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<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(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<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::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<uint64_t> XCOFFObjectFile::getStartAddress() const {
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(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<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>>

View File

@ -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, sizeof(Header)); }
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>::mapping(
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

View File

@ -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: ...

View File

@ -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

View File

@ -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();