forked from OSchip/llvm-project
[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:
parent
71f8f745b4
commit
9212206d25
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>>
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
|
@ -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: ...
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue