Skip to content

Commit

Permalink
[AIX][XCOFF] 64-bit relocation reading support
Browse files Browse the repository at this point in the history
Support XCOFFDumper relocation reading support
This patch is part of D103696 partition

Reviewed By: daltenty, Helflym

Differential Revision: https://reviews.llvm.org/D104646
  • Loading branch information
Maryam Benimmar authored and daltenty committed Aug 20, 2021
1 parent 337bd67 commit 2cdfd0b
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 80 deletions.
19 changes: 14 additions & 5 deletions llvm/include/llvm/Object/XCOFFObjectFile.h
Expand Up @@ -228,7 +228,7 @@ struct XCOFFSectAuxEntForStat {
uint8_t Pad[10];
}; // 32-bit XCOFF file only.

struct XCOFFRelocation32 {
template <typename AddressType> struct XCOFFRelocation {
// Masks for packing/unpacking the r_rsize field of relocations.

// The msb is used to indicate if the bits being relocated are signed or
Expand All @@ -244,7 +244,7 @@ struct XCOFFRelocation32 {
static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;

public:
support::ubig32_t VirtualAddress;
AddressType VirtualAddress;
support::ubig32_t SymbolIndex;

// Packed field, see XR_* masks for details of packing.
Expand All @@ -260,6 +260,12 @@ struct XCOFFRelocation32 {
uint8_t getRelocatedLength() const;
};

extern template struct XCOFFRelocation<llvm::support::ubig32_t>;
extern template struct XCOFFRelocation<llvm::support::ubig64_t>;

struct XCOFFRelocation32 : XCOFFRelocation<llvm::support::ubig32_t> {};
struct XCOFFRelocation64 : XCOFFRelocation<llvm::support::ubig64_t> {};

class XCOFFSymbolRef;

class XCOFFObjectFile : public ObjectFile {
Expand All @@ -275,6 +281,7 @@ class XCOFFObjectFile : public ObjectFile {

const XCOFFSectionHeader32 *sectionHeaderTable32() const;
const XCOFFSectionHeader64 *sectionHeaderTable64() const;
template <typename T> const T *sectionHeaderTable() const;

size_t getFileHeaderSize() const;
size_t getSectionHeaderSize() const;
Expand Down Expand Up @@ -415,11 +422,12 @@ class XCOFFObjectFile : public ObjectFile {
void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;

// Relocation-related interfaces.
template <typename T>
Expected<uint32_t>
getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const;
getNumberOfRelocationEntries(const XCOFFSectionHeader<T> &Sec) const;

Expected<ArrayRef<XCOFFRelocation32>>
relocations(const XCOFFSectionHeader32 &) const;
template <typename Shdr, typename Reloc>
Expected<ArrayRef<Reloc>> relocations(const Shdr &Sec) const;

// This function returns string table entry.
Expected<StringRef> getStringTableEntry(uint32_t Offset) const;
Expand Down Expand Up @@ -572,6 +580,7 @@ class XCOFFTracebackTable {
Optional<uint8_t> ExtensionTable;

XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);

public:
/// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
/// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
Expand Down
197 changes: 137 additions & 60 deletions llvm/lib/Object/XCOFFObjectFile.cpp
Expand Up @@ -69,15 +69,18 @@ bool XCOFFSectionHeader<T>::isReservedSectionType() const {
return getSectionType() & SectionFlagsReservedMask;
}

bool XCOFFRelocation32::isRelocationSigned() const {
template <typename AddressType>
bool XCOFFRelocation<AddressType>::isRelocationSigned() const {
return Info & XR_SIGN_INDICATOR_MASK;
}

bool XCOFFRelocation32::isFixupIndicated() const {
template <typename AddressType>
bool XCOFFRelocation<AddressType>::isFixupIndicated() const {
return Info & XR_FIXUP_INDICATOR_MASK;
}

uint8_t XCOFFRelocation32::getRelocatedLength() const {
template <typename AddressType>
uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const {
// The relocation encodes the bit length being relocated minus 1. Add back
// the 1 to get the actual length being relocated.
return (Info & XR_BIASED_LENGTH_MASK) + 1;
Expand Down Expand Up @@ -146,6 +149,10 @@ const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
return static_cast<const XCOFFFileHeader64 *>(FileHeader);
}

template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
return static_cast<const T *>(SectionHeaderTable);
}

const XCOFFSectionHeader32 *
XCOFFObjectFile::sectionHeaderTable32() const {
assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
Expand Down Expand Up @@ -329,78 +336,133 @@ bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
}

relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
if (is64Bit())
report_fatal_error("64-bit support not implemented yet");
const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
auto RelocationsOrErr = relocations(*SectionEntPtr);
if (Error E = RelocationsOrErr.takeError())
return relocation_iterator(RelocationRef());
DataRefImpl Ret;
Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
if (is64Bit()) {
const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
auto RelocationsOrErr =
relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
if (Error E = RelocationsOrErr.takeError()) {
// TODO: report the error up the stack.
consumeError(std::move(E));
return relocation_iterator(RelocationRef());
}
Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
} else {
const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
auto RelocationsOrErr =
relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
if (Error E = RelocationsOrErr.takeError()) {
// TODO: report the error up the stack.
consumeError(std::move(E));
return relocation_iterator(RelocationRef());
}
Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin());
}
return relocation_iterator(RelocationRef(Ret, this));
}

relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const {
if (is64Bit())
report_fatal_error("64-bit support not implemented yet");
const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
auto RelocationsOrErr = relocations(*SectionEntPtr);
if (Error E = RelocationsOrErr.takeError())
return relocation_iterator(RelocationRef());
DataRefImpl Ret;
Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
if (is64Bit()) {
const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec);
auto RelocationsOrErr =
relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr);
if (Error E = RelocationsOrErr.takeError()) {
// TODO: report the error up the stack.
consumeError(std::move(E));
return relocation_iterator(RelocationRef());
}
Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
} else {
const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec);
auto RelocationsOrErr =
relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr);
if (Error E = RelocationsOrErr.takeError()) {
// TODO: report the error up the stack.
consumeError(std::move(E));
return relocation_iterator(RelocationRef());
}
Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end());
}
return relocation_iterator(RelocationRef(Ret, this));
}

void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
if (is64Bit())
Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1);
else
Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1);
}

uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const {
if (is64Bit())
report_fatal_error("64-bit support not implemented yet");
const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
const uint32_t RelocAddress = Reloc->VirtualAddress;
const uint16_t NumberOfSections = getNumberOfSections();
for (uint16_t i = 0; i < NumberOfSections; ++i) {
// Find which section this relocation is belonging to, and get the
// relocation offset relative to the start of the section.
if (Sec32->VirtualAddress <= RelocAddress &&
RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
return RelocAddress - Sec32->VirtualAddress;
if (is64Bit()) {
const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64();
const uint64_t RelocAddress = Reloc->VirtualAddress;
const uint16_t NumberOfSections = getNumberOfSections();
for (uint16_t I = 0; I < NumberOfSections; ++I) {
// Find which section this relocation belongs to, and get the
// relocation offset relative to the start of the section.
if (Sec64->VirtualAddress <= RelocAddress &&
RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) {
return RelocAddress - Sec64->VirtualAddress;
}
++Sec64;
}
} else {
const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32();
const uint32_t RelocAddress = Reloc->VirtualAddress;
const uint16_t NumberOfSections = getNumberOfSections();
for (uint16_t I = 0; I < NumberOfSections; ++I) {
// Find which section this relocation belongs to, and get the
// relocation offset relative to the start of the section.
if (Sec32->VirtualAddress <= RelocAddress &&
RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) {
return RelocAddress - Sec32->VirtualAddress;
}
++Sec32;
}
++Sec32;
}
return InvalidRelocOffset;
}

symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
if (is64Bit())
report_fatal_error("64-bit support not implemented yet");
const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
const uint32_t Index = Reloc->SymbolIndex;

if (Index >= getLogicalNumberOfSymbolTableEntries32())
return symbol_end();

uint32_t Index;
if (is64Bit()) {
const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
Index = Reloc->SymbolIndex;

if (Index >= getNumberOfSymbolTableEntries64())
return symbol_end();
} else {
const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
Index = Reloc->SymbolIndex;

if (Index >= getLogicalNumberOfSymbolTableEntries32())
return symbol_end();
}
DataRefImpl SymDRI;
SymDRI.p = getSymbolEntryAddressByIndex(Index);
return symbol_iterator(SymbolRef(SymDRI, this));
}

uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const {
if (is64Bit())
report_fatal_error("64-bit support not implemented yet");
return viewAs<XCOFFRelocation64>(Rel.p)->Type;
return viewAs<XCOFFRelocation32>(Rel.p)->Type;
}

void XCOFFObjectFile::getRelocationTypeName(
DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
if (is64Bit())
report_fatal_error("64-bit support not implemented yet");
const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
StringRef Res = XCOFF::getRelocationTypeString(Reloc->Type);
StringRef Res;
if (is64Bit()) {
const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p);
Res = XCOFF::getRelocationTypeString(Reloc->Type);
} else {
const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p);
Res = XCOFF::getRelocationTypeString(Reloc->Type);
}
Result.append(Res.begin(), Res.end());
}

