[XCOFF][AIX] Enable tooling support for 64 bit symbol table parsing

Add in the ability of parsing symbol table for 64 bit object.

Reviewed By: jhenderson, DiggerLin

Differential Revision: https://reviews.llvm.org/D85774
This commit is contained in:
jasonliu 2021-06-07 14:52:55 +00:00
parent 30de816da1
commit c03aed5d1b
13 changed files with 1084 additions and 239 deletions

View File

@ -296,6 +296,15 @@ enum CFileCpuId : uint8_t {
TCPU_970 = 19 ///< PPC970 - PowerPC 64-bit architecture.
};
enum SymbolAuxType : uint8_t {
AUX_EXCEPT = 255, ///< Identifies an exception auxiliary entry.
AUX_FCN = 254, ///< Identifies a function auxiliary entry.
AUX_SYM = 253, ///< Identifies a symbol auxiliary entry.
AUX_FILE = 252, ///< Identifies a file auxiliary entry.
AUX_CSECT = 251, ///< Identifies a csect auxiliary entry.
AUX_SECT = 250 ///< Identifies a SECT auxiliary entry.
}; // 64-bit XCOFF file only.
StringRef getMappingClassString(XCOFF::StorageMappingClass SMC);
StringRef getRelocationTypeString(XCOFF::RelocationType Type);
SmallString<32> parseParmsType(uint32_t Value, unsigned ParmsNum);

View File

