aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/XCOFFObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Object/XCOFFObjectFile.cpp')
-rw-r--r--llvm/lib/Object/XCOFFObjectFile.cpp197
1 files changed, 137 insertions, 60 deletions
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 28355b6..7ec418c 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -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;
@@ -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.");
@@ -329,61 +336,112 @@ 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));
@@ -391,16 +449,20 @@ symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
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());
}
@@ -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)
@@ -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>
@@ -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;