[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

llvm-svn: 365524
This commit is contained in:
Sean Fertile 2019-07-09 18:09:11 +00:00
parent 5f4d7c9d4f
commit 837ae69f8b
14 changed files with 638 additions and 192 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -66,6 +66,8 @@ file_magic llvm::identify_magic(StringRef Magic) {
// 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

View File

@ -70,6 +70,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
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:

View File

@ -150,7 +150,9 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
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);
}

View File

@ -70,6 +70,7 @@ SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type,
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:

View File

@ -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 char *Name, uint64_t Size) {
: 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(DataRefImpl Symb) const {
if (isReservedSectionNumber(SectNum))
return section_end();
const XCOFFSectionHeader *Sec;
if (std::error_code EC = getSectionByNum(SectNum, Sec))
return errorCodeToError(EC);
Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
if (!ExpSec)
return ExpSec.takeError();
DataRefImpl SecDRI;
SecDRI.p = reinterpret_cast<uintptr_t>(Sec);
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(DataRefImpl &Sec) const {
}
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::isSectionCompressed(DataRefImpl Sec) const {
}
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(DataRefImpl Symb) const {
}
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::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();
}
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(const XCOFFSymbolEntry *SymEntPtr) const {
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::isReservedSectionNumber(int16_t SectionNumber) {
}
uint16_t XCOFFObjectFile::getNumberOfSections() const {
return FileHdrPtr->NumberOfSections;
return is64Bit() ? fileHeader64()->NumberOfSections
: fileHeader32()->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);
int32_t XCOFFObjectFile::getTimeStamp() const {
return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
}
uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
return FileHdrPtr->AuxHeaderSize;
return is64Bit() ? fileHeader64()->AuxHeaderSize
: fileHeader32()->AuxHeaderSize;
}
XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
: ObjectFile(Binary::ID_XCOFF32, Object) {
uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
return fileHeader32()->SymbolTableOffset;
}
// Current location within the file.
uint64_t CurPtr = 0;
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;
}
if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr)))
return;
uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
return (fileHeader32()->NumberOfSymTableEntries >= 0
? fileHeader32()->NumberOfSymTableEntries
: 0);
}
CurPtr += getFileHeaderSize();
uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
return fileHeader64()->SymbolTableOffset;
}
uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
return fileHeader64()->NumberOfSymTableEntries;
}
uint16_t XCOFFObjectFile::getFlags() const {
return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
}
const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
}
uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
return reinterpret_cast<uintptr_t>(SectionHeaderTable);
}
int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
}
XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
: ObjectFile(Type, Object) {
assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
}
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());
}
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);
// 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};
auto StringTableOrErr =
getObject<char>(Obj->Data, Obj->base() + Offset, Size);
if (Error E = StringTableOrErr.takeError())
return std::move(E);
const char *StringTablePtr = StringTableOrErr.get();
if (StringTablePtr[Size - 1] != '\0')
return errorCodeToError(object_error::string_table_non_null_end);
return XCOFFStringTable{Size, StringTablePtr};
}
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));
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.
CurPtr += FileHdrPtr->AuxHeaderSize;
CurOffset += Obj->getOptionalHeaderSize();
if (getNumberOfSections() != 0) {
if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr,
getNumberOfSections() * getSectionHeaderSize())))
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();
}
if (getLogicalNumberOfSymbolTableEntries() == 0)
return;
// 64-bit object supports only file header and section headers for now.
if (Obj->is64Bit())
return std::move(Obj);
// Get pointer to the symbol table.
CurPtr = FileHdrPtr->SymbolTableOffset;
// 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)) *
getLogicalNumberOfSymbolTableEntries();
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;
if ((EC = getObject(SymbolTblPtr, Data, base() + CurPtr, SymbolTableSize)))
return;
// Parse String table.
Expected<XCOFFStringTable> StringTableOrErr =
parseStringTable(Obj.get(), CurOffset);
if (Error E = StringTableOrErr.takeError())
return std::move(E);
Obj->StringTable = StringTableOrErr.get();
// Move pointer to the string table.
CurPtr += SymbolTableSize;
if (CurPtr + 4 > Data.getBufferSize())
return;
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;
StringTable.Data = reinterpret_cast<const char *>(base() + CurPtr);
if (StringTable.Data[StringTable.Size - 1] != '\0') {
EC = object_error::string_table_non_null_end;
return;
}
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;
ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
unsigned FileType) {
return XCOFFObjectFile::create(FileType, MemBufRef);
}
if (Type == file_magic::xcoff_object_32) {
Ret.reset(new XCOFFObjectFile(Object, EC));
} else {
llvm_unreachable("Encountered an unexpected binary file type!");
}
StringRef XCOFFSectionHeader32::getName() const {
return generateStringRef(Name, XCOFF::SectionNameSize);
}
if (EC)
return errorCodeToError(EC);
return std::move(Ret);
StringRef XCOFFSectionHeader64::getName() const {
return generateStringRef(Name, XCOFF::SectionNameSize);
}
} // namespace object

Binary file not shown.

View File

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

View File

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

View File

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

View File

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