Expand Down Expand Up @@ -661,13 +723,16 @@ ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const {
// section header contains the actual count of relocation entries in the s_paddr
// field. STYP_OVRFLO headers contain the section index of their corresponding
// sections as their raw "NumberOfRelocations" field value.
Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries(
const XCOFFSectionHeader32 &Sec) const {

uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1;
template <typename T>
Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries(
const XCOFFSectionHeader<T> &Sec) const {
const T &Section = static_cast<const T &>(Sec);
if (is64Bit())
return Section.NumberOfRelocations;

if (Sec.NumberOfRelocations < XCOFF::RelocOverflow)
return Sec.NumberOfRelocations;
uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1;
if (Section.NumberOfRelocations < XCOFF::RelocOverflow)
return Section.NumberOfRelocations;
for (const auto &Sec : sections32()) {
if (Sec.Flags == XCOFF::STYP_OVRFLO &&
Sec.NumberOfRelocations == SectionIndex)
Expand All @@ -676,27 +741,27 @@ Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries(
return errorCodeToError(object_error::parse_failed);
}

Expected<ArrayRef<XCOFFRelocation32>>
XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const {
template <typename Shdr, typename Reloc>
Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const {
uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
Sec.FileOffsetToRelocationInfo);
auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec);
auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec);
if (Error E = NumRelocEntriesOrErr.takeError())
return std::move(E);

uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();

static_assert(
sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32, "");
static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 ||
sizeof(Reloc) == XCOFF::RelocationSerializationSize32),
"Relocation structure is incorrect");
auto RelocationOrErr =
getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr),
NumRelocEntries * sizeof(XCOFFRelocation32));
getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
NumRelocEntries * sizeof(Reloc));
if (Error E = RelocationOrErr.takeError())
return std::move(E);

const XCOFFRelocation32 *StartReloc = RelocationOrErr.get();
const Reloc *StartReloc = RelocationOrErr.get();

return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries);
return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
}

Expected<XCOFFStringTable>
Expand Down Expand Up @@ -900,6 +965,18 @@ Expected<StringRef> XCOFFSymbolRef::getName() const {
template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
template struct XCOFFSectionHeader<XCOFFSectionHeader64>;

template struct XCOFFRelocation<llvm::support::ubig32_t>;
template struct XCOFFRelocation<llvm::support::ubig64_t>;

template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>>
llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64,
llvm::object::XCOFFRelocation64>(
llvm::object::XCOFFSectionHeader64 const &) const;
template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>>
llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32,
llvm::object::XCOFFRelocation32>(
llvm::object::XCOFFSectionHeader32 const &) const;

bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
if (Bytes.size() < 4)
return false;
Expand Down

0 comments on commit 2cdfd0b

Please sign in to comment.