@ -97,68 +97,113 @@ struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
char Padding[4];
};
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::NameSize];
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;
};
struct XCOFFCsectAuxEnt32 {
static constexpr uint8_t SymbolTypeMask = 0x07;
static constexpr uint8_t SymbolAlignmentMask = 0xF8;
static constexpr size_t SymbolAlignmentBitOffset = 3;
support::ubig32_t
SectionOrLength; // If the symbol type is XTY_SD or XTY_CM, the csect
// length.
// If the symbol type is XTY_LD, the symbol table
// index of the containing csect.
// If the symbol type is XTY_ER, 0.
support::ubig32_t SectionOrLength;
support::ubig32_t ParameterHashIndex;
support::ubig16_t TypeChkSectNum;
uint8_t SymbolAlignmentAndType;
XCOFF::StorageMappingClass StorageMappingClass;
support::ubig32_t StabInfoIndex;
support::ubig16_t StabSectNum;
};
struct XCOFFCsectAuxEnt64 {
support::ubig32_t SectionOrLengthLowByte;
support::ubig32_t ParameterHashIndex;
support::ubig16_t TypeChkSectNum;
uint8_t SymbolAlignmentAndType;
XCOFF::StorageMappingClass StorageMappingClass;
support::ubig32_t SectionOrLengthHighByte;
uint8_t Pad;
XCOFF::SymbolAuxType AuxType;
};
class XCOFFCsectAuxRef {
public:
static constexpr uint8_t SymbolTypeMask = 0x07;
static constexpr uint8_t SymbolAlignmentMask = 0xF8;
static constexpr size_t SymbolAlignmentBitOffset = 3;
XCOFFCsectAuxRef(const XCOFFCsectAuxEnt32 *Entry32) : Entry32(Entry32) {}
XCOFFCsectAuxRef(const XCOFFCsectAuxEnt64 *Entry64) : Entry64(Entry64) {}
// For getSectionOrLength(),
// If the symbol type is XTY_SD or XTY_CM, the csect length.
// If the symbol type is XTY_LD, the symbol table
// index of the containing csect.
// If the symbol type is XTY_ER, 0.
uint64_t getSectionOrLength() const {
return Entry32 ? getSectionOrLength32() : getSectionOrLength64();
}
uint32_t getSectionOrLength32() const {
assert(Entry32 && "32-bit interface called on 64-bit object file.");
return Entry32->SectionOrLength;
}
uint64_t getSectionOrLength64() const {
assert(Entry64 && "64-bit interface called on 32-bit object file.");
return (static_cast<uint64_t>(Entry64->SectionOrLengthHighByte) << 32) |
Entry64->SectionOrLengthLowByte;
}
#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
uint32_t getParameterHashIndex() const {
return GETVALUE(ParameterHashIndex);
}
uint16_t getTypeChkSectNum() const { return GETVALUE(TypeChkSectNum); }
XCOFF::StorageMappingClass getStorageMappingClass() const {
return GETVALUE(StorageMappingClass);
}
uintptr_t getEntryAddress() const {
return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
: reinterpret_cast<uintptr_t>(Entry64);
}
uint16_t getAlignmentLog2() const {
return (SymbolAlignmentAndType & SymbolAlignmentMask) >>
return (getSymbolAlignmentAndType() & SymbolAlignmentMask) >>
SymbolAlignmentBitOffset;
}
uint8_t getSymbolType() const {
return SymbolAlignmentAndType & SymbolTypeMask;
return getSymbolAlignmentAndType() & SymbolTypeMask;
}
bool isLabel() const { return getSymbolType() == XCOFF::XTY_LD; }
uint32_t getStabInfoIndex32() const {
assert(Entry32 && "32-bit interface called on 64-bit object file.");
return Entry32->StabInfoIndex;
}
uint16_t getStabSectNum32() const {
assert(Entry32 && "32-bit interface called on 64-bit object file.");
return Entry32->StabSectNum;
}
XCOFF::SymbolAuxType getAuxType64() const {
assert(Entry64 && "64-bit interface called on 32-bit object file.");
return Entry64->AuxType;
}
private:
uint8_t getSymbolAlignmentAndType() const {
return GETVALUE(SymbolAlignmentAndType);
}
#undef GETVALUE
const XCOFFCsectAuxEnt32 *Entry32 = nullptr;
const XCOFFCsectAuxEnt64 *Entry64 = nullptr;
};
struct XCOFFFileAuxEnt {
@ -173,7 +218,7 @@ struct XCOFFFileAuxEnt {
};
XCOFF::CFileStringType Type;
uint8_t ReservedZeros[2];
uint8_t AuxType; // 64-bit XCOFF file only.
XCOFF::SymbolAuxType AuxType; // 64-bit XCOFF file only.
};
struct XCOFFSectAuxEntForStat {
@ -181,7 +226,7 @@ struct XCOFFSectAuxEntForStat {
support::ubig16_t NumberOfRelocEnt;
support::ubig16_t NumberOfLineNum;
uint8_t Pad[10];
};
}; // 32-bit XCOFF file only.
struct XCOFFRelocation32 {
// Masks for packing/unpacking the r_rsize field of relocations.
@ -215,12 +260,14 @@ public:
uint8_t getRelocatedLength() const;
};
class XCOFFSymbolRef;
class XCOFFObjectFile : public ObjectFile {
private:
const void *FileHeader = nullptr;
const void *SectionHeaderTable = nullptr;
const XCOFFSymbolEntry *SymbolTblPtr = nullptr;
const void *SymbolTblPtr = nullptr;
XCOFFStringTable StringTable = {0, nullptr};
const XCOFFFileHeader32 *fileHeader32() const;
@ -242,9 +289,6 @@ private:
// null-terminated.
const char *getSectionNameInternal(DataRefImpl Sec) const;
// This function returns string table entry.
Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
static bool isReservedSectionNumber(int16_t SectionNumber);
// Constructor and "create" factory function. The constructor is only a thin
@ -323,15 +367,11 @@ public:
// Below here is the non-inherited interface.
bool is64Bit() const;
const XCOFFSymbolEntry *getPointerToSymbolTable() const {
assert(!is64Bit() && "Symbol table handling not supported yet.");
return SymbolTblPtr;
}
const void *getPointerToSymbolTable() const { return SymbolTblPtr; }
Expected<StringRef>
getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const;
Expected<StringRef> getSymbolSectionName(XCOFFSymbolRef Ref) const;
const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const;
XCOFFSymbolRef toSymbolRef(DataRefImpl Ref) const;
// File header related interfaces.
uint16_t getMagic() const;
@ -351,7 +391,13 @@ public:
uint32_t getLogicalNumberOfSymbolTableEntries32() const;
uint32_t getNumberOfSymbolTableEntries64() const;
// Return getLogicalNumberOfSymbolTableEntries32 or
// getNumberOfSymbolTableEntries64 depending on the object mode.
uint32_t getNumberOfSymbolTableEntries() const;
uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
uintptr_t getSymbolEntryAddressByIndex(uint32_t SymbolTableIndex) const;
Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
@ -374,26 +420,120 @@ public:
Expected<ArrayRef<XCOFFRelocation32>>
relocations(const XCOFFSectionHeader32 &) const;
// This function returns string table entry.
Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
const XCOFF::SymbolAuxType *getSymbolAuxType(uintptr_t AuxEntryAddress) const;
static uintptr_t getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
uint32_t Distance);
static bool classof(const Binary *B) { return B->isXCOFF(); }
}; // XCOFFObjectFile
class XCOFFSymbolRef {
const DataRefImpl SymEntDataRef;
const XCOFFObjectFile *const OwningObjectPtr;
typedef struct {
uint8_t LanguageId;
uint8_t CpuTypeId;
} CFileLanguageIdAndTypeIdType;
struct XCOFFSymbolEntry32 {
typedef struct {
support::big32_t Magic; // Zero indicates name in string table.
support::ubig32_t Offset;
} NameInStrTblType;
union {
char SymbolName[XCOFF::NameSize];
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 XCOFFSymbolEntry64 {
support::ubig64_t Value; // Symbol value; storage class-dependent.
support::ubig32_t Offset;
support::big16_t SectionNumber;
union {
support::ubig16_t SymbolType;
CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId;
};
XCOFF::StorageClass StorageClass;
uint8_t NumberOfAuxEntries;
};
class XCOFFSymbolRef {
public:
enum { NAME_IN_STR_TBL_MAGIC = 0x0 };
XCOFFSymbolRef(DataRefImpl SymEntDataRef,
const XCOFFObjectFile *OwningObjectPtr)
: SymEntDataRef(SymEntDataRef), OwningObjectPtr(OwningObjectPtr){};
: OwningObjectPtr(OwningObjectPtr) {
assert(OwningObjectPtr && "OwningObjectPtr cannot be nullptr!");
assert(SymEntDataRef.p != 0 &&
"Symbol table entry pointer cannot be nullptr!");
XCOFF::StorageClass getStorageClass() const;
uint8_t getNumberOfAuxEntries() const;
const XCOFFCsectAuxEnt32 *getXCOFFCsectAuxEnt32() const;
uint16_t getType() const;
int16_t getSectionNumber() const;
if (OwningObjectPtr->is64Bit())
Entry64 = reinterpret_cast<const XCOFFSymbolEntry64 *>(SymEntDataRef.p);
else
Entry32 = reinterpret_cast<const XCOFFSymbolEntry32 *>(SymEntDataRef.p);
}
bool hasCsectAuxEnt() const;
uint64_t getValue() const { return Entry32 ? getValue32() : getValue64(); }
uint32_t getValue32() const { return Entry32->Value; }
uint64_t getValue64() const { return Entry64->Value; }
#define GETVALUE(X) Entry32 ? Entry32->X : Entry64->X
int16_t getSectionNumber() const { return GETVALUE(SectionNumber); }
uint16_t getSymbolType() const { return GETVALUE(SymbolType); }
uint8_t getLanguageIdForCFile() const {
assert(getStorageClass() == XCOFF::C_FILE &&
"This interface is for C_FILE only.");
return GETVALUE(CFileLanguageIdAndTypeId.LanguageId);
}
uint8_t getCPUTypeIddForCFile() const {
assert(getStorageClass() == XCOFF::C_FILE &&
"This interface is for C_FILE only.");
return GETVALUE(CFileLanguageIdAndTypeId.CpuTypeId);
}
XCOFF::StorageClass getStorageClass() const { return GETVALUE(StorageClass); }
uint8_t getNumberOfAuxEntries() const { return GETVALUE(NumberOfAuxEntries); }
#undef GETVALUE
uintptr_t getEntryAddress() const {
return Entry32 ? reinterpret_cast<uintptr_t>(Entry32)
: reinterpret_cast<uintptr_t>(Entry64);
}
Expected<StringRef> getName() const;
bool isFunction() const;
bool isCsectSymbol() const;
Expected<XCOFFCsectAuxRef> getXCOFFCsectAuxRef() const;
private:
const XCOFFObjectFile *OwningObjectPtr;
const XCOFFSymbolEntry32 *Entry32 = nullptr;
const XCOFFSymbolEntry64 *Entry64 = nullptr;
};
class TBVectorExt {

View File

@ -24,8 +24,8 @@ using namespace XCOFF;
namespace object {
static const uint8_t FunctionSym = 0x20;
static const uint8_t SymTypeMask = 0x07;
static const uint16_t NoRelMask = 0x0001;
static const size_t SymbolAuxTypeOffset = 17;
// Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
// 'M'. Returns a pointer to the underlying object on success.
@ -83,6 +83,19 @@ uint8_t XCOFFRelocation32::getRelocatedLength() const {
return (Info & XR_BIASED_LENGTH_MASK) + 1;
}
uintptr_t
XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress,
uint32_t Distance) {
return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize);
}
const XCOFF::SymbolAuxType *
XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const {
assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
return viewAs<XCOFF::SymbolAuxType>(
getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset));
}
void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
uintptr_t TableAddress) const {
if (Addr < TableAddress)
@ -115,14 +128,12 @@ XCOFFObjectFile::toSection64(DataRefImpl Ref) const {
return viewAs<XCOFFSectionHeader64>(Ref.p);
}
const XCOFFSymbolEntry *XCOFFObjectFile::toSymbolEntry(DataRefImpl Ref) const {
assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const {
assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!");
#ifndef NDEBUG
checkSymbolEntryPointer(Ref.p);
#endif
auto SymEntPtr = viewAs<XCOFFSymbolEntry>(Ref.p);
return SymEntPtr;
return XCOFFSymbolRef(Ref, this);
}
const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const {
@ -148,15 +159,15 @@ XCOFFObjectFile::sectionHeaderTable64() const {
}
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
SymEntPtr += SymEntPtr->NumberOfAuxEntries + 1;
uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress(
Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1);
#ifndef NDEBUG
// This function is used by basic_symbol_iterator, which allows to
// point to the end-of-symbol-table address.
if (reinterpret_cast<uintptr_t>(SymEntPtr) != getEndOfSymbolTableAddress())
checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(SymEntPtr));
if (NextSymbolAddr != getEndOfSymbolTableAddress())
checkSymbolEntryPointer(NextSymbolAddr);
#endif
Symb.p = reinterpret_cast<uintptr_t>(SymEntPtr);
Symb.p = NextSymbolAddr;
}
Expected<StringRef>
@ -178,34 +189,21 @@ XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
Expected<StringRef>
XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const {
if (CFileEntPtr->NameInStrTbl.Magic !=
XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
return generateXCOFFFixedNameStringRef(CFileEntPtr->Name);
return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset);
}
Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const {
const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
// 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");
if (SymEntPtr->NameInStrTbl.Magic != XCOFFSymbolEntry::NAME_IN_STR_TBL_MAGIC)
return generateXCOFFFixedNameStringRef(SymEntPtr->SymbolName);
return getStringTableEntry(SymEntPtr->NameInStrTbl.Offset);
return toSymbolRef(Symb).getName();
}
Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const {
assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
return toSymbolEntry(Symb)->Value;
return toSymbolRef(Symb).getValue();
}
uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
return toSymbolEntry(Symb)->Value;
return toSymbolRef(Symb).getValue();
}
uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
@ -222,8 +220,7 @@ XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
Expected<section_iterator>
XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
const XCOFFSymbolEntry *SymEntPtr = toSymbolEntry(Symb);
int16_t SectNum = SymEntPtr->SectionNumber;
const int16_t SectNum = toSymbolRef(Symb).getSectionNumber();
if (isReservedSectionNumber(SectNum))
return section_end();
@ -376,7 +373,7 @@ symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
return symbol_end();
DataRefImpl SymDRI;
SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
SymDRI.p = getSymbolEntryAddressByIndex(Index);
return symbol_iterator(SymbolRef(SymDRI, this));
}
@ -402,19 +399,15 @@ Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
}
basic_symbol_iterator XCOFFObjectFile::symbol_begin() const {
if (is64Bit())
report_fatal_error("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 {
if (is64Bit())
report_fatal_error("64-bit support not implemented yet");
DataRefImpl SymDRI;
SymDRI.p = reinterpret_cast<uintptr_t>(
SymbolTblPtr + getLogicalNumberOfSymbolTableEntries32());
const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries();
SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries);
return basic_symbol_iterator(SymbolRef(SymDRI, this));
}
@ -501,9 +494,8 @@ Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
}
Expected<StringRef>
XCOFFObjectFile::getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const {
assert(!is64Bit() && "Symbol table support not implemented for 64-bit.");
int16_t SectionNum = SymEntPtr->SectionNumber;
XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const {
const int16_t SectionNum = SymEntPtr.getSectionNumber();
switch (SectionNum) {
case XCOFF::N_DEBUG:
@ -564,10 +556,13 @@ uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const {
return fileHeader64()->NumberOfSymTableEntries;
}
uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
return is64Bit() ? getNumberOfSymbolTableEntries64()
: getLogicalNumberOfSymbolTableEntries32();
}
uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const {
uint32_t NumberOfSymTableEntries =
is64Bit() ? getNumberOfSymbolTableEntries64()
: getLogicalNumberOfSymbolTableEntries32();
const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr),
XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries);
}
@ -593,16 +588,20 @@ uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
XCOFF::SymbolTableEntrySize;
}
uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
return getAdvancedSymbolEntryAddress(
reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
}
Expected<StringRef>
XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
if (is64Bit())
report_fatal_error("64-bit symbol table support not implemented yet.");
const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
if (Index >= getLogicalNumberOfSymbolTableEntries32())
if (Index >= NumberOfSymTableEntries)
return errorCodeToError(object_error::invalid_symbol_index);
DataRefImpl SymDRI;
SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
SymDRI.p = getSymbolEntryAddressByIndex(Index);
return getSymbolName(SymDRI);
}
@ -745,20 +744,21 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
Obj->SectionHeaderTable = SecHeadersOrErr.get();
}
// 64-bit object supports only file header and section headers for now.
if (Obj->is64Bit())
return std::move(Obj);
const uint32_t NumberOfSymbolTableEntries =
Obj->getNumberOfSymbolTableEntries();
// If there is no symbol table we are done parsing the memory buffer.
if (Obj->getLogicalNumberOfSymbolTableEntries32() == 0)
if (NumberOfSymbolTableEntries == 0)
return std::move(Obj);
// Parse symbol table.
CurOffset = Obj->fileHeader32()->SymbolTableOffset;
uint64_t SymbolTableSize = (uint64_t)(sizeof(XCOFFSymbolEntry)) *
Obj->getLogicalNumberOfSymbolTableEntries32();
CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64()
: Obj->getSymbolTableOffset32();
const uint64_t SymbolTableSize =
static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) *
NumberOfSymbolTableEntries;
auto SymTableOrErr =
getObject<XCOFFSymbolEntry>(Data, Base + CurOffset, SymbolTableSize);
getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
if (Error E = SymTableOrErr.takeError())
return std::move(E);
Obj->SymbolTblPtr = SymTableOrErr.get();
@ -780,74 +780,103 @@ ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef,
return XCOFFObjectFile::create(FileType, MemBufRef);
}
XCOFF::StorageClass XCOFFSymbolRef::getStorageClass() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->StorageClass;
bool XCOFFSymbolRef::isFunction() const {
if (!isCsectSymbol())
return false;
if (getSymbolType() & FunctionSym)
return true;
Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef();
if (!ExpCsectAuxEnt)
return false;
const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get();
// A function definition should be a label definition.
// FIXME: This is not necessarily the case when -ffunction-sections is
// enabled.
if (!CsectAuxRef.isLabel())
return false;
if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR)
return false;
const int16_t SectNum = getSectionNumber();
Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
if (!SI) {
// If we could not get the section, then this symbol should not be
// a function. So consume the error and return `false` to move on.
consumeError(SI.takeError());
return false;
}
return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
}
uint8_t XCOFFSymbolRef::getNumberOfAuxEntries() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->NumberOfAuxEntries;
}
// TODO: The function needs to return an error if there is no csect auxiliary
// entry.
const XCOFFCsectAuxEnt32 *XCOFFSymbolRef::getXCOFFCsectAuxEnt32() const {
assert(!OwningObjectPtr->is64Bit() &&
"32-bit interface called on 64-bit object file.");
assert(hasCsectAuxEnt() && "No Csect Auxiliary Entry is found.");
// In XCOFF32, the csect auxilliary entry is always the last auxiliary
// entry for the symbol.
uintptr_t AuxAddr = getWithOffset(
SymEntDataRef.p, XCOFF::SymbolTableEntrySize * getNumberOfAuxEntries());
#ifndef NDEBUG
OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
#endif
return reinterpret_cast<const XCOFFCsectAuxEnt32 *>(AuxAddr);
}
uint16_t XCOFFSymbolRef::getType() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SymbolType;
}
int16_t XCOFFSymbolRef::getSectionNumber() const {
return OwningObjectPtr->toSymbolEntry(SymEntDataRef)->SectionNumber;
}
// TODO: The function name needs to be changed to express the purpose of the
// function.
bool XCOFFSymbolRef::hasCsectAuxEnt() const {
bool XCOFFSymbolRef::isCsectSymbol() const {
XCOFF::StorageClass SC = getStorageClass();
return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT ||
SC == XCOFF::C_HIDEXT);
}
bool XCOFFSymbolRef::isFunction() const {
if (OwningObjectPtr->is64Bit())
report_fatal_error("64-bit support is unimplemented yet.");
Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
assert(isCsectSymbol() &&
"Calling csect symbol interface with a non-csect symbol.");
if (getType() & FunctionSym)
return true;
uint8_t NumberOfAuxEntries = getNumberOfAuxEntries();
if (!hasCsectAuxEnt())
return false;
Expected<StringRef> NameOrErr = getName();
if (auto Err = NameOrErr.takeError())
return std::move(Err);
const XCOFFCsectAuxEnt32 *CsectAuxEnt = getXCOFFCsectAuxEnt32();
if (!NumberOfAuxEntries) {
return createStringError(object_error::parse_failed,
"csect symbol \"" + *NameOrErr +
"\" contains no auxiliary entry");
}
// A function definition should be a label definition.
if ((CsectAuxEnt->SymbolAlignmentAndType & SymTypeMask) != XCOFF::XTY_LD)
return false;
if (!OwningObjectPtr->is64Bit()) {
// In XCOFF32, the csect auxilliary entry is always the last auxiliary
// entry for the symbol.
uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
getEntryAddress(), NumberOfAuxEntries);
return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr));
}
if (CsectAuxEnt->StorageMappingClass != XCOFF::XMC_PR)
return false;
// XCOFF64 uses SymbolAuxType to identify the auxiliary entry type.
// We need to iterate through all the auxiliary entries to find it.
for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) {
uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
getEntryAddress(), Index);
if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) ==
XCOFF::SymbolAuxType::AUX_CSECT) {
#ifndef NDEBUG
OwningObjectPtr->checkSymbolEntryPointer(AuxAddr);
#endif
return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr));
}
}
int16_t SectNum = getSectionNumber();
Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum);
if (!SI)
return false;
return createStringError(
object_error::parse_failed,
"a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\"");
}
return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT);
Expected<StringRef> XCOFFSymbolRef::getName() const {
// A storage class value with the high-order bit on indicates that the name is
// a symbolic debugger stabstring.
if (getStorageClass() & 0x80)
return StringRef("Unimplemented Debug Name");
if (Entry32) {
if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC)
return generateXCOFFFixedNameStringRef(Entry32->SymbolName);
return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset);
}
return OwningObjectPtr->getStringTableEntry(Entry64->Offset);
}
// Explictly instantiate template classes.

