aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Object
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object')
-rw-r--r--contrib/llvm-project/llvm/lib/Object/Archive.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp5
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ELF.cpp71
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp82
-rw-r--r--contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp29
-rw-r--r--contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp46
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp7
-rw-r--r--contrib/llvm-project/llvm/lib/Object/Object.cpp9
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp15
-rw-r--r--contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp119
-rw-r--r--contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp502
13 files changed, 710 insertions, 181 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/Archive.cpp b/contrib/llvm-project/llvm/lib/Object/Archive.cpp
index 6ff896cf347e..5492692445e7 100644
--- a/contrib/llvm-project/llvm/lib/Object/Archive.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/Archive.cpp
@@ -418,7 +418,7 @@ Expected<bool> Archive::Child::isThinMember() const {
if (!NameOrErr)
return NameOrErr.takeError();
StringRef Name = NameOrErr.get();
- return Parent->IsThin && Name != "/" && Name != "//";
+ return Parent->IsThin && Name != "/" && Name != "//" && Name != "/SYM64/";
}
Expected<std::string> Archive::Child::getFullName() const {
diff --git a/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp b/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp
index 8f29f7a658fd..55ddd3baca2b 100644
--- a/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp
@@ -80,11 +80,6 @@ static bool isDecorated(StringRef Sym, bool MingwDef) {
(!MingwDef && Sym.contains('@'));
}
-static Error createError(const Twine &Err) {
- return make_error<StringError>(StringRef(Err.str()),
- object_error::parse_failed);
-}
-
class Lexer {
public:
Lexer(StringRef S) : Buf(S) {}
diff --git a/contrib/llvm-project/llvm/lib/Object/ELF.cpp b/contrib/llvm-project/llvm/lib/Object/ELF.cpp
index ca2ed4449120..84181ae5e501 100644
--- a/contrib/llvm-project/llvm/lib/Object/ELF.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ELF.cpp
@@ -246,6 +246,9 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS);
}
break;
+ case ELF::EM_MSP430:
+ switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_MSP430_ATTRIBUTES); }
+ break;
case ELF::EM_RISCV:
switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_RISCV_ATTRIBUTES); }
break;
@@ -333,40 +336,26 @@ ELFFile<ELFT>::decode_relrs(Elf_Relr_Range relrs) const {
std::vector<Elf_Rel> Relocs;
// Word type: uint32_t for Elf32, and uint64_t for Elf64.
- typedef typename ELFT::uint Word;
-
- // Word size in number of bytes.
- const size_t WordSize = sizeof(Word);
+ using Addr = typename ELFT::uint;
- // Number of bits used for the relocation offsets bitmap.
- // These many relative relocations can be encoded in a single entry.
- const size_t NBits = 8*WordSize - 1;
-
- Word Base = 0;
- for (const Elf_Relr &R : relrs) {
- Word Entry = R;
- if ((Entry&1) == 0) {
+ Addr Base = 0;
+ for (Elf_Relr R : relrs) {
+ typename ELFT::uint Entry = R;
+ if ((Entry & 1) == 0) {
// Even entry: encodes the offset for next relocation.
Rel.r_offset = Entry;
Relocs.push_back(Rel);
// Set base offset for subsequent bitmap entries.
- Base = Entry + WordSize;
- continue;
- }
-
- // Odd entry: encodes bitmap for relocations starting at base.
- Word Offset = Base;
- while (Entry != 0) {
- Entry >>= 1;
- if ((Entry&1) != 0) {
- Rel.r_offset = Offset;
- Relocs.push_back(Rel);
- }
- Offset += WordSize;
+ Base = Entry + sizeof(Addr);
+ } else {
+ // Odd entry: encodes bitmap for relocations starting at base.
+ for (Addr Offset = Base; (Entry >>= 1) != 0; Offset += sizeof(Addr))
+ if ((Entry & 1) != 0) {
+ Rel.r_offset = Offset;
+ Relocs.push_back(Rel);
+ }
+ Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(Addr);
}
-
- // Advance base offset by NBits words.
- Base += NBits * WordSize;
}
return Relocs;
@@ -474,6 +463,14 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
}
break;
+ case ELF::EM_PPC:
+ switch (Type) {
+#define PPC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef PPC_DYNAMIC_TAG
+ }
+ break;
+
case ELF::EM_PPC64:
switch (Type) {
#define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
@@ -481,6 +478,14 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
#undef PPC64_DYNAMIC_TAG
}
break;
+
+ case ELF::EM_RISCV:
+ switch (Type) {
+#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef RISCV_DYNAMIC_TAG
+ }
+ break;
}
#undef DYNAMIC_TAG
switch (Type) {
@@ -488,7 +493,9 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
#define AARCH64_DYNAMIC_TAG(name, value)
#define MIPS_DYNAMIC_TAG(name, value)
#define HEXAGON_DYNAMIC_TAG(name, value)
+#define PPC_DYNAMIC_TAG(name, value)
#define PPC64_DYNAMIC_TAG(name, value)
+#define RISCV_DYNAMIC_TAG(name, value)
// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
#define DYNAMIC_TAG_MARKER(name, value)
#define DYNAMIC_TAG(name, value) case value: return #name;
@@ -497,7 +504,9 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
#undef AARCH64_DYNAMIC_TAG
#undef MIPS_DYNAMIC_TAG
#undef HEXAGON_DYNAMIC_TAG
+#undef PPC_DYNAMIC_TAG
#undef PPC64_DYNAMIC_TAG
+#undef RISCV_DYNAMIC_TAG
#undef DYNAMIC_TAG_MARKER
#undef DYNAMIC_STRINGIFY_ENUM
default:
@@ -613,14 +622,14 @@ ELFFile<ELFT>::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const {
}
template <class ELFT>
-Expected<std::vector<typename ELFT::BBAddrMap>>
+Expected<std::vector<BBAddrMap>>
ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
if (!ContentsOrErr)
return ContentsOrErr.takeError();
ArrayRef<uint8_t> Content = *ContentsOrErr;
DataExtractor Data(Content, isLE(), ELFT::Is64Bits ? 8 : 4);
- std::vector<Elf_BBAddrMap> FunctionEntries;
+ std::vector<BBAddrMap> FunctionEntries;
DataExtractor::Cursor Cur(0);
Error ULEBSizeErr = Error::success();
@@ -647,7 +656,7 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) {
uintX_t Address = static_cast<uintX_t>(Data.getAddress(Cur));
uint32_t NumBlocks = ReadULEB128AsUInt32();
- std::vector<typename Elf_BBAddrMap::BBEntry> BBEntries;
+ std::vector<BBAddrMap::BBEntry> BBEntries;
for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks);
++BlockID) {
uint32_t Offset = ReadULEB128AsUInt32();
diff --git a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp
index 6613d79ab3d0..50035d6c7523 100644
--- a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp
@@ -15,6 +15,7 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Object/Error.h"
@@ -25,7 +26,6 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/RISCVAttributeParser.h"
#include "llvm/Support/RISCVAttributes.h"
-#include "llvm/Support/TargetRegistry.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
@@ -538,9 +538,16 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
case ARMBuildAttrs::v6K:
Triple += "v6k";
break;
- case ARMBuildAttrs::v7:
- Triple += "v7";
+ case ARMBuildAttrs::v7: {
+ Optional<unsigned> ArchProfileAttr =
+ Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile);
+ if (ArchProfileAttr.hasValue() &&
+ ArchProfileAttr.getValue() == ARMBuildAttrs::MicroControllerProfile)
+ Triple += "v7m";
+ else
+ Triple += "v7";
break;
+ }
case ARMBuildAttrs::v6_M:
Triple += "v6m";
break;
@@ -647,3 +654,72 @@ ELFObjectFileBase::getPltAddresses() const {
}
return Result;
}
+
+template <class ELFT>
+static Expected<std::vector<VersionEntry>>
+readDynsymVersionsImpl(const ELFFile<ELFT> &EF,
+ ELFObjectFileBase::elf_symbol_iterator_range Symbols) {
+ using Elf_Shdr = typename ELFT::Shdr;
+ const Elf_Shdr *VerSec = nullptr;
+ const Elf_Shdr *VerNeedSec = nullptr;
+ const Elf_Shdr *VerDefSec = nullptr;
+ // The user should ensure sections() can't fail here.
+ for (const Elf_Shdr &Sec : cantFail(EF.sections())) {
+ if (Sec.sh_type == ELF::SHT_GNU_versym)
+ VerSec = &Sec;
+ else if (Sec.sh_type == ELF::SHT_GNU_verdef)
+ VerDefSec = &Sec;
+ else if (Sec.sh_type == ELF::SHT_GNU_verneed)
+ VerNeedSec = &Sec;
+ }
+ if (!VerSec)
+ return std::vector<VersionEntry>();
+
+ Expected<SmallVector<Optional<VersionEntry>, 0>> MapOrErr =
+ EF.loadVersionMap(VerNeedSec, VerDefSec);
+ if (!MapOrErr)
+ return MapOrErr.takeError();
+
+ std::vector<VersionEntry> Ret;
+ size_t I = 0;
+ for (auto It = Symbols.begin(), E = Symbols.end(); It != E; ++It) {
+ ++I;
+ Expected<const typename ELFT::Versym *> VerEntryOrErr =
+ EF.template getEntry<typename ELFT::Versym>(*VerSec, I);
+ if (!VerEntryOrErr)
+ return createError("unable to read an entry with index " + Twine(I) +
+ " from " + describe(EF, *VerSec) + ": " +
+ toString(VerEntryOrErr.takeError()));
+
+ Expected<uint32_t> FlagsOrErr = It->getFlags();
+ if (!FlagsOrErr)
+ return createError("unable to read flags for symbol with index " +
+ Twine(I) + ": " + toString(FlagsOrErr.takeError()));
+
+ bool IsDefault;
+ Expected<StringRef> VerOrErr = EF.getSymbolVersionByIndex(
+ (*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr,
+ (*FlagsOrErr) & SymbolRef::SF_Undefined);
+ if (!VerOrErr)
+ return createError("unable to get a version for entry " + Twine(I) +
+ " of " + describe(EF, *VerSec) + ": " +
+ toString(VerOrErr.takeError()));
+
+ Ret.push_back({(*VerOrErr).str(), IsDefault});
+ }
+
+ return Ret;
+}
+
+Expected<std::vector<VersionEntry>>
+ELFObjectFileBase::readDynsymVersions() const {
+ elf_symbol_iterator_range Symbols = getDynamicSymbolIterators();
+ if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this))
+ return readDynsymVersionsImpl(Obj->getELFFile(), Symbols);
+ if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this))
+ return readDynsymVersionsImpl(Obj->getELFFile(), Symbols);
+ if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this))
+ return readDynsymVersionsImpl(Obj->getELFFile(), Symbols);
+ return readDynsymVersionsImpl(cast<ELF64BEObjectFile>(this)->getELFFile(),
+ Symbols);
+}
diff --git a/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp
index befba5d57127..c653262791cc 100644
--- a/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp
@@ -18,9 +18,9 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace object;
diff --git a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp
index 746b00867157..093ae1bbc267 100644
--- a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp
@@ -41,10 +41,15 @@
using namespace llvm;
using namespace irsymtab;
-static const char *LibcallRoutineNames[] = {
+static const char *PreservedSymbols[] = {
#define HANDLE_LIBCALL(code, name) name,
#include "llvm/IR/RuntimeLibcalls.def"
#undef HANDLE_LIBCALL
+ // There are global variables, so put it here instead of in
+ // RuntimeLibcalls.def.
+ // TODO: Are there similar such variables?
+ "__ssp_canary_word",
+ "__stack_chk_guard",
};
namespace {
@@ -261,9 +266,9 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
setStr(Sym.IRName, GV->getName());
- bool IsBuiltinFunc = llvm::is_contained(LibcallRoutineNames, GV->getName());
+ bool IsPreservedSymbol = llvm::is_contained(PreservedSymbols, GV->getName());
- if (Used.count(GV) || IsBuiltinFunc)
+ if (Used.count(GV) || IsPreservedSymbol)
Sym.Flags |= 1 << storage::Symbol::FB_used;
if (GV->isThreadLocal())
Sym.Flags |= 1 << storage::Symbol::FB_tls;
@@ -283,11 +288,15 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
Uncommon().CommonAlign = GVar->getAlignment();
}
- const GlobalObject *Base = GV->getBaseObject();
- if (!Base)
- return make_error<StringError>("Unable to determine comdat of alias!",
- inconvertibleErrorCode());
- if (const Comdat *C = Base->getComdat()) {
+ const GlobalObject *GO = GV->getAliaseeObject();
+ if (!GO) {
+ if (isa<GlobalIFunc>(GV))
+ GO = cast<GlobalIFunc>(GV)->getResolverFunction();
+ if (!GO)
+ return make_error<StringError>("Unable to determine comdat of alias!",
+ inconvertibleErrorCode());
+ }
+ if (const Comdat *C = GO->getComdat()) {
Expected<int> ComdatIndexOrErr = getComdatIndex(C, GV->getParent());
if (!ComdatIndexOrErr)
return ComdatIndexOrErr.takeError();
@@ -312,8 +321,8 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
}
}
- if (!Base->getSection().empty())
- setStr(Uncommon().SectionName, Saver.save(Base->getSection()));
+ if (!GO->getSection().empty())
+ setStr(Uncommon().SectionName, Saver.save(GO->getSection()));
return Error::success();
}
diff --git a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp
index 177314a9a790..7501661591f0 100644
--- a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp
@@ -246,8 +246,8 @@ static Error checkOverlappingElement(std::list<MachOElement> &Elements,
if (Size == 0)
return Error::success();
- for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
- auto E = *it;
+ for (auto it = Elements.begin(); it != Elements.end(); ++it) {
+ const auto &E = *it;
if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
(Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
(Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
@@ -258,7 +258,7 @@ static Error checkOverlappingElement(std::list<MachOElement> &Elements,
auto nt = it;
nt++;
if (nt != Elements.end()) {
- auto N = *nt;
+ const auto &N = *nt;
if (Offset + Size <= N.Offset) {
Elements.insert(nt, {Offset, Size, Name});
return Error::success();
@@ -2048,6 +2048,46 @@ bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const {
SectionName == "__swift_ast";
}
+namespace {
+template <typename LoadCommandType>
+ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
+ MachOObjectFile::LoadCommandInfo LoadCmd,
+ StringRef SegmentName) {
+ auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
+ if (!SegmentOrErr) {
+ consumeError(SegmentOrErr.takeError());
+ return {};
+ }
+ auto &Segment = SegmentOrErr.get();
+ if (StringRef(Segment.segname, 16).startswith(SegmentName))
+ return arrayRefFromStringRef(Obj.getData().slice(
+ Segment.fileoff, Segment.fileoff + Segment.filesize));
+ return {};
+}
+} // namespace
+
+ArrayRef<uint8_t>
+MachOObjectFile::getSegmentContents(StringRef SegmentName) const {
+ for (auto LoadCmd : load_commands()) {
+ ArrayRef<uint8_t> Contents;
+ switch (LoadCmd.C.cmd) {
+ case MachO::LC_SEGMENT:
+ Contents = ::getSegmentContents<MachO::segment_command>(*this, LoadCmd,
+ SegmentName);
+ break;
+ case MachO::LC_SEGMENT_64:
+ Contents = ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd,
+ SegmentName);
+ break;
+ default:
+ continue;
+ }
+ if (!Contents.empty())
+ return Contents;
+ }
+ return {};
+}
+
unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
return Sec.getRawDataRefImpl().d.a;
}
diff --git a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp
index 9a79de77af16..954d1f09f4e9 100644
--- a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp
@@ -36,6 +36,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
@@ -43,7 +44,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -204,8 +204,9 @@ uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const {
if (GVar->isConstant())
Res |= BasicSymbolRef::SF_Const;
}
- if (dyn_cast_or_null<Function>(GV->getBaseObject()))
- Res |= BasicSymbolRef::SF_Executable;
+ if (const GlobalObject *GO = GV->getAliaseeObject())
+ if (isa<Function>(GO) || isa<GlobalIFunc>(GO))
+ Res |= BasicSymbolRef::SF_Executable;
if (isa<GlobalAlias>(GV))
Res |= BasicSymbolRef::SF_Indirect;
if (GV->hasPrivateLinkage())
diff --git a/contrib/llvm-project/llvm/lib/Object/Object.cpp b/contrib/llvm-project/llvm/lib/Object/Object.cpp
index b486e9f5c9a8..0659cf6a2d41 100644
--- a/contrib/llvm-project/llvm/lib/Object/Object.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/Object.cpp
@@ -222,8 +222,7 @@ void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SecOrErr.takeError(), OS);
- OS.flush();
- report_fatal_error(Buf);
+ report_fatal_error(Twine(OS.str()));
}
*unwrap(Sect) = *SecOrErr;
}
@@ -304,8 +303,7 @@ const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(Ret.takeError(), OS);
- OS.flush();
- report_fatal_error(Buf);
+ report_fatal_error(Twine(OS.str()));
}
return Ret->data();
}
@@ -316,8 +314,7 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(Ret.takeError(), OS);
- OS.flush();
- report_fatal_error(Buf);
+ report_fatal_error(Twine(OS.str()));
}
return *Ret;
}
diff --git a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp
index 5c894439ff67..6fd02f3b9592 100644
--- a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp
@@ -55,14 +55,15 @@ bool SectionRef::containsSymbol(SymbolRef S) const {
}
Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const {
- if (Expected<uint32_t> FlagsOrErr = getSymbolFlags(Ref)) {
- if (*FlagsOrErr & SymbolRef::SF_Undefined)
- return 0;
- if (*FlagsOrErr & SymbolRef::SF_Common)
- return getCommonSymbolSize(Ref);
- } else
+ uint32_t Flags;
+ if (Error E = getSymbolFlags(Ref).moveInto(Flags))
// TODO: Test this error.
- return FlagsOrErr.takeError();
+ return std::move(E);
+
+ if (Flags & SymbolRef::SF_Undefined)
+ return 0;
+ if (Flags & SymbolRef::SF_Common)
+ return getCommonSymbolSize(Ref);
return getSymbolValueImpl(Ref);
}
diff --git a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp
index ab98a2dd2ac1..00a45e2c5d4e 100644
--- a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp
@@ -18,7 +18,7 @@ namespace object {
static int64_t getELFAddend(RelocationRef R) {
Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
- report_fatal_error(EI.message());
+ report_fatal_error(Twine(EI.message()));
});
return *AddendOrErr;
}
diff --git a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
index a08c648358c0..6a19b159f3d5 100644
--- a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
@@ -286,9 +286,9 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
return;
}
- WasmSection Sec;
WasmSectionOrderChecker Checker;
while (Ctx.Ptr < Ctx.End) {
+ WasmSection Sec;
if ((Err = readSection(Sec, Ctx, Checker)))
return;
if ((Err = parseSection(Sec)))
@@ -339,7 +339,8 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) {
}
Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
- // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
+ // Legacy "dylink" section support.
+ // See parseDylink0Section for the current "dylink.0" section parsing.
HasDylinkSection = true;
DylinkInfo.MemorySize = readVaruint32(Ctx);
DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
@@ -349,17 +350,77 @@ Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
while (Count--) {
DylinkInfo.Needed.push_back(readString(Ctx));
}
+
if (Ctx.Ptr != Ctx.End)
return make_error<GenericBinaryError>("dylink section ended prematurely",
object_error::parse_failed);
return Error::success();
}
+Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
+ // See
+ // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
+ HasDylinkSection = true;
+
+ const uint8_t *OrigEnd = Ctx.End;
+ while (Ctx.Ptr < OrigEnd) {
+ Ctx.End = OrigEnd;
+ uint8_t Type = readUint8(Ctx);
+ uint32_t Size = readVaruint32(Ctx);
+ LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
+ << "\n");
+ Ctx.End = Ctx.Ptr + Size;
+ uint32_t Count;
+ switch (Type) {
+ case wasm::WASM_DYLINK_MEM_INFO:
+ DylinkInfo.MemorySize = readVaruint32(Ctx);
+ DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
+ DylinkInfo.TableSize = readVaruint32(Ctx);
+ DylinkInfo.TableAlignment = readVaruint32(Ctx);
+ break;
+ case wasm::WASM_DYLINK_NEEDED:
+ Count = readVaruint32(Ctx);
+ while (Count--) {
+ DylinkInfo.Needed.push_back(readString(Ctx));
+ }
+ break;
+ case wasm::WASM_DYLINK_EXPORT_INFO: {
+ uint32_t Count = readVaruint32(Ctx);
+ while (Count--) {
+ DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
+ }
+ break;
+ }
+ case wasm::WASM_DYLINK_IMPORT_INFO: {
+ uint32_t Count = readVaruint32(Ctx);
+ while (Count--) {
+ DylinkInfo.ImportInfo.push_back(
+ {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
+ }
+ break;
+ }
+ default:
+ LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
+ Ctx.Ptr += Size;
+ break;
+ }
+ if (Ctx.Ptr != Ctx.End) {
+ return make_error<GenericBinaryError>(
+ "dylink.0 sub-section ended prematurely", object_error::parse_failed);
+ }
+ }
+
+ if (Ctx.Ptr != Ctx.End)
+ return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
llvm::DenseSet<uint64_t> SeenFunctions;
llvm::DenseSet<uint64_t> SeenGlobals;
llvm::DenseSet<uint64_t> SeenSegments;
- if (FunctionTypes.size() && !SeenCodeSection) {
+ if (Functions.size() && !SeenCodeSection) {
return make_error<GenericBinaryError>("names must come after code section",
object_error::parse_failed);
}
@@ -427,7 +488,7 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
HasLinkingSection = true;
- if (FunctionTypes.size() && !SeenCodeSection) {
+ if (Functions.size() && !SeenCodeSection) {
return make_error<GenericBinaryError>(
"linking data must come after code section",
object_error::parse_failed);
@@ -529,7 +590,6 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
const wasm::WasmSignature *Signature = nullptr;
const wasm::WasmGlobalType *GlobalType = nullptr;
const wasm::WasmTableType *TableType = nullptr;
- const wasm::WasmTagType *TagType = nullptr;
Info.Kind = readUint8(Ctx);
Info.Flags = readVaruint32(Ctx);
@@ -545,8 +605,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
if (IsDefined) {
Info.Name = readString(Ctx);
unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
- Signature = &Signatures[FunctionTypes[FuncIndex]];
wasm::WasmFunction &Function = Functions[FuncIndex];
+ Signature = &Signatures[Function.SigIndex];
if (Function.SymbolName.empty())
Function.SymbolName = Info.Name;
} else {
@@ -674,8 +734,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Info.Name = readString(Ctx);
unsigned TagIndex = Info.ElementIndex - NumImportedTags;
wasm::WasmTag &Tag = Tags[TagIndex];
- Signature = &Signatures[Tag.Type.SigIndex];
- TagType = &Tag.Type;
+ Signature = &Signatures[Tag.SigIndex];
if (Tag.SymbolName.empty())
Tag.SymbolName = Info.Name;
@@ -687,8 +746,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
} else {
Info.Name = Import.Field;
}
- TagType = &Import.Tag;
- Signature = &Signatures[TagType->SigIndex];
+ Signature = &Signatures[Import.SigIndex];
if (!Import.Module.empty()) {
Info.ImportModule = Import.Module;
}
@@ -710,7 +768,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
object_error::parse_failed);
LinkingData.SymbolTable.emplace_back(Info);
Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
- TagType, Signature);
+ Signature);
LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
}
@@ -984,6 +1042,9 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
if (Sec.Name == "dylink") {
if (Error Err = parseDylinkSection(Ctx))
return Err;
+ } else if (Sec.Name == "dylink.0") {
+ if (Error Err = parseDylink0Section(Ctx))
+ return Err;
} else if (Sec.Name == "name") {
if (Error Err = parseNameSection(Ctx))
return Err;
@@ -1034,6 +1095,7 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
+ uint32_t NumTypes = Signatures.size();
Imports.reserve(Count);
for (uint32_t I = 0; I < Count; I++) {
wasm::WasmImport Im;
@@ -1044,6 +1106,9 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
case wasm::WASM_EXTERNAL_FUNCTION:
NumImportedFunctions++;
Im.SigIndex = readVaruint32(Ctx);
+ if (Im.SigIndex >= NumTypes)
+ return make_error<GenericBinaryError>("invalid function type",
+ object_error::parse_failed);
break;
case wasm::WASM_EXTERNAL_GLOBAL:
NumImportedGlobals++;
@@ -1067,8 +1132,13 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
}
case wasm::WASM_EXTERNAL_TAG:
NumImportedTags++;
- Im.Tag.Attribute = readUint8(Ctx);
- Im.Tag.SigIndex = readVarint32(Ctx);
+ if (readUint8(Ctx) != 0) // Reserved 'attribute' field
+ return make_error<GenericBinaryError>("invalid attribute",
+ object_error::parse_failed);
+ Im.SigIndex = readVaruint32(Ctx);
+ if (Im.SigIndex >= NumTypes)
+ return make_error<GenericBinaryError>("invalid tag type",
+ object_error::parse_failed);
break;
default:
return make_error<GenericBinaryError>("unexpected import kind",
@@ -1084,15 +1154,16 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
- FunctionTypes.reserve(Count);
- Functions.resize(Count);
+ Functions.reserve(Count);
uint32_t NumTypes = Signatures.size();
while (Count--) {
uint32_t Type = readVaruint32(Ctx);
if (Type >= NumTypes)
return make_error<GenericBinaryError>("invalid function type",
object_error::parse_failed);
- FunctionTypes.push_back(Type);
+ wasm::WasmFunction F;
+ F.SigIndex = Type;
+ Functions.push_back(F);
}
if (Ctx.Ptr != Ctx.End)
return make_error<GenericBinaryError>("function section ended prematurely",
@@ -1141,11 +1212,18 @@ Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
TagSection = Sections.size();
uint32_t Count = readVaruint32(Ctx);
Tags.reserve(Count);
+ uint32_t NumTypes = Signatures.size();
while (Count--) {
+ if (readUint8(Ctx) != 0) // Reserved 'attribute' field
+ return make_error<GenericBinaryError>("invalid attribute",
+ object_error::parse_failed);
+ uint32_t Type = readVaruint32(Ctx);
+ if (Type >= NumTypes)
+ return make_error<GenericBinaryError>("invalid tag type",
+ object_error::parse_failed);
wasm::WasmTag Tag;
Tag.Index = NumImportedTags + Tags.size();
- Tag.Type.Attribute = readUint8(Ctx);
- Tag.Type.SigIndex = readVaruint32(Ctx);
+ Tag.SigIndex = Type;
Tags.push_back(Tag);
}
@@ -1216,7 +1294,7 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
}
bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
- return Index < NumImportedFunctions + FunctionTypes.size();
+ return Index < NumImportedFunctions + Functions.size();
}
bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
@@ -1304,7 +1382,7 @@ Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
SeenCodeSection = true;
CodeSection = Sections.size();
uint32_t FunctionCount = readVaruint32(Ctx);
- if (FunctionCount != FunctionTypes.size()) {
+ if (FunctionCount != Functions.size()) {
return make_error<GenericBinaryError>("invalid function count",
object_error::parse_failed);
}
@@ -1793,6 +1871,7 @@ int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
case wasm::WASM_SEC_CUSTOM:
return StringSwitch<unsigned>(CustomSectionName)
.Case("dylink", WASM_SEC_ORDER_DYLINK)
+ .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
.Case("linking", WASM_SEC_ORDER_LINKING)
.StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
.Case("name", WASM_SEC_ORDER_NAME)
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;