1
0
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:
Lang Hames 2016-04-27 20:24:48 +00:00
parent 89a20099cf
commit 82333c4cad
14 changed files with 484 additions and 288 deletions

View File

@ -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;

View File

@ -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,
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,14 +205,20 @@ 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;
@ -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,7 +403,7 @@ 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,
Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
uint64_t &CodeSize,
uint32_t &CodeAlign,
uint64_t &RODataSize,
@ -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,
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,7 +746,8 @@ unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
return SectionID;
}
unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj,
Expected<unsigned>
RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj,
const SectionRef &Section,
bool IsCode,
ObjSectionToIDMap &LocalSections) {
@ -683,7 +757,10 @@ unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj,
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;

View File

@ -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) {

View File

@ -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,7 +781,7 @@ void RuntimeDyldELF::applyMIPS64Relocation(uint8_t *TargetPtr,
}
// Return the .TOC. section and offset.
void RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,
Error RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel) {
// Set a default SectionID in case we do not find a TOC section below.
@ -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,11 +815,13 @@ 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,
Error RuntimeDyldELF::findOPDEntrySection(const ELFObjectFileBase &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel) {
// Get the ELF symbol value (st_value) to compare with Relocation offset in
@ -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);
}
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 {

View File

@ -90,10 +90,10 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
void setMipsABI(const ObjectFile &Obj) override;
void findPPC64TOCSection(const ELFObjectFileBase &Obj,
Error findPPC64TOCSection(const ELFObjectFileBase &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel);
void findOPDEntrySection(const ELFObjectFileBase &Obj,
Error findOPDEntrySection(const ELFObjectFileBase &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel);
@ -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,7 +171,7 @@ public:
bool isCompatibleFile(const object::ObjectFile &Obj) const override;
void registerEHFrames() override;
void deregisterEHFrames() override;
void finalizeLoad(const ObjectFile &Obj,
Error finalizeLoad(const ObjectFile &Obj,
ObjSectionToIDMap &SectionMap) override;
};

View File

@ -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,13 +348,15 @@ 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,
Expected<unsigned> emitSection(const ObjectFile &Obj,
const SectionRef &Section,
bool IsCode);
/// \brief Find Section in LocalSections. If the secton is not found - emit
@ -382,8 +364,9 @@ protected:
/// \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,7 +401,7 @@ protected:
// \brief Compute an upper bound of the memory that is required to load all
// sections
void computeTotalAllocSize(const ObjectFile &Obj,
Error computeTotalAllocSize(const ObjectFile &Obj,
uint64_t &CodeSize, uint32_t &CodeAlign,
uint64_t &RODataSize, uint32_t &RODataAlign,
uint64_t &RWDataSize, uint32_t &RWDataAlign);
@ -428,7 +411,7 @@ protected:
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

View File

@ -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,7 +222,8 @@ bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const {
}
template <typename Impl>
void RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
Error
RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj,
ObjSectionToIDMap &SectionMap) {
unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
unsigned TextSID = 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

View File

@ -80,8 +80,8 @@ protected:
}
/// Process a scattered vanilla relocation.
relocation_iterator processScatteredVANILLA(
unsigned SectionID, relocation_iterator RelI,
Expected<relocation_iterator>
processScatteredVANILLA(unsigned SectionID, relocation_iterator RelI,
const ObjectFile &BaseObjT,
RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID);
@ -94,7 +94,8 @@ 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,
Expected<RelocationValueRef>
getRelocationValueRef(const ObjectFile &BaseTObj,
const relocation_iterator &RI,
const RelocationEntry &RE,
ObjSectionToIDMap &ObjSectionToID);
@ -113,7 +114,7 @@ protected:
// Populate __pointers section.
void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj,
Error populateIndirectSymbolPointersSection(const MachOObjectFile &Obj,
const SectionRef &PTSection,
unsigned PTSectionID);
@ -154,7 +155,7 @@ public:
RuntimeDyld::SymbolResolver &Resolver)
: RuntimeDyldMachO(MemMgr, Resolver) {}
void finalizeLoad(const ObjectFile &Obj,
Error finalizeLoad(const ObjectFile &Obj,
ObjSectionToIDMap &SectionMap) override;
void registerEHFrames() override;
};

View File

@ -34,11 +34,13 @@ public:
unsigned getStubAlignment() override { return 1; }
relocation_iterator processRelocationRef(unsigned SectionID,
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 {}
};
}

View File

@ -106,7 +106,8 @@ public:
}
}
relocation_iterator processRelocationRef(unsigned SectionID,
Expected<relocation_iterator>
processRelocationRef(unsigned SectionID,
relocation_iterator RelI,
const ObjectFile &Obj,
ObjSectionToIDMap &ObjSectionToID,
@ -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,
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();
}
};

View File

@ -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,

View File

@ -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),
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;

View File

@ -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),
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();
}
};

View File

@ -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,