View File

@ -0,0 +1,96 @@
# REQUIRES: powerpc-registered-target
# RUN: llvm-objdump -D %p/Inputs/xcoff-section-headers64.o | \
# RUN: FileCheck --check-prefixes=COMMON,PLAIN %s
# RUN: llvm-objdump -D --symbol-description %p/Inputs/xcoff-section-headers64.o | \
# RUN: FileCheck --check-prefixes=COMMON,DESC %s
# RUN: not --crash llvm-objdump -D -r --symbol-description %p/Inputs/xcoff-section-headers64.o 2>&1 | \
# RUN: FileCheck --check-prefix=ERROR %s
# ERROR: 64-bit support not implemented yet
## xcoff-section-headers64.o Compiled with IBM XL C/C++ for AIX, V16.1.0
## compiler command: xlc -q64 -qtls -o xcoff-section-headers64.o -c test.c
## test.c:
## int a;
## int b = 12345;
## __thread int c;
## __thread double d = 3.14159;
##
## int func(void) {
## return a;
## }
COMMON: Inputs/xcoff-section-headers64.o: file format aix5coff64-rs6000
COMMON: Disassembly of section .text:
COMMON-EMPTY:
PLAIN: 0000000000000000 <.func>:
DESC: 0000000000000000 (idx: 6) .func:
COMMON-NEXT: 0: e8 62 00 08 ld 3, 8(2)
COMMON-NEXT: 4: e8 63 00 02 lwa 3, 0(3)
COMMON-NEXT: 8: 4e 80 00 20 blr
COMMON-NEXT: c: 00 00 00 00 <unknown>
COMMON-NEXT: 10: 00 00 20 40 <unknown>
COMMON-NEXT: 14: 00 00 00 01 <unknown>
COMMON-NEXT: 18: 00 00 00 0c <unknown>
COMMON-NEXT: 1c: 00 04 66 75 <unknown>
COMMON-NEXT: 20: 6e 63 00 00 xoris 3, 19, 0
COMMON-NEXT: ...
COMMON-EMPTY:
COMMON-NEXT: Disassembly of section .data:
COMMON-EMPTY:
PLAIN: 0000000000000080 <func>:
DESC: 0000000000000080 (idx: 12) func[TC]:
COMMON-NEXT: 80: 00 00 00 00 <unknown>
COMMON-NEXT: 84: 00 00 00 a8 <unknown>
COMMON-EMPTY:
PLAIN: 0000000000000088 <a>:
DESC: 0000000000000088 (idx: 16) a[TC]:
COMMON-NEXT: 88: 00 00 00 00 <unknown>
COMMON-NEXT: 8c: 00 00 00 c8 <unknown>
COMMON-EMPTY:
PLAIN: 0000000000000090 <b>:
DESC: 0000000000000090 (idx: 20) b[TC]:
COMMON-NEXT: 90: 00 00 00 00 <unknown>
COMMON-NEXT: 94: 00 00 00 c0 <unknown>
COMMON-EMPTY:
PLAIN: 0000000000000098 <c>:
DESC: 0000000000000098 (idx: 24) c[TC]:
COMMON-NEXT: 98: 00 00 00 00 <unknown>
COMMON-NEXT: 9c: 00 00 00 08 <unknown>
COMMON-EMPTY:
PLAIN: 00000000000000a0 <d>:
DESC: 00000000000000a0 (idx: 28) d[TC]:
COMMON-NEXT: ...
COMMON-EMPTY:
PLAIN: 00000000000000a8 <func>:
DESC: 00000000000000a8 (idx: 10) func[DS]:
COMMON-NEXT: ...
COMMON-NEXT: b4: 00 00 00 80 <unknown>
COMMON-NEXT: ...
COMMON-EMPTY:
PLAIN: 00000000000000c0 <b>:
DESC: 00000000000000c0 (idx: 18) b[RW]:
COMMON-NEXT: c0: 00 00 30 39 <unknown>
COMMON-NEXT: c4: 00 00 00 00 <unknown>
COMMON-EMPTY:
COMMON-NEXT: Disassembly of section .bss:
COMMON-EMPTY:
PLAIN: 00000000000000c8 <a>:
DESC: 00000000000000c8 (idx: 14) a[RW]:
COMMON-NEXT: ...
COMMON-EMPTY:
COMMON-NEXT: Disassembly of section .tdata:
COMMON-EMPTY:
PLAIN: 0000000000000000 <d>:
DESC: 0000000000000000 (idx: 26) d[TL]:
COMMON-NEXT: 0: 40 09 21 f9 bdnzfl 9, 0x21f8
COMMON-NEXT: 4: f0 1b 86 6e <unknown>
COMMON-EMPTY:
COMMON-NEXT: Disassembly of section .tbss:
COMMON-EMPTY:
PLAIN: 0000000000000008 <c>:
DESC: 0000000000000008 (idx: 22) c[UL]:
COMMON-NEXT: ...

