From 8959531c51af99600296b3db6c94af567ec22aca Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Wed, 27 Apr 2016 20:24:48 +0000 Subject: [PATCH] [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 --- llvm/include/llvm/ExecutionEngine/RuntimeDyld.h | 13 ++ .../ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 209 ++++++++++++++------- .../RuntimeDyld/RuntimeDyldCOFF.cpp | 9 +- .../ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 101 ++++++---- .../ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 18 +- .../ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 59 +++--- .../RuntimeDyld/RuntimeDyldMachO.cpp | 96 ++++++---- .../ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h | 27 +-- .../RuntimeDyld/Targets/RuntimeDyldCOFFI386.h | 22 ++- .../RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h | 27 ++- .../RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h | 19 +- .../RuntimeDyld/Targets/RuntimeDyldMachOARM.h | 64 ++++--- .../RuntimeDyld/Targets/RuntimeDyldMachOI386.h | 79 +++++--- .../RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h | 29 ++- 14 files changed, 484 insertions(+), 288 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h b/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h index 44102d0..ad2e202 100644 --- a/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -31,6 +31,19 @@ namespace object { template class OwningBinary; } +/// Base class for errors originating in RuntimeDyld, e.g. missing relocation +/// support. +class RuntimeDyldError : public ErrorInfo { +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; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index edb2fbe..5ac2db9 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -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(Condition)) { + case GenericRTDyldError: return "Generic RuntimeDyld error"; + } + llvm_unreachable("Unrecognized RuntimeDyldErrorCode"); + } +}; + +static ManagedStatic 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 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::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 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 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 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 CodeSectionSizes; std::vector 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 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 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); -} -unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, - const SectionRef &Section, bool IsCode) { + return Error::success(); +} +Expected +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 +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; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp index e5fab92..f345b47 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp @@ -57,7 +57,14 @@ llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch, std::unique_ptr RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) { - return llvm::make_unique(*this, loadObjectImpl(O)); + if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) + return llvm::make_unique(*this, *ObjSectionToIDOrErr); + else { + HasError = true; + raw_string_ostream ErrStream(ErrorStr); + logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, ""); + return nullptr; + } } uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) { diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index c2b843e..1b59ffa 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -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 DyldELFObject : public ELFObjectFile { @@ -220,7 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() { std::unique_ptr RuntimeDyldELF::loadObject(const object::ObjectFile &O) { - return llvm::make_unique(*this, loadObjectImpl(O)); + if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) + return llvm::make_unique(*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 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 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 +RuntimeDyldELF::processRelocationRef( unsigned SectionID, relocation_iterator RelI, const ObjectFile &O, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { const auto &Obj = cast(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 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("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("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 { diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 041811d..cca80af 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -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 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 diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 18560c8..76bd3fc 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -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("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 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 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 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 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 diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 68c85d6..fd109ae 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -50,7 +50,8 @@ int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { return static_cast(readBytesUnaligned(Src, NumBytes)); } -relocation_iterator RuntimeDyldMachO::processScatteredVANILLA( +Expected +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 +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 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 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 -void RuntimeDyldMachOCRTPBase::finalizeLoad(const ObjectFile &Obj, - ObjSectionToIDMap &SectionMap) { +Error +RuntimeDyldMachOCRTPBase::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::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 @@ -343,7 +361,15 @@ RuntimeDyldMachO::create(Triple::ArchType Arch, std::unique_ptr RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { - return llvm::make_unique(*this, loadObjectImpl(O)); + if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) + return llvm::make_unique(*this, + *ObjSectionToIDOrErr); + else { + HasError = true; + raw_string_ostream ErrStream(ErrorStr); + logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream, ""); + return nullptr; + } } } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index c8ae47b..30f3bb3 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -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 + 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 + 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; }; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h index 9573d3f..3456b33 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h @@ -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 + 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 {} }; } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h index 1fd8515..7dd112e5 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h @@ -106,11 +106,12 @@ public: } } - relocation_iterator processRelocationRef(unsigned SectionID, - relocation_iterator RelI, - const ObjectFile &Obj, - ObjSectionToIDMap &ObjSectionToID, - StubMap &Stubs) override { + Expected + 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(); } }; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index fba157b9..7d1a62f 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -242,7 +242,7 @@ public: } } - relocation_iterator + Expected 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("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, diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 7731df0..b3f4ce4 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -49,7 +49,7 @@ public: } } - relocation_iterator + Expected 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("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(Obj), - Section, SectionID); + return populateIndirectSymbolPointersSection(cast(Obj), + Section, SectionID); + return Error::success(); } private: @@ -201,7 +213,7 @@ private: resolveRelocation(TargetRE, (uint64_t)Addr); } - relocation_iterator + Expected 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; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 843aa36..129acf7 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -30,7 +30,7 @@ public: unsigned getStubAlignment() override { return 1; } - relocation_iterator + Expected 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("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("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(Obj), Section, SectionID); + return populateJumpTable(cast(Obj), Section, SectionID); else if (Name == "__pointers") - populateIndirectSymbolPointersSection(cast(Obj), - Section, SectionID); + return populateIndirectSymbolPointersSection(cast(Obj), + Section, SectionID); + return Error::success(); } private: - relocation_iterator + Expected 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("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 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(); } }; diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 8f566b7..a46658d 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -30,7 +30,7 @@ public: unsigned getStubAlignment() override { return 1; } - relocation_iterator + Expected 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("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, -- 2.7.4