aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-03-20 11:40:34 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-05-14 11:43:05 +0000
commit349cc55c9796c4596a5b9904cd3281af295f878f (patch)
tree410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp
parentcb2ae6163174b90e999326ecec3699ee093a5d43 (diff)
parentc0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp502
1 files changed, 412 insertions, 90 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp
index 53447d0c97b2..9b0a5efacba7 100644
--- a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/contrib/llvm-project/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,20 @@ const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const {
return static_cast<const XCOFFFileHeader64 *>(FileHeader);
}
+const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const {
+ assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
+ return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader);
+}
+
+const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const {
+ assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
+ return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader);
+}
+
+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.");
@@ -183,12 +200,16 @@ XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const {
if (StringTable.Data != nullptr && StringTable.Size > Offset)
return (StringTable.Data + Offset);
- return make_error<GenericBinaryError>("Bad offset for string table entry",
- object_error::parse_failed);
+ return createError("entry with offset 0x" + Twine::utohexstr(Offset) +
+ " in a string table with size 0x" +
+ Twine::utohexstr(StringTable.Size) + " is invalid");
}
StringRef XCOFFObjectFile::getStringTable() const {
- return StringRef(StringTable.Data, StringTable.Size);
+ // If the size is less than or equal to 4, then the string table contains no
+ // string data.
+ return StringRef(StringTable.Data,
+ StringTable.Size <= 4 ? 0 : StringTable.Size);
}
Expected<StringRef>
@@ -210,15 +231,85 @@ uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
return toSymbolRef(Symb).getValue();
}
+uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
+ uint64_t Result = 0;
+ XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
+ if (XCOFFSym.isCsectSymbol()) {
+ Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
+ XCOFFSym.getXCOFFCsectAuxRef();
+ if (!CsectAuxRefOrError)
+ // TODO: report the error up the stack.
+ consumeError(CsectAuxRefOrError.takeError());
+ else
+ Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2();
+ }
+ return Result;
+}
+
uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
uint64_t Result = 0;
- llvm_unreachable("Not yet implemented!");
+ XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
+ if (XCOFFSym.isCsectSymbol()) {
+ Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
+ XCOFFSym.getXCOFFCsectAuxRef();
+ if (!CsectAuxRefOrError)
+ // TODO: report the error up the stack.
+ consumeError(CsectAuxRefOrError.takeError());
+ else {
+ XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
+ assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM);
+ Result = CsectAuxRef.getSectionOrLength();
+ }
+ }
return Result;
}
Expected<SymbolRef::Type>
XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const {
- // TODO: Return the correct symbol type.
+ XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
+
+ if (XCOFFSym.isFunction())
+ return SymbolRef::ST_Function;
+
+ if (XCOFF::C_FILE == XCOFFSym.getStorageClass())
+ return SymbolRef::ST_File;
+
+ int16_t SecNum = XCOFFSym.getSectionNumber();
+ if (SecNum <= 0)
+ return SymbolRef::ST_Other;
+
+ Expected<DataRefImpl> SecDRIOrErr =
+ getSectionByNum(XCOFFSym.getSectionNumber());
+
+ if (!SecDRIOrErr)
+ return SecDRIOrErr.takeError();
+
+ DataRefImpl SecDRI = SecDRIOrErr.get();
+
+ Expected<StringRef> SymNameOrError = XCOFFSym.getName();
+ if (SymNameOrError) {
+ // The "TOC" symbol is treated as SymbolRef::ST_Other.
+ if (SymNameOrError.get() == "TOC")
+ return SymbolRef::ST_Other;
+
+ // The symbol for a section name is treated as SymbolRef::ST_Other.
+ StringRef SecName;
+ if (is64Bit())
+ SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName();
+ else
+ SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName();
+
+ if (SecName == SymNameOrError.get())
+ return SymbolRef::ST_Other;
+ } else
+ return SymNameOrError.takeError();
+
+ if (isSectionData(SecDRI) || isSectionBSS(SecDRI))
+ return SymbolRef::ST_Data;
+
+ if (isDebugSection(SecDRI))
+ return SymbolRef::ST_Debug;
+
return SymbolRef::ST_Other;
}
@@ -285,8 +376,12 @@ XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
const uint8_t * ContentStart = base() + OffsetToRaw;
uint64_t SectionSize = getSectionSize(Sec);
- if (checkOffset(Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
- return make_error<BinaryError>();
+ if (Error E = Binary::checkOffset(
+ Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
+ return createError(
+ toString(std::move(E)) + ": section data with offset 0x" +
+ Twine::utohexstr(OffsetToRaw) + " and size 0x" +
+ Twine::utohexstr(SectionSize) + " goes past the end of the file");
return makeArrayRef(ContentStart,SectionSize);
}
@@ -297,6 +392,43 @@ uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
return Result;
}
+Expected<uintptr_t> XCOFFObjectFile::getLoaderSectionAddress() const {
+ uint64_t OffsetToLoaderSection = 0;
+ uint64_t SizeOfLoaderSection = 0;
+
+ if (is64Bit()) {
+ for (const auto &Sec64 : sections64())
+ if (Sec64.getSectionType() == XCOFF::STYP_LOADER) {
+ OffsetToLoaderSection = Sec64.FileOffsetToRawData;
+ SizeOfLoaderSection = Sec64.SectionSize;
+ break;
+ }
+ } else {
+ for (const auto &Sec32 : sections32())
+ if (Sec32.getSectionType() == XCOFF::STYP_LOADER) {
+ OffsetToLoaderSection = Sec32.FileOffsetToRawData;
+ SizeOfLoaderSection = Sec32.SectionSize;
+ break;
+ }
+ }
+
+ // No loader section is not an error.
+ if (!SizeOfLoaderSection)
+ return 0;
+
+ uintptr_t LoderSectionStart =
+ reinterpret_cast<uintptr_t>(base() + OffsetToLoaderSection);
+ if (Error E =
+ Binary::checkOffset(Data, LoderSectionStart, SizeOfLoaderSection))
+ return createError(toString(std::move(E)) +
+ ": loader section with offset 0x" +
+ Twine::utohexstr(OffsetToLoaderSection) +
+ " and size 0x" + Twine::utohexstr(SizeOfLoaderSection) +
+ " goes past the end of the file");
+
+ return LoderSectionStart;
+}
+
bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
return false;
}
@@ -326,61 +458,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));
@@ -388,22 +571,50 @@ 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());
}
Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
- uint32_t Result = 0;
- // TODO: Return correct symbol flags.
+ XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
+ uint32_t Result = SymbolRef::SF_None;
+
+ if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS)
+ Result |= SymbolRef::SF_Absolute;
+
+ XCOFF::StorageClass SC = XCOFFSym.getStorageClass();
+ if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC)
+ Result |= SymbolRef::SF_Global;
+
+ if (XCOFF::C_WEAKEXT == SC)
+ Result |= SymbolRef::SF_Weak;
+
+ if (XCOFFSym.isCsectSymbol()) {
+ Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr =
+ XCOFFSym.getXCOFFCsectAuxRef();
+ if (CsectAuxEntOrErr) {
+ if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM)
+ Result |= SymbolRef::SF_Common;
+ } else
+ return CsectAuxEntOrErr.takeError();
+ }
+
+ if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF)
+ Result |= SymbolRef::SF_Undefined;
+
return Result;
}
@@ -494,7 +705,9 @@ uint16_t XCOFFObjectFile::getMagic() const {
Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const {
if (Num <= 0 || Num > getNumberOfSections())
- return errorCodeToError(object_error::invalid_section_index);
+ return createStringError(object_error::invalid_section_index,
+ "the section index (" + Twine(Num) +
+ ") is invalid");
DataRefImpl DRI;
DRI.p = getWithOffset(getSectionHeaderTableAddress(),
@@ -602,6 +815,25 @@ uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const {
XCOFF::SymbolTableEntrySize;
}
+uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
+ uint64_t Result = 0;
+ XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb);
+ if (XCOFFSym.isCsectSymbol()) {
+ Expected<XCOFFCsectAuxRef> CsectAuxRefOrError =
+ XCOFFSym.getXCOFFCsectAuxRef();
+ if (!CsectAuxRefOrError)
+ // TODO: report the error up the stack.
+ consumeError(CsectAuxRefOrError.takeError());
+ else {
+ XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get();
+ uint8_t SymType = CsectAuxRef.getSymbolType();
+ if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM)
+ Result = CsectAuxRef.getSectionOrLength();
+ }
+ }
+ return Result;
+}
+
uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const {
return getAdvancedSymbolEntryAddress(
reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index);
@@ -612,7 +844,9 @@ XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries();
if (Index >= NumberOfSymTableEntries)
- return errorCodeToError(object_error::invalid_symbol_index);
+ return createError("symbol index " + Twine(Index) +
+ " exceeds symbol count " +
+ Twine(NumberOfSymTableEntries));
DataRefImpl SymDRI;
SymDRI.p = getSymbolEntryAddressByIndex(Index);
@@ -658,13 +892,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)
@@ -673,27 +910,31 @@ 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));
- if (Error E = RelocationOrErr.takeError())
- return std::move(E);
+ getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr),
+ NumRelocEntries * sizeof(Reloc));
+ if (!RelocationOrErr)
+ return createError(
+ toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" +
+ Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" +
+ Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) +
+ " go past the end of the file");
- const XCOFFRelocation32 *StartReloc = RelocationOrErr.get();
+ const Reloc *StartReloc = RelocationOrErr.get();
- return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries);
+ return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries);
}
Expected<XCOFFStringTable>
@@ -716,8 +957,12 @@ XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
auto StringTableOrErr =
getObject<char>(Obj->Data, Obj->base() + Offset, Size);
- if (Error E = StringTableOrErr.takeError())
- return std::move(E);
+ if (!StringTableOrErr)
+ return createError(toString(StringTableOrErr.takeError()) +
+ ": string table with offset 0x" +
+ Twine::utohexstr(Offset) + " and size 0x" +
+ Twine::utohexstr(Size) +
+ " goes past the end of the file");
const char *StringTablePtr = StringTableOrErr.get();
if (StringTablePtr[Size - 1] != '\0')
@@ -726,6 +971,54 @@ XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
return XCOFFStringTable{Size, StringTablePtr};
}
+// This function returns the import file table. Each entry in the import file
+// table consists of: "path_name\0base_name\0archive_member_name\0".
+Expected<StringRef> XCOFFObjectFile::getImportFileTable() const {
+ Expected<uintptr_t> LoaderSectionAddrOrError = getLoaderSectionAddress();
+ if (!LoaderSectionAddrOrError)
+ return LoaderSectionAddrOrError.takeError();
+
+ uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
+ if (!LoaderSectionAddr)
+ return StringRef();
+
+ uint64_t OffsetToImportFileTable = 0;
+ uint64_t LengthOfImportFileTable = 0;
+ if (is64Bit()) {
+ const LoaderSectionHeader64 *LoaderSec64 =
+ viewAs<LoaderSectionHeader64>(LoaderSectionAddr);
+ OffsetToImportFileTable = LoaderSec64->OffsetToImpid;
+ LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl;
+ } else {
+ const LoaderSectionHeader32 *LoaderSec32 =
+ viewAs<LoaderSectionHeader32>(LoaderSectionAddr);
+ OffsetToImportFileTable = LoaderSec32->OffsetToImpid;
+ LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl;
+ }
+
+ auto ImportTableOrErr = getObject<char>(
+ Data,
+ reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable),
+ LengthOfImportFileTable);
+ if (!ImportTableOrErr)
+ return createError(
+ toString(ImportTableOrErr.takeError()) +
+ ": import file table with offset 0x" +
+ Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
+ " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
+ " goes past the end of the file");
+
+ const char *ImportTablePtr = ImportTableOrErr.get();
+ if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0')
+ return createError(
+ ": import file name table with offset 0x" +
+ Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) +
+ " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) +
+ " must end with a null terminator");
+
+ return StringRef(ImportTablePtr, LengthOfImportFileTable);
+}
+
Expected<std::unique_ptr<XCOFFObjectFile>>
XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
// Can't use std::make_unique because of the private constructor.
@@ -744,17 +1037,30 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
Obj->FileHeader = FileHeaderOrErr.get();
CurOffset += Obj->getFileHeaderSize();
- // TODO FIXME we don't have support for an optional header yet, so just skip
- // past it.
+
+ if (Obj->getOptionalHeaderSize()) {
+ auto AuxiliaryHeaderOrErr =
+ getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize());
+ if (Error E = AuxiliaryHeaderOrErr.takeError())
+ return std::move(E);
+ Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get();
+ }
+
CurOffset += Obj->getOptionalHeaderSize();
// Parse the section header table if it is present.
if (Obj->getNumberOfSections()) {
- auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset,
- Obj->getNumberOfSections() *
- Obj->getSectionHeaderSize());
- if (Error E = SecHeadersOrErr.takeError())
- return std::move(E);
+ uint64_t SectionHeadersSize =
+ Obj->getNumberOfSections() * Obj->getSectionHeaderSize();
+ auto SecHeadersOrErr =
+ getObject<void>(Data, Base + CurOffset, SectionHeadersSize);
+ if (!SecHeadersOrErr)
+ return createError(toString(SecHeadersOrErr.takeError()) +
+ ": section headers with offset 0x" +
+ Twine::utohexstr(CurOffset) + " and size 0x" +
+ Twine::utohexstr(SectionHeadersSize) +
+ " go past the end of the file");
+
Obj->SectionHeaderTable = SecHeadersOrErr.get();
}
@@ -773,8 +1079,12 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) {
NumberOfSymbolTableEntries;
auto SymTableOrErr =
getObject<void *>(Data, Base + CurOffset, SymbolTableSize);
- if (Error E = SymTableOrErr.takeError())
- return std::move(E);
+ if (!SymTableOrErr)
+ return createError(
+ toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" +
+ Twine::utohexstr(CurOffset) + " and size 0x" +
+ Twine::utohexstr(SymbolTableSize) + " goes past the end of the file");
+
Obj->SymbolTblPtr = SymTableOrErr.get();
CurOffset += SymbolTableSize;
@@ -844,10 +1154,10 @@ Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
if (auto Err = NameOrErr.takeError())
return std::move(Err);
+ uint32_t SymbolIdx = OwningObjectPtr->getSymbolIndex(getEntryAddress());
if (!NumberOfAuxEntries) {
- return createStringError(object_error::parse_failed,
- "csect symbol \"" + *NameOrErr +
- "\" contains no auxiliary entry");
+ return createError("csect symbol \"" + *NameOrErr + "\" with index " +
+ Twine(SymbolIdx) + " contains no auxiliary entry");
}
if (!OwningObjectPtr->is64Bit()) {
@@ -872,9 +1182,9 @@ Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const {
}
}
- return createStringError(
- object_error::parse_failed,
- "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\"");
+ return createError(
+ "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr +
+ "\" with index " + Twine(SymbolIdx));
}
Expected<StringRef> XCOFFSymbolRef::getName() const {
@@ -897,6 +1207,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;