Binary file not shown.

View File

@ -0,0 +1,19 @@
## This file tests the raw data output ability when a file auxiliary entry does
## not have the matching auxiliary type.
# RUN: llvm-readobj --symbols %p/Inputs/file-aux-wrong64.o | FileCheck %s
# CHECK: Symbols [
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Index: 0
# CHECK-NEXT: Name: .file
# CHECK-NEXT: Value (SymbolTableIndex): 0x0
# CHECK-NEXT: Section: N_DEBUG
# CHECK-NEXT: Source Language ID: 0xC
# CHECK-NEXT: CPU Version ID: TCPU_PPC64 (0x2)
# CHECK-NEXT: StorageClass: C_FILE (0x67)
# CHECK-NEXT: NumberOfAuxEntries: 1
# CHECK-NEXT: !Unexpected raw auxiliary entry data:
# CHECK-NEXT: 612e7300 00000000 00000000 00000000 00fb
# CHECK-NEXT: }
# CHECK-NEXT: ]

View File

@ -0,0 +1,387 @@
## This file tests the ability of llvm-readobj to display the symbol table for a
## 64-bit XCOFF object file.
## The object file used is generated by the following source file
## and command on AIX:
##
## > cat test8.c
##
## extern int i;
## extern int TestforXcoff;
## extern int fun(int i);
## static int static_i;
## char* p="abcd";
## int fun1(int j) {
## static_i++;
## j++;
## j=j+*p;
## return j;
## }
##
## int main() {
## i++;
## fun(i);
## return fun1(i);
## }
##
## > xlc -q64 -c test8.c -o symbol64.o
# RUN: llvm-readobj --symbols %p/Inputs/symbol64.o | \
# RUN: FileCheck --check-prefix=SYMBOL64 %s
# SYMBOL64: File: {{.*}}symbol64.o
# SYMBOL64-NEXT: Format: aix5coff64-rs6000
# SYMBOL64-NEXT: Arch: powerpc64
# SYMBOL64-NEXT: AddressSize: 64bit
# SYMBOL64-NEXT: Symbols [
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 0
# SYMBOL64-NEXT: Name: .file
# SYMBOL64-NEXT: Value (SymbolTableIndex): 0x0
# SYMBOL64-NEXT: Section: N_DEBUG
# SYMBOL64-NEXT: Source Language ID: TB_C (0x0)
# SYMBOL64-NEXT: CPU Version ID: TCPU_PPC64 (0x2)
# SYMBOL64-NEXT: StorageClass: C_FILE (0x67)
# SYMBOL64-NEXT: NumberOfAuxEntries: 3
# SYMBOL64-NEXT: File Auxiliary Entry {
# SYMBOL64-NEXT: Index: 1
# SYMBOL64-NEXT: Name: test64.c
# SYMBOL64-NEXT: Type: XFT_FN (0x0)
# SYMBOL64-NEXT: Auxiliary Type: AUX_FILE (0xFC)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: File Auxiliary Entry {
# SYMBOL64-NEXT: Index: 2
# SYMBOL64-NEXT: Name: Mon Aug 10 16:07:48 2020
# SYMBOL64-NEXT: Type: XFT_CT (0x1)
# SYMBOL64-NEXT: Auxiliary Type: AUX_FILE (0xFC)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: File Auxiliary Entry {
# SYMBOL64-NEXT: Index: 3
# SYMBOL64-NEXT: Name: IBM XL C for AIX, Version 16.1.0.6
# SYMBOL64-NEXT: Type: XFT_CV (0x2)
# SYMBOL64-NEXT: Auxiliary Type: AUX_FILE (0xFC)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 4
# SYMBOL64-NEXT: Name:
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0
# SYMBOL64-NEXT: Section: .text
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 5
# SYMBOL64-NEXT: SectionLen: 256
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 7
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 6
# SYMBOL64-NEXT: Name: .fun1
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0
# SYMBOL64-NEXT: Section: .text
# SYMBOL64-NEXT: Type: 0x20
# SYMBOL64-NEXT: StorageClass: C_EXT (0x2)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 7
# SYMBOL64-NEXT: ContainingCsectSymbolIndex: 4
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 0
# SYMBOL64-NEXT: SymbolType: XTY_LD (0x2)
# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 8
# SYMBOL64-NEXT: Name: .main
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x80
# SYMBOL64-NEXT: Section: .text
# SYMBOL64-NEXT: Type: 0x20
# SYMBOL64-NEXT: StorageClass: C_EXT (0x2)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 9
# SYMBOL64-NEXT: ContainingCsectSymbolIndex: 4
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 0
# SYMBOL64-NEXT: SymbolType: XTY_LD (0x2)
# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 10
# SYMBOL64-NEXT: Name: TOC
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x100
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 11
# SYMBOL64-NEXT: SectionLen: 0
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 2
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_TC0 (0xF)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 12
# SYMBOL64-NEXT: Name:
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x128
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 13
# SYMBOL64-NEXT: SectionLen: 8
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 14
# SYMBOL64-NEXT: Name:
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x168
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 15
# SYMBOL64-NEXT: SectionLen: 5
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_RO (0x1)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 16
# SYMBOL64-NEXT: Name: _$STATIC_BSS
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x170
# SYMBOL64-NEXT: Section: .bss
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 17
# SYMBOL64-NEXT: SectionLen: 4
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 2
# SYMBOL64-NEXT: SymbolType: XTY_CM (0x3)
# SYMBOL64-NEXT: StorageMappingClass: XMC_RW (0x5)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 18
# SYMBOL64-NEXT: Name: _$STATIC_BSS
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x108
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 19
# SYMBOL64-NEXT: SectionLen: 8
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 20
# SYMBOL64-NEXT: Name: fun1
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x130
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_EXT (0x2)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 21
# SYMBOL64-NEXT: SectionLen: 24
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_DS (0xA)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 22
# SYMBOL64-NEXT: Name: fun1
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x100
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 23
# SYMBOL64-NEXT: SectionLen: 8
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 24
# SYMBOL64-NEXT: Name: p
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x160
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_EXT (0x2)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 25
# SYMBOL64-NEXT: SectionLen: 8
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_RW (0x5)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 26
# SYMBOL64-NEXT: Name: p
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x110
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 27
# SYMBOL64-NEXT: SectionLen: 8
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 28
# SYMBOL64-NEXT: Name: main
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x148
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_EXT (0x2)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 29
# SYMBOL64-NEXT: SectionLen: 24
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_DS (0xA)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 30
# SYMBOL64-NEXT: Name: main
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x118
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 31
# SYMBOL64-NEXT: SectionLen: 8
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 32
# SYMBOL64-NEXT: Name: i
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0
# SYMBOL64-NEXT: Section: N_UNDEF
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_EXT (0x2)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 33
# SYMBOL64-NEXT: SectionLen: 0
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 0
# SYMBOL64-NEXT: SymbolType: XTY_ER (0x0)
# SYMBOL64-NEXT: StorageMappingClass: XMC_UA (0x4)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 34
# SYMBOL64-NEXT: Name: i
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x120
# SYMBOL64-NEXT: Section: .data
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_HIDEXT (0x6B)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 35
# SYMBOL64-NEXT: SectionLen: 8
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 3
# SYMBOL64-NEXT: SymbolType: XTY_SD (0x1)
# SYMBOL64-NEXT: StorageMappingClass: XMC_TC (0x3)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: Symbol {
# SYMBOL64-NEXT: Index: 36
# SYMBOL64-NEXT: Name: .fun
# SYMBOL64-NEXT: Value (RelocatableAddress): 0x0
# SYMBOL64-NEXT: Section: N_UNDEF
# SYMBOL64-NEXT: Type: 0x0
# SYMBOL64-NEXT: StorageClass: C_EXT (0x2)
# SYMBOL64-NEXT: NumberOfAuxEntries: 1
# SYMBOL64-NEXT: CSECT Auxiliary Entry {
# SYMBOL64-NEXT: Index: 37
# SYMBOL64-NEXT: SectionLen: 0
# SYMBOL64-NEXT: ParameterHashIndex: 0x0
# SYMBOL64-NEXT: TypeChkSectNum: 0x0
# SYMBOL64-NEXT: SymbolAlignmentLog2: 0
# SYMBOL64-NEXT: SymbolType: XTY_ER (0x0)
# SYMBOL64-NEXT: StorageMappingClass: XMC_PR (0x0)
# SYMBOL64-NEXT: Auxiliary Type: AUX_CSECT (0xFB)
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: }
# SYMBOL64-NEXT: ]

