[llvm] r365524 - [Object][XCOFF] Add support for 64-bit file header and section header dumping.
Sean Fertile via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 9 11:09:11 PDT 2019
Author: sfertile
Date: Tue Jul 9 11:09:11 2019
New Revision: 365524
URL: http://llvm.org/viewvc/llvm-project?rev=365524&view=rev
Log:
[Object][XCOFF] Add support for 64-bit file header and section header dumping.
Adds a readobj dumper for 32-bit and 64-bit section header tables, and extend
support for the file-header dumping to include 64-bit object files. Also
refactors the binary file parsing to be done in a helper function in an attempt
to cleanup error handeling.
Differential Revision: https://reviews.llvm.org/D63843
Added:
llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o (with props)
llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test
Modified:
llvm/trunk/include/llvm/BinaryFormat/Magic.h
llvm/trunk/include/llvm/Object/Binary.h
llvm/trunk/include/llvm/Object/ObjectFile.h
llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
llvm/trunk/lib/BinaryFormat/Magic.cpp
llvm/trunk/lib/Object/Binary.cpp
llvm/trunk/lib/Object/ObjectFile.cpp
llvm/trunk/lib/Object/SymbolicFile.cpp
llvm/trunk/lib/Object/XCOFFObjectFile.cpp
llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test
llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp
llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp
Modified: llvm/trunk/include/llvm/BinaryFormat/Magic.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Magic.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Magic.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Magic.h Tue Jul 9 11:09:11 2019
@@ -46,6 +46,7 @@ struct file_magic {
pecoff_executable, ///< PECOFF executable file
windows_resource, ///< Windows compiled resource file (.res)
xcoff_object_32, ///< 32-bit XCOFF object file
+ xcoff_object_64, ///< 64-bit XCOFF object file
wasm_object, ///< WebAssembly Object file
pdb, ///< Windows PDB debug info file
};
Modified: llvm/trunk/include/llvm/Object/Binary.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Binary.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Binary.h (original)
+++ llvm/trunk/include/llvm/Object/Binary.h Tue Jul 9 11:09:11 2019
@@ -51,7 +51,9 @@ protected:
// Object and children.
ID_StartObjects,
ID_COFF,
+
ID_XCOFF32, // AIX XCOFF 32-bit
+ ID_XCOFF64, // AIX XCOFF 64-bit
ID_ELF32L, // ELF 32-bit, little endian
ID_ELF32B, // ELF 32-bit, big endian
@@ -121,7 +123,7 @@ public:
return TypeID == ID_COFF;
}
- bool isXCOFF() const { return TypeID == ID_XCOFF32; }
+ bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; }
bool isWasm() const { return TypeID == ID_Wasm; }
Modified: llvm/trunk/include/llvm/Object/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ObjectFile.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/ObjectFile.h Tue Jul 9 11:09:11 2019
@@ -359,7 +359,7 @@ public:
createCOFFObjectFile(MemoryBufferRef Object);
static Expected<std::unique_ptr<ObjectFile>>
- createXCOFFObjectFile(MemoryBufferRef Object);
+ createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
static Expected<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Object);
Modified: llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/XCOFFObjectFile.h?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/XCOFFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/XCOFFObjectFile.h Tue Jul 9 11:09:11 2019
@@ -34,7 +34,7 @@
namespace llvm {
namespace object {
-struct XCOFFFileHeader {
+struct XCOFFFileHeader32 {
support::ubig16_t Magic;
support::ubig16_t NumberOfSections;
@@ -48,7 +48,21 @@ struct XCOFFFileHeader {
support::ubig16_t Flags;
};
-struct XCOFFSectionHeader {
+struct XCOFFFileHeader64 {
+ support::ubig16_t Magic;
+ support::ubig16_t NumberOfSections;
+
+ // Unix time value, value of 0 indicates no timestamp.
+ // Negative values are reserved.
+ support::big32_t TimeStamp;
+
+ support::ubig64_t SymbolTableOffset; // File offset to symbol table.
+ support::ubig16_t AuxHeaderSize;
+ support::ubig16_t Flags;
+ support::ubig32_t NumberOfSymTableEntries;
+};
+
+struct XCOFFSectionHeader32 {
char Name[XCOFF::SectionNameSize];
support::ubig32_t PhysicalAddress;
support::ubig32_t VirtualAddress;
@@ -59,6 +73,24 @@ struct XCOFFSectionHeader {
support::ubig16_t NumberOfRelocations;
support::ubig16_t NumberOfLineNumbers;
support::big32_t Flags;
+
+ StringRef getName() const;
+};
+
+struct XCOFFSectionHeader64 {
+ char Name[XCOFF::SectionNameSize];
+ support::ubig64_t PhysicalAddress;
+ support::ubig64_t VirtualAddress;
+ support::ubig64_t SectionSize;
+ support::big64_t FileOffsetToRawData;
+ support::big64_t FileOffsetToRelocationInfo;
+ support::big64_t FileOffsetToLineNumberInfo;
+ support::ubig32_t NumberOfRelocations;
+ support::ubig32_t NumberOfLineNumbers;
+ support::big32_t Flags;
+ char Padding[4];
+
+ StringRef getName() const;
};
struct XCOFFSymbolEntry {
@@ -97,20 +129,54 @@ struct XCOFFStringTable {
class XCOFFObjectFile : public ObjectFile {
private:
- const XCOFFFileHeader *FileHdrPtr = nullptr;
- const XCOFFSectionHeader *SectionHdrTablePtr = nullptr;
+ const void *FileHeader = nullptr;
+ const void *SectionHeaderTable = nullptr;
+
const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
XCOFFStringTable StringTable = {0, nullptr};
+ const XCOFFFileHeader32 *fileHeader32() const;
+ const XCOFFFileHeader64 *fileHeader64() const;
+
+ const XCOFFSectionHeader32 *sectionHeaderTable32() const;
+ const XCOFFSectionHeader64 *sectionHeaderTable64() const;
+
size_t getFileHeaderSize() const;
size_t getSectionHeaderSize() const;
- const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
+ const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const;
+ const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const;
+ void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const;
+ uintptr_t getSectionHeaderTableAddress() const;
+
+ // This returns a pointer to the start of the storage for the name field of
+ // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily
+ // null-terminated.
+ const char *getSectionNameInternal(DataRefImpl Sec) const;
+
+ int32_t getSectionFlags(DataRefImpl Sec) const;
+
static bool isReservedSectionNumber(int16_t SectionNumber);
- std::error_code getSectionByNum(int16_t Num,
- const XCOFFSectionHeader *&Result) const;
+ Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
+
+ // Constructor and "create" factory function. The constructor is only a thin
+ // wrapper around the base constructor. The "create" function fills out the
+ // XCOFF-specific information and performs the error checking along the way.
+ XCOFFObjectFile(unsigned Type, MemoryBufferRef Object);
+ static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type,
+ MemoryBufferRef MBR);
+
+ // Helper for parsing the StringTable. Returns an 'Error' if parsing failed
+ // and an XCOFFStringTable if parsing succeeded.
+ static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj,
+ uint64_t Offset);
+
+ // Make a friend so it can call the private 'create' function.
+ friend Expected<std::unique_ptr<ObjectFile>>
+ ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
public:
+ // Interface inherited from base classes.
void moveSymbolNext(DataRefImpl &Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
@@ -156,10 +222,11 @@ public:
Expected<uint64_t> getStartAddress() const override;
bool isRelocatableObject() const override;
- XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
+ // Below here is the non-inherited interface.
+ bool is64Bit() const;
- const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
const XCOFFSymbolEntry *getPointerToSymbolTable() const {
+ assert(!is64Bit() && "Symbol table handling not supported yet.");
return SymbolTblPtr;
}
@@ -167,19 +234,32 @@ public:
getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
+
+ // File header related interfaces.
uint16_t getMagic() const;
uint16_t getNumberOfSections() const;
int32_t getTimeStamp() const;
- uint32_t getSymbolTableOffset() const;
- // Returns the value as encoded in the object file.
- // Negative values are reserved for future use.
- int32_t getRawNumberOfSymbolTableEntries() const;
+ // Symbol table offset and entry count are handled differently between
+ // XCOFF32 and XCOFF64.
+ uint32_t getSymbolTableOffset32() const;
+ uint64_t getSymbolTableOffset64() const;
+
+ // Note that this value is signed and might return a negative value. Negative
+ // values are reserved for future use.
+ int32_t getRawNumberOfSymbolTableEntries32() const;
+
+ // The sanitized value appropriate to use as an index into the symbol table.
+ uint32_t getLogicalNumberOfSymbolTableEntries32() const;
+
+ uint32_t getNumberOfSymbolTableEntries64() const;
- // Returns a sanitized value, useable as an index into the symbol table.
- uint32_t getLogicalNumberOfSymbolTableEntries() const;
uint16_t getOptionalHeaderSize() const;
- uint16_t getFlags() const { return FileHdrPtr->Flags; };
+ uint16_t getFlags() const;
+
+ // Section header table related interfaces.
+ ArrayRef<XCOFFSectionHeader32> sections32() const;
+ ArrayRef<XCOFFSectionHeader64> sections64() const;
}; // XCOFFObjectFile
} // namespace object
Modified: llvm/trunk/lib/BinaryFormat/Magic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Magic.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Magic.cpp (original)
+++ llvm/trunk/lib/BinaryFormat/Magic.cpp Tue Jul 9 11:09:11 2019
@@ -66,6 +66,8 @@ file_magic llvm::identify_magic(StringRe
// XCOFF format
if (startswith(Magic, "\x01\xDF"))
return file_magic::xcoff_object_32;
+ if (startswith(Magic, "\x01\xF7"))
+ return file_magic::xcoff_object_64;
break;
case 0xDE: // 0x0B17C0DE = BC wraper
Modified: llvm/trunk/lib/Object/Binary.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Binary.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Binary.cpp (original)
+++ llvm/trunk/lib/Object/Binary.cpp Tue Jul 9 11:09:11 2019
@@ -70,6 +70,7 @@ Expected<std::unique_ptr<Binary>> object
case file_magic::pecoff_executable:
case file_magic::bitcode:
case file_magic::xcoff_object_32:
+ case file_magic::xcoff_object_64:
case file_magic::wasm_object:
return ObjectFile::createSymbolicFile(Buffer, Type, Context);
case file_magic::macho_universal_binary:
Modified: llvm/trunk/lib/Object/ObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ObjectFile.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/ObjectFile.cpp Tue Jul 9 11:09:11 2019
@@ -150,7 +150,9 @@ ObjectFile::createObjectFile(MemoryBuffe
case file_magic::pecoff_executable:
return createCOFFObjectFile(Object);
case file_magic::xcoff_object_32:
- return createXCOFFObjectFile(Object);
+ return createXCOFFObjectFile(Object, Binary::ID_XCOFF32);
+ case file_magic::xcoff_object_64:
+ return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
case file_magic::wasm_object:
return createWasmObjectFile(Object);
}
Modified: llvm/trunk/lib/Object/SymbolicFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/SymbolicFile.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/SymbolicFile.cpp (original)
+++ llvm/trunk/lib/Object/SymbolicFile.cpp Tue Jul 9 11:09:11 2019
@@ -70,6 +70,7 @@ SymbolicFile::createSymbolicFile(MemoryB
case file_magic::macho_kext_bundle:
case file_magic::pecoff_executable:
case file_magic::xcoff_object_32:
+ case file_magic::xcoff_object_64:
case file_magic::wasm_object:
return ObjectFile::createObjectFile(Object, Type);
case file_magic::coff_import_library:
Modified: llvm/trunk/lib/Object/XCOFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/XCOFFObjectFile.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/lib/Object/XCOFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/XCOFFObjectFile.cpp Tue Jul 9 11:09:11 2019
@@ -22,32 +22,20 @@
namespace llvm {
namespace object {
-enum { XCOFF32FileHeaderSize = 20 };
-static_assert(sizeof(XCOFFFileHeader) == XCOFF32FileHeaderSize,
- "Wrong size for XCOFF file header.");
-
-// Sets EC and returns false if there is less than 'Size' bytes left in the
-// buffer at 'Offset'.
-static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Offset,
- uint64_t Size) {
- if (M.getBufferSize() < Offset + Size) {
- EC = object_error::unexpected_eof;
- return false;
- }
- return true;
-}
-
-// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
-// Returns unexpected_eof on error.
+// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
+// 'M'. Returns a pointer to the underlying object on success.
template <typename T>
-static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
- const void *Ptr,
- const uint64_t Size = sizeof(T)) {
+static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr,
+ const uint64_t Size = sizeof(T)) {
uintptr_t Addr = uintptr_t(Ptr);
if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
- return EC;
- Obj = reinterpret_cast<const T *>(Addr);
- return std::error_code();
+ return errorCodeToError(EC);
+ return reinterpret_cast<const T *>(Addr);
+}
+
+static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) {
+ return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) +
+ Offset);
}
template <typename T> static const T *viewAs(uintptr_t in) {
@@ -60,43 +48,69 @@ static StringRef generateStringRef(const
: StringRef(Name, Size);
}
-const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
- auto Sec = viewAs<XCOFFSectionHeader>(Ref.p);
-#ifndef NDEBUG
- if (Sec < SectionHdrTablePtr ||
- Sec >= (SectionHdrTablePtr + getNumberOfSections()))
+void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
+ uintptr_t TableAddress) const {
+ if (Addr < TableAddress)
+ report_fatal_error("Section header outside of section header table.");
+
+ uintptr_t Offset = Addr - TableAddress;
+ if (Offset >= getSectionHeaderSize() * getNumberOfSections())
report_fatal_error("Section header outside of section header table.");
- uintptr_t Offset = uintptr_t(Sec) - uintptr_t(SectionHdrTablePtr);
if (Offset % getSectionHeaderSize() != 0)
report_fatal_error(
"Section header pointer does not point to a valid section header.");
+}
+
+const XCOFFSectionHeader32 *
+XCOFFObjectFile::toSection32(DataRefImpl Ref) const {
+ assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+#ifndef NDEBUG
+ checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
#endif
- return Sec;
+ return viewAs<XCOFFSectionHeader32>(Ref.p);
+}
+
+const XCOFFSectionHeader64 *
+XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
+ assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+#ifndef NDEBUG
+ checkSectionAddress(Ref.p, getSectionHeaderTableAddress());
+#endif
+ return viewAs<XCOFFSectionHeader64>(Ref.p);
}
const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
+ assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
return SymEntPtr;
}
-// The next 2 functions are not exactly necessary yet, but they are useful to
-// abstract over the size difference between XCOFF32 and XCOFF64 structure
-// definitions.
-size_t XCOFFObjectFile::getFileHeaderSize() const {
- return sizeof(XCOFFFileHeader);
+const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
+ assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+ return static_cast<const XCOFFFileHeader32 *>(FileHeader);
}
-size_t XCOFFObjectFile::getSectionHeaderSize() const {
- return sizeof(XCOFFSectionHeader);
+const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
+ assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+ return static_cast<const XCOFFFileHeader64 *>(FileHeader);
}
-uint16_t XCOFFObjectFile::getMagic() const { return FileHdrPtr->Magic; }
+const XCOFFSectionHeader32 *
+XCOFFObjectFile::sectionHeaderTable32() const {
+ assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+ return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
+}
+
+const XCOFFSectionHeader64 *
+XCOFFObjectFile::sectionHeaderTable64() const {
+ assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+ return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
+}
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
-
SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
}
@@ -158,14 +172,11 @@ XCOFFObjectFile::getSymbolSection(DataRe
if (isReservedSectionNumber(SectNum))
return section_end();
- const XCOFFSectionHeader *Sec;
- if (std::error_code EC = getSectionByNum(SectNum, Sec))
- return errorCodeToError(EC);
-
- DataRefImpl SecDRI;
- SecDRI.p = reinterpret_cast<uintptr_t>(Sec);
+ Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum);
+ if (!ExpSec)
+ return ExpSec.takeError();
- return section_iterator(SectionRef(SecDRI, this));
+ return section_iterator(SectionRef(ExpSec.get(), this));
}
void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
@@ -174,25 +185,26 @@ void XCOFFObjectFile::moveSectionNext(Da
}
Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const {
- const char *Name = toSection(Sec)->Name;
- auto NulCharPtr =
- static_cast<const char *>(memchr(Name, '\0', XCOFF::SectionNameSize));
- return NulCharPtr ? StringRef(Name, NulCharPtr - Name)
- : StringRef(Name, XCOFF::SectionNameSize);
+ return generateStringRef(getSectionNameInternal(Sec), XCOFF::SectionNameSize);
}
uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
- return toSection(Sec)->VirtualAddress;
+ return is64Bit() ? toSection64(Sec)->VirtualAddress
+ : toSection32(Sec)->VirtualAddress;
}
uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
// Section numbers in XCOFF are numbered beginning at 1. A section number of
// zero is used to indicate that a symbol is being imported or is undefined.
- return toSection(Sec) - SectionHdrTablePtr + 1;
+ if (is64Bit())
+ return toSection64(Sec) - sectionHeaderTable64() + 1;
+ else
+ return toSection32(Sec) - sectionHeaderTable32() + 1;
}
uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
- return toSection(Sec)->SectionSize;
+ return is64Bit() ? toSection64(Sec)->SectionSize
+ : toSection32(Sec)->SectionSize;
}
Expected<ArrayRef<uint8_t>>
@@ -213,16 +225,16 @@ bool XCOFFObjectFile::isSectionCompresse
}
bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
- return toSection(Sec)->Flags & XCOFF::STYP_TEXT;
+ return getSectionFlags(Sec) & XCOFF::STYP_TEXT;
}
bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
- unsigned Flags = toSection(Sec)->Flags;
+ uint32_t Flags = getSectionFlags(Sec);
return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
}
bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
- unsigned Flags = toSection(Sec)->Flags;
+ uint32_t Flags = getSectionFlags(Sec);
return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
}
@@ -277,45 +289,41 @@ uint32_t XCOFFObjectFile::getSymbolFlags
}
basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
+ assert(!is64Bit() && "64-bit support not implemented yet.");
DataRefImpl SymDRI;
SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr);
return basic_symbol_iterator(SymbolRef(SymDRI, this));
}
basic_symbol_iterator XCOFFObjectFile::symbol_end() const {
+ assert(!is64Bit() && "64-bit support not implemented yet.");
DataRefImpl SymDRI;
SymDRI.p = reinterpret_cast<uintptr_t>(
- SymbolTblPtr + getLogicalNumberOfSymbolTableEntries());
+ SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
return basic_symbol_iterator(SymbolRef(SymDRI, this));
}
section_iterator XCOFFObjectFile::section_begin() const {
DataRefImpl DRI;
- DRI.p = reinterpret_cast<uintptr_t>(SectionHdrTablePtr);
+ DRI.p = getSectionHeaderTableAddress();
return section_iterator(SectionRef(DRI, this));
}
section_iterator XCOFFObjectFile::section_end() const {
DataRefImpl DRI;
- DRI.p =
- reinterpret_cast<uintptr_t>(SectionHdrTablePtr + getNumberOfSections());
+ DRI.p = getWithOffset(getSectionHeaderTableAddress(),
+ getNumberOfSections() * getSectionHeaderSize());
return section_iterator(SectionRef(DRI, this));
}
-uint8_t XCOFFObjectFile::getBytesInAddress() const {
- // Only support 32-bit object files for now ...
- assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
- return 4;
-}
+uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; }
StringRef XCOFFObjectFile::getFileFormatName() const {
- assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
- return "aixcoff-rs6000";
+ return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000";
}
Triple::ArchType XCOFFObjectFile::getArch() const {
- assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
- return Triple::ppc;
+ return is64Bit() ? Triple::ppc64 : Triple::ppc;
}
SubtargetFeatures XCOFFObjectFile::getFeatures() const {
@@ -335,19 +343,36 @@ Expected<uint64_t> XCOFFObjectFile::getS
return 0;
}
-std::error_code
-XCOFFObjectFile::getSectionByNum(int16_t Num,
- const XCOFFSectionHeader *&Result) const {
- if (Num > 0 && static_cast<uint16_t>(Num) <= getNumberOfSections()) {
- Result = SectionHdrTablePtr + (Num - 1);
- return std::error_code();
- }
+size_t XCOFFObjectFile::getFileHeaderSize() const {
+ return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32);
+}
- return object_error::invalid_section_index;
+size_t XCOFFObjectFile::getSectionHeaderSize() const {
+ return is64Bit() ? sizeof(XCOFFSectionHeader64) :
+ sizeof(XCOFFSectionHeader32);
+}
+
+bool XCOFFObjectFile::is64Bit() const {
+ return Binary::ID_XCOFF64 == getType();
+}
+
+uint16_t XCOFFObjectFile::getMagic() const {
+ return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic;
+}
+
+Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
+ if (Num <= 0 || Num > getNumberOfSections())
+ return errorCodeToError(object_error::invalid_section_index);
+
+ DataRefImpl DRI;
+ DRI.p = getWithOffset(getSectionHeaderTableAddress(),
+ getSectionHeaderSize() * (Num - 1));
+ return DRI;
}
Expected<StringRef>
XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
+ assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
int16_t SectionNum = SymEntPtr->SectionNumber;
switch (SectionNum) {
@@ -357,14 +382,12 @@ XCOFFObjectFile::getSymbolSectionName(co
return "N_ABS";
case XCOFF::N_UNDEF:
return "N_UNDEF";
- default: {
- const XCOFFSectionHeader *SectHeaderPtr;
- std::error_code EC;
- if ((EC = getSectionByNum(SectionNum, SectHeaderPtr)))
- return errorCodeToError(EC);
- else
- return generateStringRef(SectHeaderPtr->Name, XCOFF::SectionNameSize);
- }
+ default:
+ Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum);
+ if (SecRef)
+ return generateStringRef(getSectionNameInternal(SecRef.get()),
+ XCOFF::SectionNameSize);
+ return SecRef.takeError();
}
}
@@ -373,99 +396,180 @@ bool XCOFFObjectFile::isReservedSectionN
}
uint16_t XCOFFObjectFile::getNumberOfSections() const {
- return FileHdrPtr->NumberOfSections;
+ return is64Bit() ? fileHeader64()->NumberOfSections
+ : fileHeader32()->NumberOfSections;
}
-int32_t XCOFFObjectFile::getTimeStamp() const { return FileHdrPtr->TimeStamp; }
+int32_t XCOFFObjectFile::getTimeStamp() const {
+ return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp;
+}
-uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
- return FileHdrPtr->SymbolTableOffset;
+uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
+ return is64Bit() ? fileHeader64()->AuxHeaderSize
+ : fileHeader32()->AuxHeaderSize;
}
-int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries() const {
- return FileHdrPtr->NumberOfSymTableEntries;
+uint32_t XCOFFObjectFile::getSymbolTableOffset32() const {
+ return fileHeader32()->SymbolTableOffset;
}
-uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries() const {
- return (FileHdrPtr->NumberOfSymTableEntries >= 0
- ? FileHdrPtr->NumberOfSymTableEntries
+int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const {
+ // As far as symbol table size is concerned, if this field is negative it is
+ // to be treated as a 0. However since this field is also used for printing we
+ // don't want to truncate any negative values.
+ return fileHeader32()->NumberOfSymTableEntries;
+}
+
+uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const {
+ return (fileHeader32()->NumberOfSymTableEntries >= 0
+ ? fileHeader32()->NumberOfSymTableEntries
: 0);
}
-uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
- return FileHdrPtr->AuxHeaderSize;
+uint64_t XCOFFObjectFile::getSymbolTableOffset64() const {
+ return fileHeader64()->SymbolTableOffset;
}
-XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
- : ObjectFile(Binary::ID_XCOFF32, Object) {
+uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
+ return fileHeader64()->NumberOfSymTableEntries;
+}
- // Current location within the file.
- uint64_t CurPtr = 0;
+uint16_t XCOFFObjectFile::getFlags() const {
+ return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
+}
- if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr)))
- return;
+const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const {
+ return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name;
+}
- CurPtr += getFileHeaderSize();
- // TODO FIXME we don't have support for an optional header yet, so just skip
- // past it.
- CurPtr += FileHdrPtr->AuxHeaderSize;
+uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const {
+ return reinterpret_cast<uintptr_t>(SectionHeaderTable);
+}
- if (getNumberOfSections() != 0) {
- if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr,
- getNumberOfSections() * getSectionHeaderSize())))
- return;
- }
+int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const {
+ return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags;
+}
- if (getLogicalNumberOfSymbolTableEntries() == 0)
- return;
+XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object)
+ : ObjectFile(Type, Object) {
+ assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64);
+}
- // Get pointer to the symbol table.
- CurPtr = FileHdrPtr->SymbolTableOffset;
- uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
- getLogicalNumberOfSymbolTableEntries();
+ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const {
+ assert(is64Bit() && "64-bit interface called for non 64-bit file.");
+ const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64();
+ return ArrayRef<XCOFFSectionHeader64>(TablePtr,
+ TablePtr + getNumberOfSections());
+}
- if ((EC = getObject(SymbolTblPtr, Data, base() + CurPtr, SymbolTableSize)))
- return;
+ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
+ assert(!is64Bit() && "32-bit interface called for non 32-bit file.");
+ const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32();
+ return ArrayRef<XCOFFSectionHeader32>(TablePtr,
+ TablePtr + getNumberOfSections());
+}
+
+Expected<XCOFFStringTable>
+XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
+ // If there is a string table, then the buffer must contain at least 4 bytes
+ // for the string table's size. Not having a string table is not an error.
+ if (auto EC = Binary::checkOffset(
+ Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4))
+ return XCOFFStringTable{0, nullptr};
+
+ // Read the size out of the buffer.
+ uint32_t Size = support::endian::read32be(Obj->base() + Offset);
- // Move pointer to the string table.
- CurPtr += SymbolTableSize;
+ // If the size is less then 4, then the string table is just a size and no
+ // string data.
+ if (Size <= 4)
+ return XCOFFStringTable{4, nullptr};
- if (CurPtr + 4 > Data.getBufferSize())
- return;
+ auto StringTableOrErr =
+ getObject<char>(Obj->Data, Obj->base() + Offset, Size);
+ if (Error E = StringTableOrErr.takeError())
+ return std::move(E);
- StringTable.Size = support::endian::read32be(base() + CurPtr);
+ const char *StringTablePtr = StringTableOrErr.get();
+ if (StringTablePtr[Size - 1] != '\0')
+ return errorCodeToError(object_error::string_table_non_null_end);
+
+ return XCOFFStringTable{Size, StringTablePtr};
+}
- if (StringTable.Size <= 4)
- return;
+Expected<std::unique_ptr<XCOFFObjectFile>>
+XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
+ // Can't use make_unique because of the private constructor.
+ std::unique_ptr<XCOFFObjectFile> Obj;
+ Obj.reset(new XCOFFObjectFile(Type, MBR));
- // Check for whether the String table has the size indicated by length
- // field
- if (!checkSize(Data, EC, CurPtr, StringTable.Size))
- return;
+ uint64_t CurOffset = 0;
+ const auto *Base = Obj->base();
+ MemoryBufferRef Data = Obj->Data;
+
+ // Parse file header.
+ auto FileHeaderOrErr =
+ getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize());
+ if (Error E = FileHeaderOrErr.takeError())
+ return std::move(E);
+ Obj->FileHeader = FileHeaderOrErr.get();
+
+ CurOffset += Obj->getFileHeaderSize();
+ // TODO FIXME we don't have support for an optional header yet, so just skip
+ // past it.
+ CurOffset += Obj->getOptionalHeaderSize();
- StringTable.Data = reinterpret_cast<const char *>(base() + CurPtr);
- if (StringTable.Data[StringTable.Size - 1] != '\0') {
- EC = object_error::string_table_non_null_end;
- return;
+ // Parse the section header table if it is present.
+ if (Obj->getNumberOfSections()) {
+ auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
+ Obj->getNumberOfSections() *
+ Obj->getSectionHeaderSize());
+ if (Error E = SecHeadersOrErr.takeError())
+ return std::move(E);
+ Obj->SectionHeaderTable = SecHeadersOrErr.get();
}
+
+ // 64-bit object supports only file header and section headers for now.
+ if (Obj->is64Bit())
+ return std::move(Obj);
+
+ // If there is no symbol table we are done parsing the memory buffer.
+ if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
+ return std::move(Obj);
+
+ // Parse symbol table.
+ CurOffset = Obj->fileHeader32()->SymbolTableOffset;
+ uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
+ Obj->getLogicalNumberOfSymbolTableEntries32();
+ auto SymTableOrErr =
+ getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
+ if (Error E = SymTableOrErr.takeError())
+ return std::move(E);
+ Obj->SymbolTblPtr = SymTableOrErr.get();
+ CurOffset += SymbolTableSize;
+
+ // Parse String table.
+ Expected<XCOFFStringTable> StringTableOrErr =
+ parseStringTable(Obj.get(), CurOffset);
+ if (Error E = StringTableOrErr.takeError())
+ return std::move(E);
+ Obj->StringTable = StringTableOrErr.get();
+
+ return std::move(Obj);
}
Expected<std::unique_ptr<ObjectFile>>
-ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) {
- StringRef Data = Object.getBuffer();
- file_magic Type = identify_magic(Data);
- std::error_code EC;
- std::unique_ptr<ObjectFile> Ret;
-
- if (Type == file_magic::xcoff_object_32) {
- Ret.reset(new XCOFFObjectFile(Object, EC));
- } else {
- llvm_unreachable("Encountered an unexpected binary file type!");
- }
+ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
+ unsigned FileType) {
+ return XCOFFObjectFile::create(FileType, MemBufRef);
+}
- if (EC)
- return errorCodeToError(EC);
- return std::move(Ret);
+StringRef XCOFFSectionHeader32::getName() const {
+ return generateStringRef(Name, XCOFF::SectionNameSize);
+}
+
+StringRef XCOFFSectionHeader64::getName() const {
+ return generateStringRef(Name, XCOFF::SectionNameSize);
}
} // namespace object
Added: llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o?rev=365524&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/xcoff-basic-64.o
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test Tue Jul 9 11:09:11 2019
@@ -1,5 +1,8 @@
# RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic.o | \
# RUN: FileCheck --check-prefix=FILEHEADER %s
+#
+# RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-64.o | \
+# RUN: FileCheck --check-prefix=FILEHEADER64 %s
# RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-neg-time.o | \
# RUN: FileCheck --check-prefix=NEGTIME %s
@@ -21,6 +24,20 @@
# FILEHEADER-NEXT: Flags: 0x0
# FILEHEADER-NEXT: }
+# FILEHEADER64: File: {{.*}}xcoff-basic-64.o
+# FILEHEADER64-NEXT: Format: aix5coff64-rs6000
+# FILEHEADER64-NEXT: Arch: powerpc64
+# FILEHEADER64-NEXT: AddressSize: 64bit
+# FILEHEADER64-NEXT: FileHeader {
+# FILEHEADER64-NEXT: Magic: 0x1F7
+# FILEHEADER64-NEXT: NumberOfSections: 5
+# FILEHEADER64-NEXT: TimeStamp: 2019-03-18T20:03:47Z (0x5C8FF9A3)
+# FILEHEADER64-NEXT: SymbolTableOffset: 0x54C
+# FILEHEADER64-NEXT: SymbolTableEntries: 58
+# FILEHEADER64-NEXT: OptionalHeaderSize: 0x0
+# FILEHEADER64-NEXT: Flags: 0x0
+# FILEHEADER64-NEXT: }
+
# NEGTIME: File: {{.*}}xcoff-basic-neg-time.o
# NEGTIME-NEXT: Format: aixcoff-rs6000
# NEGTIME-NEXT: Arch: powerpc
Added: llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test?rev=365524&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/xcoff-sections.test Tue Jul 9 11:09:11 2019
@@ -0,0 +1,164 @@
+# RUN: llvm-readobj --section-headers %p/Inputs/xcoff-basic.o | \
+# RUN: FileCheck --check-prefix=SEC32 %s
+
+# RUN: llvm-readobj --section-headers %p/Inputs/xcoff-basic-64.o | \
+# RUN: FileCheck --check-prefix=SEC64 %s
+
+# SEC32: File: {{.*}}xcoff-basic.o
+# SEC32-NEXT: Format: aixcoff-rs6000
+# SEC32-NEXT: Arch: powerpc
+# SEC32-NEXT: AddressSize: 32bit
+# SEC32-NEXT: Sections [
+# SEC32-NEXT: Section {
+# SEC32-NEXT: Index: 1
+# SEC32-NEXT: Name: .text
+# SEC32-NEXT: PhysicalAddress: 0x0
+# SEC32-NEXT: VirtualAddress: 0x0
+# SEC32-NEXT: Size: 0x100
+# SEC32-NEXT: RawDataOffset: 0x200
+# SEC32-NEXT: RelocationPointer: 0x3D8
+# SEC32-NEXT: LineNumberPointer: 0x4E6
+# SEC32-NEXT: NumberOfRelocations: 8
+# SEC32-NEXT: NumberOfLineNumbers: 12
+# SEC32-NEXT: Type: STYP_TEXT (0x20)
+# SEC32-NEXT: }
+# SEC32-NEXT: Section {
+# SEC32-NEXT: Index: 2
+# SEC32-NEXT: Name: .data
+# SEC32-NEXT: PhysicalAddress: 0x100
+# SEC32-NEXT: VirtualAddress: 0x100
+# SEC32-NEXT: Size: 0x68
+# SEC32-NEXT: RawDataOffset: 0x300
+# SEC32-NEXT: RelocationPointer: 0x428
+# SEC32-NEXT: LineNumberPointer: 0x0
+# SEC32-NEXT: NumberOfRelocations: 19
+# SEC32-NEXT: NumberOfLineNumbers: 0
+# SEC32-NEXT: Type: STYP_DATA (0x40)
+# SEC32-NEXT: }
+# SEC32-NEXT: Section {
+# SEC32-NEXT: Index: 3
+# SEC32-NEXT: Name: .bss
+# SEC32-NEXT: PhysicalAddress: 0x168
+# SEC32-NEXT: VirtualAddress: 0x168
+# SEC32-NEXT: Size: 0x4
+# SEC32-NEXT: RawDataOffset: 0x0
+# SEC32-NEXT: RelocationPointer: 0x0
+# SEC32-NEXT: LineNumberPointer: 0x0
+# SEC32-NEXT: NumberOfRelocations: 0
+# SEC32-NEXT: NumberOfLineNumbers: 0
+# SEC32-NEXT: Type: STYP_BSS (0x80)
+# SEC32-NEXT: }
+# SEC32-NEXT: Section {
+# SEC32-NEXT: Index: 4
+# SEC32-NEXT: Name: .tdata
+# SEC32-NEXT: PhysicalAddress: 0x0
+# SEC32-NEXT: VirtualAddress: 0x0
+# SEC32-NEXT: Size: 0x4
+# SEC32-NEXT: RawDataOffset: 0x368
+# SEC32-NEXT: RelocationPointer: 0x47A
+# SEC32-NEXT: LineNumberPointer: 0x0
+# SEC32-NEXT: NumberOfRelocations: 0
+# SEC32-NEXT: NumberOfLineNumbers: 0
+# SEC32-NEXT: Type: STYP_TDATA (0x400)
+# SEC32-NEXT: }
+# SEC32-NEXT: Section {
+# SEC32-NEXT: Index: 5
+# SEC32-NEXT: Name: .tbss
+# SEC32-NEXT: PhysicalAddress: 0x4
+# SEC32-NEXT: VirtualAddress: 0x4
+# SEC32-NEXT: Size: 0x8
+# SEC32-NEXT: RawDataOffset: 0x0
+# SEC32-NEXT: RelocationPointer: 0x0
+# SEC32-NEXT: LineNumberPointer: 0x0
+# SEC32-NEXT: NumberOfRelocations: 0
+# SEC32-NEXT: NumberOfLineNumbers: 0
+# SEC32-NEXT: Type: STYP_TBSS (0x800)
+# SEC32-NEXT: }
+# SEC32-NEXT: Section {
+# SEC32-NEXT: Index: 6
+# SEC32-NEXT: Name: .debug
+# SEC32-NEXT: PhysicalAddress: 0x0
+# SEC32-NEXT: VirtualAddress: 0x0
+# SEC32-NEXT: Size: 0x6C
+# SEC32-NEXT: RawDataOffset: 0x36C
+# SEC32-NEXT: RelocationPointer: 0x0
+# SEC32-NEXT: LineNumberPointer: 0x0
+# SEC32-NEXT: NumberOfRelocations: 0
+# SEC32-NEXT: NumberOfLineNumbers: 0
+# SEC32-NEXT: Type: STYP_DEBUG (0x2000)
+# SEC32-NEXT: }
+# SEC32-NEXT: ]
+
+
+# SEC64: File: {{.*}}xcoff-basic-64.o
+# SEC64-NEXT: Format: aix5coff64-rs6000
+# SEC64-NEXT: Arch: powerpc64
+# SEC64-NEXT: AddressSize: 64bit
+# SEC64-NEXT: Sections [
+# SEC64-NEXT: Section {
+# SEC64-NEXT: Index: 1
+# SEC64-NEXT: Name: .text
+# SEC64-NEXT: PhysicalAddress: 0x0
+# SEC64-NEXT: VirtualAddress: 0x0
+# SEC64-NEXT: Size: 0x100
+# SEC64-NEXT: RawDataOffset: 0x200
+# SEC64-NEXT: RelocationPointer: 0x3C4
+# SEC64-NEXT: LineNumberPointer: 0x0
+# SEC64-NEXT: NumberOfRelocations: 9
+# SEC64-NEXT: NumberOfLineNumbers: 0
+# SEC64-NEXT: Type: STYP_TEXT (0x20)
+# SEC64-NEXT: }
+# SEC64-NEXT: Section {
+# SEC64-NEXT: Index: 2
+# SEC64-NEXT: Name: .data
+# SEC64-NEXT: PhysicalAddress: 0x100
+# SEC64-NEXT: VirtualAddress: 0x100
+# SEC64-NEXT: Size: 0xC0
+# SEC64-NEXT: RawDataOffset: 0x300
+# SEC64-NEXT: RelocationPointer: 0x442
+# SEC64-NEXT: LineNumberPointer: 0x0
+# SEC64-NEXT: NumberOfRelocations: 19
+# SEC64-NEXT: NumberOfLineNumbers: 0
+# SEC64-NEXT: Type: STYP_DATA (0x40)
+# SEC64-NEXT: }
+# SEC64-NEXT: Section {
+# SEC64-NEXT: Index: 3
+# SEC64-NEXT: Name: .bss
+# SEC64-NEXT: PhysicalAddress: 0x1C0
+# SEC64-NEXT: VirtualAddress: 0x1C0
+# SEC64-NEXT: Size: 0x8
+# SEC64-NEXT: RawDataOffset: 0x0
+# SEC64-NEXT: RelocationPointer: 0x0
+# SEC64-NEXT: LineNumberPointer: 0x0
+# SEC64-NEXT: NumberOfRelocations: 0
+# SEC64-NEXT: NumberOfLineNumbers: 0
+# SEC64-NEXT: Type: STYP_BSS (0x80)
+# SEC64-NEXT: }
+# SEC64-NEXT: Section {
+# SEC64-NEXT: Index: 4
+# SEC64-NEXT: Name: .tdata
+# SEC64-NEXT: PhysicalAddress: 0x0
+# SEC64-NEXT: VirtualAddress: 0x0
+# SEC64-NEXT: Size: 0x4
+# SEC64-NEXT: RawDataOffset: 0x3C0
+# SEC64-NEXT: RelocationPointer: 0x54C
+# SEC64-NEXT: LineNumberPointer: 0x0
+# SEC64-NEXT: NumberOfRelocations: 0
+# SEC64-NEXT: NumberOfLineNumbers: 0
+# SEC64-NEXT: Type: STYP_TDATA (0x400)
+# SEC64-NEXT: }
+# SEC64-NEXT: Section {
+# SEC64-NEXT: Index: 5
+# SEC64-NEXT: Name: .tbss
+# SEC64-NEXT: PhysicalAddress: 0x4
+# SEC64-NEXT: VirtualAddress: 0x4
+# SEC64-NEXT: Size: 0x8
+# SEC64-NEXT: RawDataOffset: 0x0
+# SEC64-NEXT: RelocationPointer: 0x0
+# SEC64-NEXT: LineNumberPointer: 0x0
+# SEC64-NEXT: NumberOfRelocations: 0
+# SEC64-NEXT: NumberOfLineNumbers: 0
+# SEC64-NEXT: Type: STYP_TBSS (0x800)
+# SEC64-NEXT: }
+# SEC64-NEXT: ]
+
Modified: llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp Tue Jul 9 11:09:11 2019
@@ -36,7 +36,12 @@ public:
void printNeededLibraries() override;
private:
+ template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
+
const XCOFFObjectFile &Obj;
+
+ // Least significant 3 bits are reserved.
+ static constexpr unsigned SectionFlagsReservedMask = 0x7;
};
} // anonymous namespace
@@ -65,12 +70,20 @@ void XCOFFDumper::printFileHeaders() {
TimeStamp);
}
- W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset());
- int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries();
- if (SymTabEntries >= 0)
- W.printNumber("SymbolTableEntries", SymTabEntries);
- else
- W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
+ // The number of symbol table entries is an unsigned value in 64-bit objects
+ // and a signed value (with negative values being 'reserved') in 32-bit
+ // objects.
+ if (Obj.is64Bit()) {
+ W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
+ W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
+ } else {
+ W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
+ int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
+ if (SymTabEntries >= 0)
+ W.printNumber("SymbolTableEntries", SymTabEntries);
+ else
+ W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
+ }
W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
W.printHex("Flags", Obj.getFlags());
@@ -80,7 +93,10 @@ void XCOFFDumper::printFileHeaders() {
}
void XCOFFDumper::printSectionHeaders() {
- llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+ if (Obj.is64Bit())
+ printSectionHeaders(Obj.sections64());
+ else
+ printSectionHeaders(Obj.sections32());
}
void XCOFFDumper::printRelocations() {
@@ -107,6 +123,59 @@ void XCOFFDumper::printNeededLibraries()
llvm_unreachable("Unimplemented functionality for XCOFFDumper");
}
+static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT),
+ ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT),
+ ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS),
+ ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
+ ECase(STYP_OVRFLO)
+#undef ECase
+};
+
+template <typename T>
+void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
+ ListScope Group(W, "Sections");
+
+ uint16_t Index = 1;
+ for (const T &Sec : Sections) {
+ DictScope SecDS(W, "Section");
+
+ W.printNumber("Index", Index++);
+ W.printString("Name", Sec.getName());
+
+ W.printHex("PhysicalAddress", Sec.PhysicalAddress);
+ W.printHex("VirtualAddress", Sec.VirtualAddress);
+ W.printHex("Size", Sec.SectionSize);
+ W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
+ W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
+ W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
+
+ // TODO Need to add overflow handling when NumberOfX == _OVERFLOW_MARKER
+ // in 32-bit object files.
+ W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
+ W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
+
+ // The most significant 16-bits represent the DWARF section subtype. For
+ // now we just dump the section type flags.
+ uint16_t Flags = Sec.Flags & 0xffffu;
+ if (Flags & SectionFlagsReservedMask)
+ W.printHex("Flags", "Reserved", Flags);
+ else
+ W.printEnum("Type", Flags, makeArrayRef(SectionTypeFlagsNames));
+ }
+
+ if (opts::SectionRelocations)
+ report_fatal_error("Dumping section relocations is unimplemented");
+
+ if (opts::SectionSymbols)
+ report_fatal_error("Dumping symbols is unimplemented");
+
+ if (opts::SectionData)
+ report_fatal_error("Dumping section data is unimplemented");
+}
+
namespace llvm {
std::error_code createXCOFFDumper(const object::ObjectFile *Obj,
ScopedPrinter &Writer,
Modified: llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp?rev=365524&r1=365523&r2=365524&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/xcoff2yaml.cpp Tue Jul 9 11:09:11 2019
@@ -29,22 +29,25 @@ public:
} // namespace
std::error_code XCOFFDumper::dump() {
- std::error_code EC;
dumpHeader();
- EC = dumpSymbols();
- return EC;
+ return dumpSymbols();
}
void XCOFFDumper::dumpHeader() {
- const XCOFFFileHeader *FileHdrPtr = Obj.getFileHeader();
- YAMLObj.Header.Magic = FileHdrPtr->Magic;
- YAMLObj.Header.NumberOfSections = FileHdrPtr->NumberOfSections;
- YAMLObj.Header.TimeStamp = FileHdrPtr->TimeStamp;
- YAMLObj.Header.SymbolTableOffset = FileHdrPtr->SymbolTableOffset;
- YAMLObj.Header.NumberOfSymTableEntries = FileHdrPtr->NumberOfSymTableEntries;
- YAMLObj.Header.AuxHeaderSize = FileHdrPtr->AuxHeaderSize;
- YAMLObj.Header.Flags = FileHdrPtr->Flags;
+ YAMLObj.Header.Magic = Obj.getMagic();
+ YAMLObj.Header.NumberOfSections = Obj.getNumberOfSections();
+ YAMLObj.Header.TimeStamp = Obj.getTimeStamp();
+
+ // TODO FIXME only dump 32 bit header for now.
+ if (Obj.is64Bit())
+ report_fatal_error("64-bit XCOFF files not supported yet.");
+ YAMLObj.Header.SymbolTableOffset = Obj.getSymbolTableOffset32();
+
+ YAMLObj.Header.NumberOfSymTableEntries =
+ Obj.getRawNumberOfSymbolTableEntries32();
+ YAMLObj.Header.AuxHeaderSize = Obj.getOptionalHeaderSize();
+ YAMLObj.Header.Flags = Obj.getFlags();
}
std::error_code XCOFFDumper::dumpSymbols() {
More information about the llvm-commits
mailing list