mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[RuntimeDyld] Plumb Error/Expected through the internals of RuntimeDyld.
Also replaces a number of calls to report_fatal_error with Error returns. The plumbing will make it easier to return errors originating in libObject. Replacing report_fatal_errors with Error returns will give JIT clients the opportunity to recover gracefully when the JIT is unable to produce/relocate code, as well as providing meaningful error messages that can be used to file bug reports. llvm-svn: 267776
This commit is contained in:
parent
89a20099cf
commit
82333c4cad
@ -31,6 +31,19 @@ namespace object {
|
||||
template <typename T> class OwningBinary;
|
||||
}
|
||||
|
||||
/// Base class for errors originating in RuntimeDyld, e.g. missing relocation
|
||||
/// support.
|
||||
class RuntimeDyldError : public ErrorInfo<RuntimeDyldError> {
|
||||
public:
|
||||
static char ID;
|
||||
RuntimeDyldError(std::string ErrMsg) : ErrMsg(std::move(ErrMsg)) {}
|
||||
void log(raw_ostream &OS) const override;
|
||||
const std::string &getErrorMessage() const { return ErrMsg; }
|
||||
std::error_code convertToErrorCode() const override;
|
||||
private:
|
||||
std::string ErrMsg;
|
||||
};
|
||||
|
||||
class RuntimeDyldImpl;
|
||||
class RuntimeDyldCheckerImpl;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "RuntimeDyldMachO.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/MutexGuard.h"
|
||||
|
||||
@ -27,6 +28,38 @@ using namespace llvm::object;
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
namespace {
|
||||
|
||||
enum RuntimeDyldErrorCode {
|
||||
GenericRTDyldError = 1
|
||||
};
|
||||
|
||||
class RuntimeDyldErrorCategory : public std::error_category {
|
||||
public:
|
||||
const char *name() const LLVM_NOEXCEPT override { return "runtimedyld"; }
|
||||
|
||||
std::string message(int Condition) const override {
|
||||
switch (static_cast<RuntimeDyldErrorCode>(Condition)) {
|
||||
case GenericRTDyldError: return "Generic RuntimeDyld error";
|
||||
}
|
||||
llvm_unreachable("Unrecognized RuntimeDyldErrorCode");
|
||||
}
|
||||
};
|
||||
|
||||
static ManagedStatic<RuntimeDyldErrorCategory> RTDyldErrorCategory;
|
||||
|
||||
}
|
||||
|
||||
char RuntimeDyldError::ID = 0;
|
||||
|
||||
void RuntimeDyldError::log(raw_ostream &OS) const {
|
||||
OS << ErrMsg << "\n";
|
||||
}
|
||||
|
||||
std::error_code RuntimeDyldError::convertToErrorCode() const {
|
||||
return std::error_code(GenericRTDyldError, *RTDyldErrorCategory);
|
||||
}
|
||||
|
||||
// Empty out-of-line virtual destructor as the key function.
|
||||
RuntimeDyldImpl::~RuntimeDyldImpl() {}
|
||||
|
||||
@ -125,16 +158,16 @@ void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress,
|
||||
llvm_unreachable("Attempting to remap address of unknown section!");
|
||||
}
|
||||
|
||||
static std::error_code getOffset(const SymbolRef &Sym, SectionRef Sec,
|
||||
uint64_t &Result) {
|
||||
static Error getOffset(const SymbolRef &Sym, SectionRef Sec,
|
||||
uint64_t &Result) {
|
||||
ErrorOr<uint64_t> AddressOrErr = Sym.getAddress();
|
||||
if (std::error_code EC = AddressOrErr.getError())
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
Result = *AddressOrErr - Sec.getAddress();
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
RuntimeDyldImpl::ObjSectionToIDMap
|
||||
Expected<RuntimeDyldImpl::ObjSectionToIDMap>
|
||||
RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
MutexGuard locked(lock);
|
||||
|
||||
@ -148,8 +181,11 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
if (MemMgr.needsToReserveAllocationSpace()) {
|
||||
uint64_t CodeSize = 0, RODataSize = 0, RWDataSize = 0;
|
||||
uint32_t CodeAlign = 1, RODataAlign = 1, RWDataAlign = 1;
|
||||
computeTotalAllocSize(Obj, CodeSize, CodeAlign, RODataSize, RODataAlign,
|
||||
RWDataSize, RWDataAlign);
|
||||
if (auto Err = computeTotalAllocSize(Obj,
|
||||
CodeSize, CodeAlign,
|
||||
RODataSize, RODataAlign,
|
||||
RWDataSize, RWDataAlign))
|
||||
return std::move(Err);
|
||||
MemMgr.reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign,
|
||||
RWDataSize, RWDataAlign);
|
||||
}
|
||||
@ -169,15 +205,21 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
if (Flags & SymbolRef::SF_Common)
|
||||
CommonSymbols.push_back(*I);
|
||||
else {
|
||||
ErrorOr<object::SymbolRef::Type> SymTypeOrErr = I->getType();
|
||||
Check(SymTypeOrErr.getError());
|
||||
object::SymbolRef::Type SymType = *SymTypeOrErr;
|
||||
|
||||
// Get the symbol type.
|
||||
object::SymbolRef::Type SymType;
|
||||
if (auto SymTypeOrErr = I->getType())
|
||||
SymType = *SymTypeOrErr;
|
||||
else
|
||||
return errorCodeToError(SymTypeOrErr.getError());
|
||||
|
||||
// Get symbol name.
|
||||
Expected<StringRef> NameOrErr = I->getName();
|
||||
Check(NameOrErr.takeError());
|
||||
StringRef Name = *NameOrErr;
|
||||
|
||||
StringRef Name;
|
||||
if (auto NameOrErr = I->getName())
|
||||
Name = *NameOrErr;
|
||||
else
|
||||
return NameOrErr.takeError();
|
||||
|
||||
// Compute JIT symbol flags.
|
||||
JITSymbolFlags RTDyldSymFlags = JITSymbolFlags::None;
|
||||
if (Flags & SymbolRef::SF_Weak)
|
||||
@ -187,32 +229,46 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
|
||||
if (Flags & SymbolRef::SF_Absolute &&
|
||||
SymType != object::SymbolRef::ST_File) {
|
||||
auto Addr = I->getAddress();
|
||||
Check(Addr.getError());
|
||||
uint64_t SectOffset = *Addr;
|
||||
uint64_t Addr = 0;
|
||||
if (auto AddrOrErr = I->getAddress())
|
||||
Addr = *AddrOrErr;
|
||||
else
|
||||
return errorCodeToError(AddrOrErr.getError());
|
||||
|
||||
unsigned SectionID = AbsoluteSymbolSection;
|
||||
|
||||
DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name
|
||||
<< " SID: " << SectionID << " Offset: "
|
||||
<< format("%p", (uintptr_t)SectOffset)
|
||||
<< format("%p", (uintptr_t)Addr)
|
||||
<< " flags: " << Flags << "\n");
|
||||
GlobalSymbolTable[Name] =
|
||||
SymbolTableEntry(SectionID, SectOffset, RTDyldSymFlags);
|
||||
SymbolTableEntry(SectionID, Addr, RTDyldSymFlags);
|
||||
} else if (SymType == object::SymbolRef::ST_Function ||
|
||||
SymType == object::SymbolRef::ST_Data ||
|
||||
SymType == object::SymbolRef::ST_Unknown ||
|
||||
SymType == object::SymbolRef::ST_Other) {
|
||||
|
||||
ErrorOr<section_iterator> SIOrErr = I->getSection();
|
||||
Check(SIOrErr.getError());
|
||||
section_iterator SI = *SIOrErr;
|
||||
section_iterator SI = Obj.section_end();
|
||||
if (auto SIOrErr = I->getSection())
|
||||
SI = *SIOrErr;
|
||||
else
|
||||
return errorCodeToError(SIOrErr.getError());
|
||||
|
||||
if (SI == Obj.section_end())
|
||||
continue;
|
||||
|
||||
// Get symbol offset.
|
||||
uint64_t SectOffset;
|
||||
Check(getOffset(*I, *SI, SectOffset));
|
||||
if (auto Err = getOffset(*I, *SI, SectOffset))
|
||||
return std::move(Err);
|
||||
|
||||
bool IsCode = SI->isText();
|
||||
unsigned SectionID = findOrEmitSection(Obj, *SI, IsCode, LocalSections);
|
||||
unsigned SectionID;
|
||||
if (auto SectionIDOrErr = findOrEmitSection(Obj, *SI, IsCode,
|
||||
LocalSections))
|
||||
SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
|
||||
DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name
|
||||
<< " SID: " << SectionID << " Offset: "
|
||||
@ -225,13 +281,13 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
}
|
||||
|
||||
// Allocate common symbols
|
||||
emitCommonSymbols(Obj, CommonSymbols);
|
||||
if (auto Err = emitCommonSymbols(Obj, CommonSymbols))
|
||||
return std::move(Err);
|
||||
|
||||
// Parse and process relocations
|
||||
DEBUG(dbgs() << "Parse relocations:\n");
|
||||
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
||||
SI != SE; ++SI) {
|
||||
unsigned SectionID = 0;
|
||||
StubMap Stubs;
|
||||
section_iterator RelocatedSection = SI->getRelocatedSection();
|
||||
|
||||
@ -245,12 +301,20 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
continue;
|
||||
|
||||
bool IsCode = RelocatedSection->isText();
|
||||
SectionID =
|
||||
findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections);
|
||||
unsigned SectionID = 0;
|
||||
if (auto SectionIDOrErr = findOrEmitSection(Obj, *RelocatedSection, IsCode,
|
||||
LocalSections))
|
||||
SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
|
||||
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
|
||||
|
||||
for (; I != E;)
|
||||
I = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs);
|
||||
if (auto IOrErr = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs))
|
||||
I = *IOrErr;
|
||||
else
|
||||
return IOrErr.takeError();
|
||||
|
||||
// If there is an attached checker, notify it about the stubs for this
|
||||
// section so that they can be verified.
|
||||
@ -259,7 +323,8 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
}
|
||||
|
||||
// Give the subclasses a chance to tie-up any loose ends.
|
||||
finalizeLoad(Obj, LocalSections);
|
||||
if (auto Err = finalizeLoad(Obj, LocalSections))
|
||||
return std::move(Err);
|
||||
|
||||
// for (auto E : LocalSections)
|
||||
// llvm::dbgs() << "Added: " << E.first.getRawDataRefImpl() << " -> " << E.second << "\n";
|
||||
@ -338,13 +403,13 @@ static bool isZeroInit(const SectionRef Section) {
|
||||
|
||||
// Compute an upper bound of the memory size that is required to load all
|
||||
// sections
|
||||
void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
|
||||
uint64_t &CodeSize,
|
||||
uint32_t &CodeAlign,
|
||||
uint64_t &RODataSize,
|
||||
uint32_t &RODataAlign,
|
||||
uint64_t &RWDataSize,
|
||||
uint32_t &RWDataAlign) {
|
||||
Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
|
||||
uint64_t &CodeSize,
|
||||
uint32_t &CodeAlign,
|
||||
uint64_t &RODataSize,
|
||||
uint32_t &RODataAlign,
|
||||
uint64_t &RWDataSize,
|
||||
uint32_t &RWDataAlign) {
|
||||
// Compute the size of all sections required for execution
|
||||
std::vector<uint64_t> CodeSectionSizes;
|
||||
std::vector<uint64_t> ROSectionSizes;
|
||||
@ -360,13 +425,15 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
|
||||
|
||||
// Consider only the sections that are required to be loaded for execution
|
||||
if (IsRequired) {
|
||||
StringRef Name;
|
||||
uint64_t DataSize = Section.getSize();
|
||||
uint64_t Alignment64 = Section.getAlignment();
|
||||
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
|
||||
bool IsCode = Section.isText();
|
||||
bool IsReadOnly = isReadOnlyData(Section);
|
||||
Check(Section.getName(Name));
|
||||
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
|
||||
|
||||
StringRef Name;
|
||||
if (auto EC = Section.getName(Name))
|
||||
return errorCodeToError(EC);
|
||||
|
||||
uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section);
|
||||
uint64_t SectionSize = DataSize + StubBufSize;
|
||||
@ -425,6 +492,8 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
|
||||
CodeSize = computeAllocationSizeForSections(CodeSectionSizes, CodeAlign);
|
||||
RODataSize = computeAllocationSizeForSections(ROSectionSizes, RODataAlign);
|
||||
RWDataSize = computeAllocationSizeForSections(RWSectionSizes, RWDataAlign);
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// compute stub buffer size for the given section
|
||||
@ -492,10 +561,10 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst,
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
|
||||
CommonSymbolList &CommonSymbols) {
|
||||
Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
|
||||
CommonSymbolList &CommonSymbols) {
|
||||
if (CommonSymbols.empty())
|
||||
return;
|
||||
return Error::success();
|
||||
|
||||
uint64_t CommonSize = 0;
|
||||
uint32_t CommonAlign = CommonSymbols.begin()->getAlignment();
|
||||
@ -504,9 +573,11 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
|
||||
DEBUG(dbgs() << "Processing common symbols...\n");
|
||||
|
||||
for (const auto &Sym : CommonSymbols) {
|
||||
Expected<StringRef> NameOrErr = Sym.getName();
|
||||
Check(NameOrErr.takeError());
|
||||
StringRef Name = *NameOrErr;
|
||||
StringRef Name;
|
||||
if (auto NameOrErr = Sym.getName())
|
||||
Name = *NameOrErr;
|
||||
else
|
||||
return NameOrErr.takeError();
|
||||
|
||||
// Skip common symbols already elsewhere.
|
||||
if (GlobalSymbolTable.count(Name) ||
|
||||
@ -543,15 +614,11 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
|
||||
for (auto &Sym : SymbolsToAllocate) {
|
||||
uint32_t Align = Sym.getAlignment();
|
||||
uint64_t Size = Sym.getCommonSize();
|
||||
Expected<StringRef> NameOrErr = Sym.getName();
|
||||
if (!NameOrErr) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
|
||||
OS.flush();
|
||||
report_fatal_error(Buf);
|
||||
}
|
||||
StringRef Name = *NameOrErr;
|
||||
StringRef Name;
|
||||
if (auto NameOrErr = Sym.getName())
|
||||
Name = *NameOrErr;
|
||||
else
|
||||
return NameOrErr.takeError();
|
||||
if (Align) {
|
||||
// This symbol has an alignment requirement.
|
||||
uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align);
|
||||
@ -574,24 +641,29 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
|
||||
|
||||
if (Checker)
|
||||
Checker->registerSection(Obj.getFileName(), SectionID);
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
||||
const SectionRef &Section, bool IsCode) {
|
||||
|
||||
Expected<unsigned>
|
||||
RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode) {
|
||||
StringRef data;
|
||||
uint64_t Alignment64 = Section.getAlignment();
|
||||
|
||||
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
|
||||
unsigned PaddingSize = 0;
|
||||
unsigned StubBufSize = 0;
|
||||
StringRef Name;
|
||||
bool IsRequired = isRequiredForExecution(Section);
|
||||
bool IsVirtual = Section.isVirtual();
|
||||
bool IsZeroInit = isZeroInit(Section);
|
||||
bool IsReadOnly = isReadOnlyData(Section);
|
||||
uint64_t DataSize = Section.getSize();
|
||||
Check(Section.getName(Name));
|
||||
|
||||
StringRef Name;
|
||||
if (auto EC = Section.getName(Name))
|
||||
return errorCodeToError(EC);
|
||||
|
||||
StubBufSize = computeSectionStubBufSize(Obj, Section);
|
||||
|
||||
@ -611,7 +683,8 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
||||
if (!IsVirtual && !IsZeroInit) {
|
||||
// In either case, set the location of the unrelocated section in memory,
|
||||
// since we still process relocations for it even if we're not applying them.
|
||||
Check(Section.getContents(data));
|
||||
if (auto EC = Section.getContents(data))
|
||||
return errorCodeToError(EC);
|
||||
pData = data.data();
|
||||
}
|
||||
|
||||
@ -673,17 +746,21 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
||||
return SectionID;
|
||||
}
|
||||
|
||||
unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode,
|
||||
ObjSectionToIDMap &LocalSections) {
|
||||
Expected<unsigned>
|
||||
RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode,
|
||||
ObjSectionToIDMap &LocalSections) {
|
||||
|
||||
unsigned SectionID = 0;
|
||||
ObjSectionToIDMap::iterator i = LocalSections.find(Section);
|
||||
if (i != LocalSections.end())
|
||||
SectionID = i->second;
|
||||
else {
|
||||
SectionID = emitSection(Obj, Section, IsCode);
|
||||
if (auto SectionIDOrErr = emitSection(Obj, Section, IsCode))
|
||||
SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
LocalSections[Section] = SectionID;
|
||||
}
|
||||
return SectionID;
|
||||
|
@ -57,7 +57,14 @@ llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
|
||||
return llvm::make_unique<LoadedCOFFObjectInfo>(*this, loadObjectImpl(O));
|
||||
if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
|
||||
return llvm::make_unique<LoadedCOFFObjectInfo>(*this, *ObjSectionToIDOrErr);
|
||||
else {
|
||||
HasError = true;
|
||||
raw_string_ostream ErrStream(ErrorStr);
|
||||
logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, "");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
|
||||
|
@ -30,13 +30,6 @@ using namespace llvm::object;
|
||||
|
||||
#define DEBUG_TYPE "dyld"
|
||||
|
||||
static inline std::error_code check(std::error_code Err) {
|
||||
if (Err) {
|
||||
report_fatal_error(Err.message());
|
||||
}
|
||||
return Err;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
|
||||
@ -220,7 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() {
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
RuntimeDyldELF::loadObject(const object::ObjectFile &O) {
|
||||
return llvm::make_unique<LoadedELFObjectInfo>(*this, loadObjectImpl(O));
|
||||
if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
|
||||
return llvm::make_unique<LoadedELFObjectInfo>(*this, *ObjSectionToIDOrErr);
|
||||
else {
|
||||
HasError = true;
|
||||
raw_string_ostream ErrStream(ErrorStr);
|
||||
logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, "");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
||||
@ -781,9 +781,9 @@ void RuntimeDyldELF::applyMIPS64Relocation(uint8_t *TargetPtr,
|
||||
}
|
||||
|
||||
// Return the .TOC. section and offset.
|
||||
void RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel) {
|
||||
Error RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel) {
|
||||
// Set a default SectionID in case we do not find a TOC section below.
|
||||
// This may happen for references to TOC base base (sym@toc, .odp
|
||||
// relocation) without a .toc directive. In this case just use the
|
||||
@ -796,13 +796,18 @@ void RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,
|
||||
// order. The TOC starts where the first of these sections starts.
|
||||
for (auto &Section: Obj.sections()) {
|
||||
StringRef SectionName;
|
||||
check(Section.getName(SectionName));
|
||||
if (auto EC = Section.getName(SectionName))
|
||||
return errorCodeToError(EC);
|
||||
|
||||
if (SectionName == ".got"
|
||||
|| SectionName == ".toc"
|
||||
|| SectionName == ".tocbss"
|
||||
|| SectionName == ".plt") {
|
||||
Rel.SectionID = findOrEmitSection(Obj, Section, false, LocalSections);
|
||||
if (auto SectionIDOrErr =
|
||||
findOrEmitSection(Obj, Section, false, LocalSections))
|
||||
Rel.SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -810,13 +815,15 @@ void RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,
|
||||
// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
|
||||
// thus permitting a full 64 Kbytes segment.
|
||||
Rel.Addend = 0x8000;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Returns the sections and offset associated with the ODP entry referenced
|
||||
// by Symbol.
|
||||
void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel) {
|
||||
Error RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel) {
|
||||
// Get the ELF symbol value (st_value) to compare with Relocation offset in
|
||||
// .opd entries
|
||||
for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
|
||||
@ -826,7 +833,9 @@ void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
continue;
|
||||
|
||||
StringRef RelSectionName;
|
||||
check(RelSecI->getName(RelSectionName));
|
||||
if (auto EC = RelSecI->getName(RelSectionName))
|
||||
return errorCodeToError(EC);
|
||||
|
||||
if (RelSectionName != ".opd")
|
||||
continue;
|
||||
|
||||
@ -843,9 +852,11 @@ void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
|
||||
uint64_t TargetSymbolOffset = i->getOffset();
|
||||
symbol_iterator TargetSymbol = i->getSymbol();
|
||||
ErrorOr<int64_t> AddendOrErr = i->getAddend();
|
||||
Check(AddendOrErr.getError());
|
||||
int64_t Addend = *AddendOrErr;
|
||||
int64_t Addend;
|
||||
if (auto AddendOrErr = i->getAddend())
|
||||
Addend = *AddendOrErr;
|
||||
else
|
||||
return errorCodeToError(AddendOrErr.getError());
|
||||
|
||||
++i;
|
||||
if (i == e)
|
||||
@ -862,13 +873,21 @@ void RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
if (Rel.Addend != (int64_t)TargetSymbolOffset)
|
||||
continue;
|
||||
|
||||
ErrorOr<section_iterator> TSIOrErr = TargetSymbol->getSection();
|
||||
check(TSIOrErr.getError());
|
||||
section_iterator tsi = *TSIOrErr;
|
||||
bool IsCode = tsi->isText();
|
||||
Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections);
|
||||
section_iterator TSI = Obj.section_end();
|
||||
if (auto TSIOrErr = TargetSymbol->getSection())
|
||||
TSI = *TSIOrErr;
|
||||
else
|
||||
return errorCodeToError(TSIOrErr.getError());
|
||||
assert(TSI != Obj.section_end() && "TSI should refer to a valid section");
|
||||
|
||||
bool IsCode = TSI->isText();
|
||||
if (auto SectionIDOrErr = findOrEmitSection(Obj, *TSI, IsCode,
|
||||
LocalSections))
|
||||
Rel.SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
Rel.Addend = (intptr_t)Addend;
|
||||
return;
|
||||
return Error::success();
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Attempting to get address of ODP entry!");
|
||||
@ -1163,7 +1182,8 @@ uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType,
|
||||
return ELF::R_MIPS_NONE;
|
||||
}
|
||||
|
||||
relocation_iterator RuntimeDyldELF::processRelocationRef(
|
||||
Expected<relocation_iterator>
|
||||
RuntimeDyldELF::processRelocationRef(
|
||||
unsigned SectionID, relocation_iterator RelI, const ObjectFile &O,
|
||||
ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) {
|
||||
const auto &Obj = cast<ELFObjectFileBase>(O);
|
||||
@ -1175,15 +1195,10 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
|
||||
// Obtain the symbol name which is referenced in the relocation
|
||||
StringRef TargetName;
|
||||
if (Symbol != Obj.symbol_end()) {
|
||||
Expected<StringRef> TargetNameOrErr = Symbol->getName();
|
||||
if (!TargetNameOrErr) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(TargetNameOrErr.takeError(), OS, "");
|
||||
OS.flush();
|
||||
report_fatal_error(Buf);
|
||||
}
|
||||
TargetName = *TargetNameOrErr;
|
||||
if (auto TargetNameOrErr = Symbol->getName())
|
||||
TargetName = *TargetNameOrErr;
|
||||
else
|
||||
return TargetNameOrErr.takeError();
|
||||
}
|
||||
DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend
|
||||
<< " TargetName: " << TargetName << "\n");
|
||||
@ -1216,7 +1231,11 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
|
||||
llvm_unreachable("Symbol section not found, bad object file format!");
|
||||
DEBUG(dbgs() << "\t\tThis is section symbol\n");
|
||||
bool isCode = si->isText();
|
||||
Value.SectionID = findOrEmitSection(Obj, (*si), isCode, ObjSectionToID);
|
||||
if (auto SectionIDOrErr = findOrEmitSection(Obj, (*si), isCode,
|
||||
ObjSectionToID))
|
||||
Value.SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
Value.Addend = Addend;
|
||||
break;
|
||||
}
|
||||
@ -1801,11 +1820,11 @@ RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(unsigned SectionID, uint64_t
|
||||
return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset);
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
|
||||
Error RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) {
|
||||
if (IsMipsO32ABI)
|
||||
if (!PendingRelocs.empty())
|
||||
report_fatal_error("Can't find matching LO16 reloc");
|
||||
return make_error<RuntimeDyldError>("Can't find matching LO16 reloc");
|
||||
|
||||
// If necessary, allocate the global offset table
|
||||
if (GOTSectionID != 0) {
|
||||
@ -1814,7 +1833,7 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
|
||||
uint8_t *Addr = MemMgr.allocateDataSection(TotalSize, getGOTEntrySize(),
|
||||
GOTSectionID, ".got", false);
|
||||
if (!Addr)
|
||||
report_fatal_error("Unable to allocate memory for GOT!");
|
||||
return make_error<RuntimeDyldError>("Unable to allocate memory for GOT!");
|
||||
|
||||
Sections[GOTSectionID] =
|
||||
SectionEntry(".got", Addr, TotalSize, TotalSize, 0);
|
||||
@ -1855,6 +1874,8 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
|
||||
|
||||
GOTSectionID = 0;
|
||||
CurrentGOTIndex = 0;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||
|
@ -90,12 +90,12 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
|
||||
void setMipsABI(const ObjectFile &Obj) override;
|
||||
|
||||
void findPPC64TOCSection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel);
|
||||
void findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel);
|
||||
Error findPPC64TOCSection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel);
|
||||
Error findOPDEntrySection(const ELFObjectFileBase &Obj,
|
||||
ObjSectionToIDMap &LocalSections,
|
||||
RelocationValueRef &Rel);
|
||||
|
||||
size_t getGOTEntrySize();
|
||||
|
||||
@ -163,7 +163,7 @@ public:
|
||||
loadObject(const object::ObjectFile &O) override;
|
||||
|
||||
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override;
|
||||
relocation_iterator
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
@ -171,8 +171,8 @@ public:
|
||||
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
|
||||
void registerEHFrames() override;
|
||||
void deregisterEHFrames() override;
|
||||
void finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override;
|
||||
Error finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -36,25 +36,12 @@ using namespace llvm::object;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// Helper for extensive error checking in debug builds.
|
||||
inline std::error_code Check(std::error_code Err) {
|
||||
if (Err) {
|
||||
report_fatal_error(Err.message());
|
||||
}
|
||||
return Err;
|
||||
}
|
||||
inline void Check(llvm::Error Err) {
|
||||
if (Err) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(std::move(Err), OS, "");
|
||||
OS.flush();
|
||||
report_fatal_error(Buf);
|
||||
}
|
||||
}
|
||||
|
||||
class Twine;
|
||||
|
||||
#define UNIMPLEMENTED_RELOC(RelType) \
|
||||
case RelType: \
|
||||
return make_error<RuntimeDyldError>("Unimplemented relocation: " #RelType)
|
||||
|
||||
/// SectionEntry - represents a section emitted into memory by the dynamic
|
||||
/// linker.
|
||||
class SectionEntry {
|
||||
@ -309,13 +296,6 @@ protected:
|
||||
bool HasError;
|
||||
std::string ErrorStr;
|
||||
|
||||
// Set the error state and record an error string.
|
||||
bool Error(const Twine &Msg) {
|
||||
ErrorStr = Msg.str();
|
||||
HasError = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t getSectionLoadAddress(unsigned SectionID) const {
|
||||
return Sections[SectionID].getLoadAddress();
|
||||
}
|
||||
@ -368,22 +348,25 @@ protected:
|
||||
/// \brief Given the common symbols discovered in the object file, emit a
|
||||
/// new section for them and update the symbol mappings in the object and
|
||||
/// symbol table.
|
||||
void emitCommonSymbols(const ObjectFile &Obj, CommonSymbolList &CommonSymbols);
|
||||
Error emitCommonSymbols(const ObjectFile &Obj,
|
||||
CommonSymbolList &CommonSymbols);
|
||||
|
||||
/// \brief Emits section data from the object file to the MemoryManager.
|
||||
/// \param IsCode if it's true then allocateCodeSection() will be
|
||||
/// used for emits, else allocateDataSection() will be used.
|
||||
/// \return SectionID.
|
||||
unsigned emitSection(const ObjectFile &Obj, const SectionRef &Section,
|
||||
bool IsCode);
|
||||
Expected<unsigned> emitSection(const ObjectFile &Obj,
|
||||
const SectionRef &Section,
|
||||
bool IsCode);
|
||||
|
||||
/// \brief Find Section in LocalSections. If the secton is not found - emit
|
||||
/// it and store in LocalSections.
|
||||
/// \param IsCode if it's true then allocateCodeSection() will be
|
||||
/// used for emmits, else allocateDataSection() will be used.
|
||||
/// \return SectionID.
|
||||
unsigned findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section,
|
||||
bool IsCode, ObjSectionToIDMap &LocalSections);
|
||||
Expected<unsigned> findOrEmitSection(const ObjectFile &Obj,
|
||||
const SectionRef &Section, bool IsCode,
|
||||
ObjSectionToIDMap &LocalSections);
|
||||
|
||||
// \brief Add a relocation entry that uses the given section.
|
||||
void addRelocationForSection(const RelocationEntry &RE, unsigned SectionID);
|
||||
@ -408,7 +391,7 @@ protected:
|
||||
/// relocation pairs) and stores it to Relocations or SymbolRelocations
|
||||
/// (this depends on the object file type).
|
||||
/// \return Iterator to the next relocation that needs to be parsed.
|
||||
virtual relocation_iterator
|
||||
virtual Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) = 0;
|
||||
@ -418,17 +401,17 @@ protected:
|
||||
|
||||
// \brief Compute an upper bound of the memory that is required to load all
|
||||
// sections
|
||||
void computeTotalAllocSize(const ObjectFile &Obj,
|
||||
uint64_t &CodeSize, uint32_t &CodeAlign,
|
||||
uint64_t &RODataSize, uint32_t &RODataAlign,
|
||||
uint64_t &RWDataSize, uint32_t &RWDataAlign);
|
||||
Error computeTotalAllocSize(const ObjectFile &Obj,
|
||||
uint64_t &CodeSize, uint32_t &CodeAlign,
|
||||
uint64_t &RODataSize, uint32_t &RODataAlign,
|
||||
uint64_t &RWDataSize, uint32_t &RWDataAlign);
|
||||
|
||||
// \brief Compute the stub buffer size required for a section
|
||||
unsigned computeSectionStubBufSize(const ObjectFile &Obj,
|
||||
const SectionRef &Section);
|
||||
|
||||
// \brief Implementation of the generic part of the loadObject algorithm.
|
||||
ObjSectionToIDMap loadObjectImpl(const object::ObjectFile &Obj);
|
||||
Expected<ObjSectionToIDMap> loadObjectImpl(const object::ObjectFile &Obj);
|
||||
|
||||
// \brief Return true if the relocation R may require allocating a stub.
|
||||
virtual bool relocationNeedsStub(const RelocationRef &R) const {
|
||||
@ -503,8 +486,10 @@ public:
|
||||
|
||||
virtual void deregisterEHFrames();
|
||||
|
||||
virtual void finalizeLoad(const ObjectFile &ObjImg,
|
||||
ObjSectionToIDMap &SectionMap) {}
|
||||
virtual Error finalizeLoad(const ObjectFile &ObjImg,
|
||||
ObjSectionToIDMap &SectionMap) {
|
||||
return Error::success();
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -50,7 +50,8 @@ int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const {
|
||||
return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes));
|
||||
}
|
||||
|
||||
relocation_iterator RuntimeDyldMachO::processScatteredVANILLA(
|
||||
Expected<relocation_iterator>
|
||||
RuntimeDyldMachO::processScatteredVANILLA(
|
||||
unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) {
|
||||
@ -74,8 +75,12 @@ relocation_iterator RuntimeDyldMachO::processScatteredVANILLA(
|
||||
uint64_t SectionBaseAddr = TargetSI->getAddress();
|
||||
SectionRef TargetSection = *TargetSI;
|
||||
bool IsCode = TargetSection.isText();
|
||||
uint32_t TargetSectionID =
|
||||
findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID);
|
||||
uint32_t TargetSectionID = ~0U;
|
||||
if (auto TargetSectionIDOrErr =
|
||||
findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID))
|
||||
TargetSectionID = *TargetSectionIDOrErr;
|
||||
else
|
||||
return TargetSectionIDOrErr.takeError();
|
||||
|
||||
Addend -= SectionBaseAddr;
|
||||
RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size);
|
||||
@ -86,7 +91,8 @@ relocation_iterator RuntimeDyldMachO::processScatteredVANILLA(
|
||||
}
|
||||
|
||||
|
||||
RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
||||
Expected<RelocationValueRef>
|
||||
RuntimeDyldMachO::getRelocationValueRef(
|
||||
const ObjectFile &BaseTObj, const relocation_iterator &RI,
|
||||
const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) {
|
||||
|
||||
@ -99,15 +105,11 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
||||
bool IsExternal = Obj.getPlainRelocationExternal(RelInfo);
|
||||
if (IsExternal) {
|
||||
symbol_iterator Symbol = RI->getSymbol();
|
||||
Expected<StringRef> TargetNameOrErr = Symbol->getName();
|
||||
if (!TargetNameOrErr) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(TargetNameOrErr.takeError(), OS, "");
|
||||
OS.flush();
|
||||
report_fatal_error(Buf);
|
||||
}
|
||||
StringRef TargetName = *TargetNameOrErr;
|
||||
StringRef TargetName;
|
||||
if (auto TargetNameOrErr = Symbol->getName())
|
||||
TargetName = *TargetNameOrErr;
|
||||
else
|
||||
return TargetNameOrErr.takeError();
|
||||
RTDyldSymbolTable::const_iterator SI =
|
||||
GlobalSymbolTable.find(TargetName.data());
|
||||
if (SI != GlobalSymbolTable.end()) {
|
||||
@ -121,7 +123,11 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
||||
} else {
|
||||
SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
|
||||
bool IsCode = Sec.isText();
|
||||
Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
|
||||
if (auto SectionIDOrErr = findOrEmitSection(Obj, Sec, IsCode,
|
||||
ObjSectionToID))
|
||||
Value.SectionID = *SectionIDOrErr;
|
||||
else
|
||||
return SectionIDOrErr.takeError();
|
||||
uint64_t Addr = Sec.getAddress();
|
||||
Value.Offset = RE.Addend - Addr;
|
||||
}
|
||||
@ -169,7 +175,7 @@ RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj,
|
||||
|
||||
|
||||
// Populate __pointers section.
|
||||
void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
||||
Error RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
||||
const MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID) {
|
||||
@ -196,15 +202,11 @@ void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
||||
unsigned SymbolIndex =
|
||||
Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
|
||||
symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
|
||||
Expected<StringRef> IndirectSymbolNameOrErr = SI->getName();
|
||||
if (!IndirectSymbolNameOrErr) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(IndirectSymbolNameOrErr.takeError(), OS, "");
|
||||
OS.flush();
|
||||
report_fatal_error(Buf);
|
||||
}
|
||||
StringRef IndirectSymbolName = *IndirectSymbolNameOrErr;
|
||||
StringRef IndirectSymbolName;
|
||||
if (auto IndirectSymbolNameOrErr = SI->getName())
|
||||
IndirectSymbolName = *IndirectSymbolNameOrErr;
|
||||
else
|
||||
return IndirectSymbolNameOrErr.takeError();
|
||||
DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex
|
||||
<< ", PT offset: " << PTEntryOffset << "\n");
|
||||
RelocationEntry RE(PTSectionID, PTEntryOffset,
|
||||
@ -212,6 +214,7 @@ void RuntimeDyldMachO::populateIndirectSymbolPointersSection(
|
||||
addRelocationForSymbol(RE, IndirectSymbolName);
|
||||
PTEntryOffset += PTEntrySize;
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||
@ -219,8 +222,9 @@ bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) {
|
||||
Error
|
||||
RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) {
|
||||
unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
|
||||
unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
|
||||
unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
|
||||
@ -232,20 +236,34 @@ void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
|
||||
// Force emission of the __text, __eh_frame, and __gcc_except_tab sections
|
||||
// if they're present. Otherwise call down to the impl to handle other
|
||||
// sections that have already been emitted.
|
||||
if (Name == "__text")
|
||||
TextSID = findOrEmitSection(Obj, Section, true, SectionMap);
|
||||
else if (Name == "__eh_frame")
|
||||
EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap);
|
||||
else if (Name == "__gcc_except_tab")
|
||||
ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap);
|
||||
else {
|
||||
if (Name == "__text") {
|
||||
if (auto TextSIDOrErr = findOrEmitSection(Obj, Section, true, SectionMap))
|
||||
TextSID = *TextSIDOrErr;
|
||||
else
|
||||
return TextSIDOrErr.takeError();
|
||||
} else if (Name == "__eh_frame") {
|
||||
if (auto EHFrameSIDOrErr = findOrEmitSection(Obj, Section, false,
|
||||
SectionMap))
|
||||
EHFrameSID = *EHFrameSIDOrErr;
|
||||
else
|
||||
return EHFrameSIDOrErr.takeError();
|
||||
} else if (Name == "__gcc_except_tab") {
|
||||
if (auto ExceptTabSIDOrErr = findOrEmitSection(Obj, Section, true,
|
||||
SectionMap))
|
||||
ExceptTabSID = *ExceptTabSIDOrErr;
|
||||
else
|
||||
return ExceptTabSIDOrErr.takeError();
|
||||
} else {
|
||||
auto I = SectionMap.find(Section);
|
||||
if (I != SectionMap.end())
|
||||
impl().finalizeSection(Obj, I->second, Section);
|
||||
if (auto Err = impl().finalizeSection(Obj, I->second, Section))
|
||||
return Err;
|
||||
}
|
||||
}
|
||||
UnregisteredEHFrameSections.push_back(
|
||||
EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
@ -343,7 +361,15 @@ RuntimeDyldMachO::create(Triple::ArchType Arch,
|
||||
|
||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
||||
RuntimeDyldMachO::loadObject(const object::ObjectFile &O) {
|
||||
return llvm::make_unique<LoadedMachOObjectInfo>(*this, loadObjectImpl(O));
|
||||
if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
|
||||
return llvm::make_unique<LoadedMachOObjectInfo>(*this,
|
||||
*ObjSectionToIDOrErr);
|
||||
else {
|
||||
HasError = true;
|
||||
raw_string_ostream ErrStream(ErrorStr);
|
||||
logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, "");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -80,10 +80,10 @@ protected:
|
||||
}
|
||||
|
||||
/// Process a scattered vanilla relocation.
|
||||
relocation_iterator processScatteredVANILLA(
|
||||
unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID);
|
||||
Expected<relocation_iterator>
|
||||
processScatteredVANILLA(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID);
|
||||
|
||||
/// Construct a RelocationValueRef representing the relocation target.
|
||||
/// For Symbols in known sections, this will return a RelocationValueRef
|
||||
@ -94,10 +94,11 @@ protected:
|
||||
/// In both cases the Addend field is *NOT* fixed up to be PC-relative. That
|
||||
/// should be done by the caller where appropriate by calling makePCRel on
|
||||
/// the RelocationValueRef.
|
||||
RelocationValueRef getRelocationValueRef(const ObjectFile &BaseTObj,
|
||||
const relocation_iterator &RI,
|
||||
const RelocationEntry &RE,
|
||||
ObjSectionToIDMap &ObjSectionToID);
|
||||
Expected<RelocationValueRef>
|
||||
getRelocationValueRef(const ObjectFile &BaseTObj,
|
||||
const relocation_iterator &RI,
|
||||
const RelocationEntry &RE,
|
||||
ObjSectionToIDMap &ObjSectionToID);
|
||||
|
||||
/// Make the RelocationValueRef addend PC-relative.
|
||||
void makeValueAddendPCRel(RelocationValueRef &Value,
|
||||
@ -113,9 +114,9 @@ protected:
|
||||
|
||||
|
||||
// Populate __pointers section.
|
||||
void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID);
|
||||
Error populateIndirectSymbolPointersSection(const MachOObjectFile &Obj,
|
||||
const SectionRef &PTSection,
|
||||
unsigned PTSectionID);
|
||||
|
||||
public:
|
||||
|
||||
@ -154,8 +155,8 @@ public:
|
||||
RuntimeDyld::SymbolResolver &Resolver)
|
||||
: RuntimeDyldMachO(MemMgr, Resolver) {}
|
||||
|
||||
void finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override;
|
||||
Error finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override;
|
||||
void registerEHFrames() override;
|
||||
};
|
||||
|
||||
|
@ -34,11 +34,13 @@ public:
|
||||
|
||||
unsigned getStubAlignment() override { return 1; }
|
||||
|
||||
relocation_iterator processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
|
||||
auto Symbol = RelI->getSymbol();
|
||||
if (Symbol == Obj.symbol_end())
|
||||
report_fatal_error("Unknown symbol in relocation");
|
||||
@ -71,8 +73,11 @@ public:
|
||||
RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
|
||||
addRelocationForSymbol(RE, TargetName);
|
||||
} else {
|
||||
TargetSectionID =
|
||||
findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID);
|
||||
if (auto TargetSectionIDOrErr =
|
||||
findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
|
||||
TargetSectionID = *TargetSectionIDOrErr;
|
||||
else
|
||||
return TargetSectionIDOrErr.takeError();
|
||||
|
||||
switch (RelType) {
|
||||
case COFF::IMAGE_REL_I386_ABSOLUTE:
|
||||
@ -195,9 +200,6 @@ public:
|
||||
|
||||
void registerEHFrames() override {}
|
||||
void deregisterEHFrames() override {}
|
||||
|
||||
void finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -106,11 +106,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
relocation_iterator processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID,
|
||||
relocation_iterator RelI,
|
||||
const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
StubMap &Stubs) override {
|
||||
// If possible, find the symbol referred to in the relocation,
|
||||
// and the section that contains it.
|
||||
symbol_iterator Symbol = RelI->getSymbol();
|
||||
@ -170,8 +171,12 @@ public:
|
||||
addRelocationForSymbol(RE, TargetName);
|
||||
} else {
|
||||
bool IsCode = SecI->isText();
|
||||
unsigned TargetSectionID =
|
||||
findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID);
|
||||
unsigned TargetSectionID;
|
||||
if (auto TargetSectionIDOrErr =
|
||||
findOrEmitSection(Obj, *SecI, IsCode, ObjSectionToID))
|
||||
TargetSectionID = *TargetSectionIDOrErr;
|
||||
else
|
||||
return TargetSectionIDOrErr.takeError();
|
||||
uint64_t TargetOffset = getSymbolOffset(*Symbol);
|
||||
RelocationEntry RE(SectionID, Offset, RelType, TargetOffset + Addend);
|
||||
addRelocationForSection(RE, TargetSectionID);
|
||||
@ -194,19 +199,21 @@ public:
|
||||
void deregisterEHFrames() override {
|
||||
// Stub
|
||||
}
|
||||
void finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override {
|
||||
Error finalizeLoad(const ObjectFile &Obj,
|
||||
ObjSectionToIDMap &SectionMap) override {
|
||||
// Look for and record the EH frame section IDs.
|
||||
for (const auto &SectionPair : SectionMap) {
|
||||
const SectionRef &Section = SectionPair.first;
|
||||
StringRef Name;
|
||||
Check(Section.getName(Name));
|
||||
if (auto EC = Section.getName(Name))
|
||||
return errorCodeToError(EC);
|
||||
// Note unwind info is split across .pdata and .xdata, so this
|
||||
// may not be sufficiently general for all users.
|
||||
if (Name == ".xdata") {
|
||||
UnregisteredEHFrameSections.push_back(SectionPair.second);
|
||||
}
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -242,7 +242,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
relocation_iterator
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
@ -252,7 +252,9 @@ public:
|
||||
MachO::any_relocation_info RelInfo =
|
||||
Obj.getRelocation(RelI->getRawDataRefImpl());
|
||||
|
||||
assert(!Obj.isRelocationScattered(RelInfo) && "");
|
||||
if (Obj.isRelocationScattered(RelInfo))
|
||||
return make_error<RuntimeDyldError>("Scattered relocations not supported "
|
||||
"for MachO AArch64");
|
||||
|
||||
// ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit
|
||||
// addend for the following relocation. If found: (1) store the associated
|
||||
@ -281,8 +283,11 @@ public:
|
||||
if (ExplicitAddend)
|
||||
RE.Addend = ExplicitAddend;
|
||||
|
||||
RelocationValueRef Value(
|
||||
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID));
|
||||
RelocationValueRef Value;
|
||||
if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
|
||||
Value = *ValueOrErr;
|
||||
else
|
||||
return ValueOrErr.takeError();
|
||||
|
||||
bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
|
||||
if (!IsExtern && RE.IsPCRel)
|
||||
@ -371,8 +376,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
const SectionRef &Section) {}
|
||||
Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
const SectionRef &Section) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
void processGOTRelocation(const RelocationEntry &RE,
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
relocation_iterator
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
@ -70,10 +70,30 @@ public:
|
||||
return ++RelI;
|
||||
}
|
||||
|
||||
// Sanity check relocation type.
|
||||
switch (RelType) {
|
||||
UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PAIR);
|
||||
UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_SECTDIFF);
|
||||
UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_LOCAL_SECTDIFF);
|
||||
UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PB_LA_PTR);
|
||||
UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_RELOC_BR22);
|
||||
UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_32BIT_BRANCH);
|
||||
UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_HALF);
|
||||
default:
|
||||
if (RelType > MachO::ARM_RELOC_HALF_SECTDIFF)
|
||||
return make_error<RuntimeDyldError>("MachO ARM relocation type " +
|
||||
std::to_string(RelType) +
|
||||
" is out of range");
|
||||
break;
|
||||
}
|
||||
|
||||
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||
RE.Addend = decodeAddend(RE);
|
||||
RelocationValueRef Value(
|
||||
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID));
|
||||
RelocationValueRef Value;
|
||||
if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
|
||||
Value = *ValueOrErr;
|
||||
else
|
||||
return ValueOrErr.takeError();
|
||||
|
||||
if (RE.IsPCRel)
|
||||
makeValueAddendPCRel(Value, RelI, 8);
|
||||
@ -108,8 +128,6 @@ public:
|
||||
}
|
||||
|
||||
switch (RE.RelType) {
|
||||
default:
|
||||
llvm_unreachable("Invalid relocation type!");
|
||||
case MachO::ARM_RELOC_VANILLA:
|
||||
writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
|
||||
break;
|
||||
@ -147,26 +165,20 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
case MachO::ARM_THUMB_RELOC_BR22:
|
||||
case MachO::ARM_THUMB_32BIT_BRANCH:
|
||||
case MachO::ARM_RELOC_HALF:
|
||||
case MachO::ARM_RELOC_PAIR:
|
||||
case MachO::ARM_RELOC_SECTDIFF:
|
||||
case MachO::ARM_RELOC_LOCAL_SECTDIFF:
|
||||
case MachO::ARM_RELOC_PB_LA_PTR:
|
||||
Error("Relocation type not implemented yet!");
|
||||
return;
|
||||
default:
|
||||
llvm_unreachable("Invalid relocation type");
|
||||
}
|
||||
}
|
||||
|
||||
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
const SectionRef &Section) {
|
||||
StringRef Name;
|
||||
Section.getName(Name);
|
||||
|
||||
if (Name == "__nl_symbol_ptr")
|
||||
populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
|
||||
Section, SectionID);
|
||||
return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
|
||||
Section, SectionID);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -201,7 +213,7 @@ private:
|
||||
resolveRelocation(TargetRE, (uint64_t)Addr);
|
||||
}
|
||||
|
||||
relocation_iterator
|
||||
Expected<relocation_iterator>
|
||||
processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseTObj,
|
||||
ObjSectionToIDMap &ObjSectionToID) {
|
||||
@ -237,8 +249,12 @@ private:
|
||||
uint64_t SectionAOffset = AddrA - SectionABase;
|
||||
SectionRef SectionA = *SAI;
|
||||
bool IsCode = SectionA.isText();
|
||||
uint32_t SectionAID =
|
||||
findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID);
|
||||
uint32_t SectionAID = ~0U;
|
||||
if (auto SectionAIDOrErr =
|
||||
findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID))
|
||||
SectionAID = *SectionAIDOrErr;
|
||||
else
|
||||
return SectionAIDOrErr.takeError();
|
||||
|
||||
uint32_t AddrB = MachO.getScatteredRelocationValue(RE2);
|
||||
section_iterator SBI = getSectionByAddress(MachO, AddrB);
|
||||
@ -246,8 +262,12 @@ private:
|
||||
uint64_t SectionBBase = SBI->getAddress();
|
||||
uint64_t SectionBOffset = AddrB - SectionBBase;
|
||||
SectionRef SectionB = *SBI;
|
||||
uint32_t SectionBID =
|
||||
findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID);
|
||||
uint32_t SectionBID = ~0U;
|
||||
if (auto SectionBIDOrErr =
|
||||
findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID))
|
||||
SectionBID = *SectionBIDOrErr;
|
||||
else
|
||||
return SectionBIDOrErr.takeError();
|
||||
|
||||
uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff;
|
||||
unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0;
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
|
||||
unsigned getStubAlignment() override { return 1; }
|
||||
|
||||
relocation_iterator
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
@ -48,13 +48,29 @@ public:
|
||||
ObjSectionToID);
|
||||
else if (RelType == MachO::GENERIC_RELOC_VANILLA)
|
||||
return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID);
|
||||
llvm_unreachable("Unhandled scattered relocation.");
|
||||
return make_error<RuntimeDyldError>("Unhandled I386 scattered relocation "
|
||||
"type: " + std::to_string(RelType));
|
||||
}
|
||||
|
||||
switch (RelType) {
|
||||
UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR);
|
||||
UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR);
|
||||
UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV);
|
||||
default:
|
||||
if (RelType > MachO::GENERIC_RELOC_TLV)
|
||||
return make_error<RuntimeDyldError>("MachO I386 relocation type " +
|
||||
std::to_string(RelType) +
|
||||
" is out of range");
|
||||
break;
|
||||
}
|
||||
|
||||
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||
RE.Addend = memcpyAddend(RE);
|
||||
RelocationValueRef Value(
|
||||
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID));
|
||||
RelocationValueRef Value;
|
||||
if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
|
||||
Value = *ValueOrErr;
|
||||
else
|
||||
return ValueOrErr.takeError();
|
||||
|
||||
// Addends for external, PC-rel relocations on i386 point back to the zero
|
||||
// offset. Calculate the final offset from the relocation target instead.
|
||||
@ -91,8 +107,6 @@ public:
|
||||
}
|
||||
|
||||
switch (RE.RelType) {
|
||||
default:
|
||||
llvm_unreachable("Invalid relocation type!");
|
||||
case MachO::GENERIC_RELOC_VANILLA:
|
||||
writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
|
||||
break;
|
||||
@ -106,25 +120,26 @@ public:
|
||||
writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
|
||||
break;
|
||||
}
|
||||
case MachO::GENERIC_RELOC_PB_LA_PTR:
|
||||
Error("Relocation type not implemented yet!");
|
||||
default:
|
||||
llvm_unreachable("Invalid relocation type!");
|
||||
}
|
||||
}
|
||||
|
||||
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
const SectionRef &Section) {
|
||||
StringRef Name;
|
||||
Section.getName(Name);
|
||||
|
||||
if (Name == "__jump_table")
|
||||
populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID);
|
||||
return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID);
|
||||
else if (Name == "__pointers")
|
||||
populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
|
||||
Section, SectionID);
|
||||
return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
|
||||
Section, SectionID);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
relocation_iterator
|
||||
Expected<relocation_iterator>
|
||||
processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
ObjSectionToIDMap &ObjSectionToID) {
|
||||
@ -153,8 +168,12 @@ private:
|
||||
uint64_t SectionAOffset = AddrA - SectionABase;
|
||||
SectionRef SectionA = *SAI;
|
||||
bool IsCode = SectionA.isText();
|
||||
uint32_t SectionAID =
|
||||
findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID);
|
||||
uint32_t SectionAID = ~0U;
|
||||
if (auto SectionAIDOrErr =
|
||||
findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID))
|
||||
SectionAID = *SectionAIDOrErr;
|
||||
else
|
||||
return SectionAIDOrErr.takeError();
|
||||
|
||||
uint32_t AddrB = Obj.getScatteredRelocationValue(RE2);
|
||||
section_iterator SBI = getSectionByAddress(Obj, AddrB);
|
||||
@ -162,8 +181,12 @@ private:
|
||||
uint64_t SectionBBase = SBI->getAddress();
|
||||
uint64_t SectionBOffset = AddrB - SectionBBase;
|
||||
SectionRef SectionB = *SBI;
|
||||
uint32_t SectionBID =
|
||||
findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID);
|
||||
uint32_t SectionBID = ~0U;
|
||||
if (auto SectionBIDOrErr =
|
||||
findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID))
|
||||
SectionBID = *SectionBIDOrErr;
|
||||
else
|
||||
return SectionBIDOrErr.takeError();
|
||||
|
||||
// Compute the addend 'C' from the original expression 'A - B + C'.
|
||||
Addend -= AddrA - AddrB;
|
||||
@ -183,11 +206,9 @@ private:
|
||||
}
|
||||
|
||||
// Populate stubs in __jump_table section.
|
||||
void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection,
|
||||
Error populateJumpTable(const MachOObjectFile &Obj,
|
||||
const SectionRef &JTSection,
|
||||
unsigned JTSectionID) {
|
||||
assert(!Obj.is64Bit() &&
|
||||
"__jump_table section not supported in 64-bit MachO.");
|
||||
|
||||
MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
|
||||
MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl());
|
||||
uint32_t JTSectionSize = Sec32.size;
|
||||
@ -197,21 +218,17 @@ private:
|
||||
uint8_t *JTSectionAddr = getSectionAddress(JTSectionID);
|
||||
unsigned JTEntryOffset = 0;
|
||||
|
||||
assert((JTSectionSize % JTEntrySize) == 0 &&
|
||||
"Jump-table section does not contain a whole number of stubs?");
|
||||
if (JTSectionSize % JTEntrySize != 0)
|
||||
return make_error<RuntimeDyldError>("Jump-table section does not contain "
|
||||
"a whole number of stubs?");
|
||||
|
||||
for (unsigned i = 0; i < NumJTEntries; ++i) {
|
||||
unsigned SymbolIndex =
|
||||
Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
|
||||
symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
|
||||
Expected<StringRef> IndirectSymbolName = SI->getName();
|
||||
if (!IndirectSymbolName) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(IndirectSymbolName.takeError(), OS, "");
|
||||
OS.flush();
|
||||
report_fatal_error(Buf);
|
||||
}
|
||||
if (!IndirectSymbolName)
|
||||
return IndirectSymbolName.takeError();
|
||||
uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset;
|
||||
createStubFunction(JTEntryAddr);
|
||||
RelocationEntry RE(JTSectionID, JTEntryOffset + 1,
|
||||
@ -219,6 +236,8 @@ private:
|
||||
addRelocationForSymbol(RE, *IndirectSymbolName);
|
||||
JTEntryOffset += JTEntrySize;
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
|
||||
unsigned getStubAlignment() override { return 1; }
|
||||
|
||||
relocation_iterator
|
||||
Expected<relocation_iterator>
|
||||
processRelocationRef(unsigned SectionID, relocation_iterator RelI,
|
||||
const ObjectFile &BaseObjT,
|
||||
ObjSectionToIDMap &ObjSectionToID,
|
||||
@ -49,13 +49,26 @@ public:
|
||||
|
||||
RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
|
||||
RE.Addend = memcpyAddend(RE);
|
||||
RelocationValueRef Value(
|
||||
getRelocationValueRef(Obj, RelI, RE, ObjSectionToID));
|
||||
RelocationValueRef Value;
|
||||
if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
|
||||
Value = *ValueOrErr;
|
||||
else
|
||||
return ValueOrErr.takeError();
|
||||
|
||||
bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
|
||||
if (!IsExtern && RE.IsPCRel)
|
||||
makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
|
||||
|
||||
switch (RelType) {
|
||||
UNIMPLEMENTED_RELOC(MachO::X86_64_RELOC_TLV);
|
||||
default:
|
||||
if (RelType > MachO::X86_64_RELOC_TLV)
|
||||
return make_error<RuntimeDyldError>("MachO X86_64 relocation type " +
|
||||
std::to_string(RelType) +
|
||||
" is out of range");
|
||||
break;
|
||||
}
|
||||
|
||||
if (RE.RelType == MachO::X86_64_RELOC_GOT ||
|
||||
RE.RelType == MachO::X86_64_RELOC_GOT_LOAD)
|
||||
processGOTRelocation(RE, Value, Stubs);
|
||||
@ -104,15 +117,13 @@ public:
|
||||
writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
|
||||
break;
|
||||
}
|
||||
case MachO::X86_64_RELOC_GOT_LOAD:
|
||||
case MachO::X86_64_RELOC_GOT:
|
||||
case MachO::X86_64_RELOC_TLV:
|
||||
Error("Relocation type not implemented yet!");
|
||||
}
|
||||
}
|
||||
|
||||
void finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
const SectionRef &Section) {}
|
||||
Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
|
||||
const SectionRef &Section) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
void processGOTRelocation(const RelocationEntry &RE,
|
||||
|
Loading…
x
Reference in New Issue
Block a user