View File

@ -46,22 +46,30 @@ Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile *Obj,
Optional<XCOFF::StorageMappingClass>
objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile *Obj,
const SymbolRef &Sym) {
XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj);
const XCOFFSymbolRef SymRef = Obj->toSymbolRef(Sym.getRawDataRefImpl());
if (SymRef.hasCsectAuxEnt())
return SymRef.getXCOFFCsectAuxEnt32()->StorageMappingClass;
if (!SymRef.isCsectSymbol())
return None;
return None;
auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
if (!CsectAuxEntOrErr)
return None;
return CsectAuxEntOrErr.get().getStorageMappingClass();
}
bool objdump::isLabel(const XCOFFObjectFile *Obj, const SymbolRef &Sym) {
XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj);
const XCOFFSymbolRef SymRef = Obj->toSymbolRef(Sym.getRawDataRefImpl());
if (SymRef.hasCsectAuxEnt())
return SymRef.getXCOFFCsectAuxEnt32()->isLabel();
if (!SymRef.isCsectSymbol())
return false;
return false;
auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
if (!CsectAuxEntOrErr)
return false;
return CsectAuxEntOrErr.get().isLabel();
}
std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,

View File

@ -40,7 +40,7 @@ private:
template <typename T> void printGenericSectionHeader(T &Sec) const;
template <typename T> void printOverflowSectionHeader(T &Sec) const;
void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr);
void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
void printSymbol(const SymbolRef &);
void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections);
@ -164,10 +164,17 @@ static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
#undef ECase
};
static const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {
#define ECase(X) \
{ #X, XCOFF::X }
ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),
ECase(AUX_CSECT), ECase(AUX_SECT)
#undef ECase
};
void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
if (Obj.is64Bit())
report_fatal_error(
"Printing for File Auxiliary Entry in 64-bit is unimplemented.");
assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&
"Mismatched auxiliary type!");
StringRef FileName =
unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
DictScope SymDs(W, "File Auxiliary Entry");
@ -176,6 +183,10 @@ void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
W.printString("Name", FileName);
W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
makeArrayRef(FileStringType));
if (Obj.is64Bit()) {
W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
makeArrayRef(SymAuxType));
}
}
static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
@ -198,27 +209,32 @@ static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
#undef ECase
};
void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {
assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&
"Mismatched auxiliary type!");
DictScope SymDs(W, "CSECT Auxiliary Entry");
W.printNumber("Index",
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
if (AuxEntPtr->isLabel())
W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength);
else
W.printNumber("SectionLen", AuxEntPtr->SectionOrLength);
W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));
W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"
: "SectionLen",
AuxEntRef.getSectionOrLength());
W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());
W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());
// Print out symbol alignment and type.
W.printNumber("SymbolAlignmentLog2", AuxEntPtr->getAlignmentLog2());
W.printEnum("SymbolType", AuxEntPtr->getSymbolType(),
W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
makeArrayRef(CsectSymbolTypeClass));
W.printEnum("StorageMappingClass",
static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
makeArrayRef(CsectStorageMappingClass));
W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
if (Obj.is64Bit()) {
W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
makeArrayRef(SymAuxType));
} else {
W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
}
}
void XCOFFDumper::printSectAuxEntForStat(
@ -300,53 +316,62 @@ static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
};
void XCOFFDumper::printSymbol(const SymbolRef &S) {
if (Obj.is64Bit())
report_fatal_error("64-bit support is unimplemented.");
DataRefImpl SymbolDRI = S.getRawDataRefImpl();
const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
DictScope SymDs(W, "Symbol");
StringRef SymbolName =
unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());
W.printNumber("Index",
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
W.printNumber("Index", Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()));
W.printString("Name", SymbolName);
W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
SymbolEntPtr->Value);
W.printHex(GetSymbolValueName(SymbolEntRef.getStorageClass()),
SymbolEntRef.getValue());
StringRef SectionName =
unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));
W.printString("Section", SectionName);
if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
W.printEnum("Source Language ID",
SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
if (SymbolEntRef.getStorageClass() == XCOFF::C_FILE) {
W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
makeArrayRef(CFileLangIdClass));
W.printEnum("CPU Version ID",
SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
makeArrayRef(CFileCpuIdClass));
} else
W.printHex("Type", SymbolEntPtr->SymbolType);
W.printHex("Type", SymbolEntRef.getSymbolType());
W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
W.printEnum("StorageClass",
static_cast<uint8_t>(SymbolEntRef.getStorageClass()),
makeArrayRef(SymStorageClass));
W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
if (NumberOfAuxEntries == 0)
return;
switch (XCOFFSymRef.getStorageClass()) {
switch (SymbolEntRef.getStorageClass()) {
case XCOFF::C_FILE:
// If the symbol is C_FILE and has auxiliary entries...
for (int i = 1; i <= NumberOfAuxEntries; i++) {
for (int I = 1; I <= NumberOfAuxEntries; I++) {
uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
SymbolEntRef.getEntryAddress(), I);
if (Obj.is64Bit() &&
*Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {
W.startLine() << "!Unexpected raw auxiliary entry data:\n";
W.startLine() << format_bytes(
ArrayRef<uint8_t>(
reinterpret_cast<const uint8_t *>(AuxAddress),
XCOFF::SymbolTableEntrySize),
0, XCOFF::SymbolTableEntrySize)
<< "\n";
continue;
}
const XCOFFFileAuxEnt *FileAuxEntPtr =
reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
reinterpret_cast<const XCOFFFileAuxEnt *>(AuxAddress);
#ifndef NDEBUG
Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
#endif
@ -355,34 +380,52 @@ void XCOFFDumper::printSymbol(const SymbolRef &S) {
break;
case XCOFF::C_EXT:
case XCOFF::C_WEAKEXT:
case XCOFF::C_HIDEXT:
case XCOFF::C_HIDEXT: {
// If the symbol is for a function, and it has more than 1 auxiliary entry,
// then one of them must be function auxiliary entry which we do not
// support yet.
if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
if (SymbolEntRef.isFunction() && NumberOfAuxEntries >= 2)
report_fatal_error("Function auxiliary entry printing is unimplemented.");
// If there is more than 1 auxiliary entry, instead of printing out
// error information, print out the raw Auxiliary entry from 1st till
// the last - 1. The last one must be a CSECT Auxiliary Entry.
for (int i = 1; i < NumberOfAuxEntries; i++) {
// error information, print out the raw Auxiliary entry.
// For 32-bit object, print from first to the last - 1. The last one must be
// a CSECT Auxiliary Entry.
// For 64-bit object, print from first to last and skips if SymbolAuxType is
// AUX_CSECT.
for (int I = 1; I <= NumberOfAuxEntries; I++) {
if (I == NumberOfAuxEntries && !Obj.is64Bit())
break;
uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
SymbolEntRef.getEntryAddress(), I);
if (Obj.is64Bit() &&
*Obj.getSymbolAuxType(AuxAddress) == XCOFF::SymbolAuxType::AUX_CSECT)
continue;
W.startLine() << "!Unexpected raw auxiliary entry data:\n";
W.startLine() << format_bytes(
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(AuxAddress),
XCOFF::SymbolTableEntrySize));
}
// The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
if (!ErrOrCsectAuxRef)
reportUniqueWarning(ErrOrCsectAuxRef.takeError());
else
printCsectAuxEnt(*ErrOrCsectAuxRef);
break;
}
case XCOFF::C_STAT:
if (NumberOfAuxEntries > 1)
report_fatal_error(
"C_STAT symbol should not have more than 1 auxiliary entry.");
const XCOFFSectAuxEntForStat *StatAuxEntPtr;
StatAuxEntPtr =
reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
StatAuxEntPtr = reinterpret_cast<const XCOFFSectAuxEntForStat *>(
XCOFFObjectFile::getAdvancedSymbolEntryAddress(
SymbolEntRef.getEntryAddress(), 1));
#ifndef NDEBUG
Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
#endif
@ -398,7 +441,9 @@ void XCOFFDumper::printSymbol(const SymbolRef &S) {
for (int i = 1; i <= NumberOfAuxEntries; i++) {
W.startLine() << "!Unexpected raw auxiliary entry data:\n";
W.startLine() << format_bytes(
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(
XCOFFObjectFile::getAdvancedSymbolEntryAddress(
SymbolEntRef.getEntryAddress(), i)),
XCOFF::SymbolTableEntrySize));
}
break;

View File

@ -55,7 +55,7 @@ std::error_code XCOFFDumper::dumpSymbols() {
for (const SymbolRef &S : Obj.symbols()) {
DataRefImpl SymbolDRI = S.getRawDataRefImpl();
const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
const XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
XCOFFYAML::Symbol Sym;
Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI);
@ -64,18 +64,18 @@ std::error_code XCOFFDumper::dumpSymbols() {
}
Sym.SymbolName = SymNameRefOrErr.get();
Sym.Value = SymbolEntPtr->Value;
Sym.Value = SymbolEntRef.getValue();
Expected<StringRef> SectionNameRefOrErr =
Obj.getSymbolSectionName(SymbolEntPtr);
Obj.getSymbolSectionName(SymbolEntRef);
if (!SectionNameRefOrErr)
return errorToErrorCode(SectionNameRefOrErr.takeError());
Sym.SectionName = SectionNameRefOrErr.get();
Sym.Type = SymbolEntPtr->SymbolType;
Sym.StorageClass = SymbolEntPtr->StorageClass;
Sym.NumberOfAuxEntries = SymbolEntPtr->NumberOfAuxEntries;
Sym.Type = SymbolEntRef.getSymbolType();
Sym.StorageClass = SymbolEntRef.getStorageClass();
Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
Symbols.push_back(Sym);
}

View File

@ -384,3 +384,115 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtExtLongTBTable) {
"unexpected end of data at offset 0x2c while reading [0x2c, 0x2d)"));
EXPECT_EQ(Size, 44u);
}
TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef32) {
uint8_t XCOFF32Binary[] = {
// File header.
0x01, 0xdf, 0x00, 0x01, 0x5f, 0x58, 0xf8, 0x95, 0x00, 0x00, 0x00, 0x3c,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
// Section header for empty .data section.
0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40,
// Start of symbol table.
// C_File symbol.
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xfe, 0x00, 0x03, 0x67, 0x01,
// File Auxiliary Entry.
0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Csect symbol.
0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x6b, 0x01,
// Csect auxiliary entry.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
ArrayRef<uint8_t> XCOFF32Ref(XCOFF32Binary, sizeof(XCOFF32Binary));
Expected<std::unique_ptr<ObjectFile>> XCOFFObjOrErr =
object::ObjectFile::createObjectFile(
MemoryBufferRef(toStringRef(XCOFF32Ref), "dummyXCOFF"),
file_magic::xcoff_object_32);
ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded());
const XCOFFObjectFile &File = *cast<XCOFFObjectFile>((*XCOFFObjOrErr).get());
DataRefImpl Ref;
Ref.p = File.getSymbolEntryAddressByIndex(2);
XCOFFSymbolRef SymRef = File.toSymbolRef(Ref);
Expected<XCOFFCsectAuxRef> CsectRefOrErr = SymRef.getXCOFFCsectAuxRef();
ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded());
// Set csect symbol's auxiliary entry count to 0.
XCOFF32Binary[113] = 0;
Expected<XCOFFCsectAuxRef> ExpectErr = SymRef.getXCOFFCsectAuxRef();
EXPECT_THAT_ERROR(
ExpectErr.takeError(),
FailedWithMessage("csect symbol \".data\" contains no auxiliary entry"));
}
TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef64) {
uint8_t XCOFF64Binary[] = {
// File header.
0x01, 0xf7, 0x00, 0x01, 0x5f, 0x59, 0x25, 0xeb, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
// Section header for empty .data section.
0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
// Start of symbol table.
// C_File symbol.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0xff, 0xfe, 0x00, 0x02, 0x67, 0x01,
// File Auxiliary Entry.
0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
// Csect symbol.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x01, 0x00, 0x00, 0x6b, 0x01,
// Csect auxiliary entry.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfb,
// String table.
0x00, 0x00, 0x00, 0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x2e, 0x64,
0x61, 0x74, 0x61, 0x00};
ArrayRef<uint8_t> XCOFF64Ref(XCOFF64Binary, sizeof(XCOFF64Binary));
Expected<std::unique_ptr<ObjectFile>> XCOFFObjOrErr =
object::ObjectFile::createObjectFile(
MemoryBufferRef(toStringRef(XCOFF64Ref), "dummyXCOFF"),
file_magic::xcoff_object_64);
ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded());
const XCOFFObjectFile &File = *cast<XCOFFObjectFile>((*XCOFFObjOrErr).get());
DataRefImpl Ref;
Ref.p = File.getSymbolEntryAddressByIndex(2);
XCOFFSymbolRef SymRef = File.toSymbolRef(Ref);
Expected<XCOFFCsectAuxRef> CsectRefOrErr = SymRef.getXCOFFCsectAuxRef();
ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded());
// Inject incorrect auxiliary type value.
XCOFF64Binary[167] = static_cast<uint8_t>(XCOFF::AUX_SYM);
Expected<XCOFFCsectAuxRef> NotFoundErr = SymRef.getXCOFFCsectAuxRef();
EXPECT_THAT_ERROR(
NotFoundErr.takeError(),
FailedWithMessage(
"a csect auxiliary entry is not found for symbol \".data\""));
// Set csect symbol's auxiliary entry count to 0.
XCOFF64Binary[149] = 0;
Expected<XCOFFCsectAuxRef> ExpectErr = SymRef.getXCOFFCsectAuxRef();
EXPECT_THAT_ERROR(
ExpectErr.takeError(),
FailedWithMessage("csect symbol \".data\" contains no auxiliary entry"));
}