From 528f6d787b1a847e61eb2f1114559f423fdeb68c Mon Sep 17 00:00:00 2001 From: Andrew Kaylor Date: Fri, 11 Oct 2013 21:25:48 +0000 Subject: Adding multiple object support to MCJIT EH frame handling git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192504 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ExecutionEngine/RTDyldMemoryManager.h | 7 +- include/llvm/ExecutionEngine/RuntimeDyld.h | 9 ++- lib/ExecutionEngine/MCJIT/MCJIT.cpp | 17 ++--- lib/ExecutionEngine/MCJIT/MCJIT.h | 4 +- lib/ExecutionEngine/RTDyldMemoryManager.cpp | 11 +++- lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 9 ++- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 30 +++++++-- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 10 ++- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 7 +- .../RuntimeDyld/RuntimeDyldMachO.cpp | 75 ++++++++++++++-------- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h | 19 +++++- test/ExecutionEngine/MCJIT/multi-module-eh-a.ll | 35 ++++++++++ test/ExecutionEngine/MCJIT/multi-module-eh-b.ir | 30 +++++++++ tools/lli/RemoteMemoryManager.cpp | 24 ------- tools/lli/RemoteMemoryManager.h | 11 +++- 15 files changed, 210 insertions(+), 88 deletions(-) create mode 100644 test/ExecutionEngine/MCJIT/multi-module-eh-a.ll create mode 100644 test/ExecutionEngine/MCJIT/multi-module-eh-b.ir diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 09a5cb4884..468b8234c9 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -53,7 +53,12 @@ public: StringRef SectionName, bool IsReadOnly) = 0; /// Register the EH frames with the runtime so that c++ exceptions work. - virtual void registerEHFrames(StringRef SectionData); + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 1a573171a4..a5610fbe3b 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -64,9 +64,14 @@ public: /// This is the address which will be used for relocation resolution. void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); - StringRef getErrorString(); + /// Register any EH frame sections that have been loaded but not previously + /// registered with the memory manager. Note, RuntimeDyld is responsible + /// for identifying the EH frame and calling the memory manager with the + /// EH frame section data. However, the memory manager itself will handle + /// the actual target-specific EH frame registration. + void registerEHFrames(); - StringRef getEHFrameSection(); + StringRef getErrorString(); }; } // end namespace llvm diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 541ba9eb62..fa2c9842d9 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -178,14 +178,12 @@ void MCJIT::finalizeLoadedModules() { if (ModuleStates[M].hasBeenLoaded() && !ModuleStates[M].hasBeenFinalized()) { - // FIXME: This should be module specific! - StringRef EHData = Dyld.getEHFrameSection(); - if (!EHData.empty()) - MemMgr.registerEHFrames(EHData); ModuleStates[M] = ModuleFinalized; } } + Dyld.registerEHFrames(); + // Set page permissions. MemMgr.finalizeMemory(); } @@ -221,14 +219,12 @@ void MCJIT::finalizeObject() { if (ModuleStates[M].hasBeenLoaded() && !ModuleStates[M].hasBeenFinalized()) { - // FIXME: This should be module specific! - StringRef EHData = Dyld.getEHFrameSection(); - if (!EHData.empty()) - MemMgr.registerEHFrames(EHData); ModuleStates[M] = ModuleFinalized; } } + Dyld.registerEHFrames(); + // Set page permissions. MemMgr.finalizeMemory(); } @@ -248,10 +244,7 @@ void MCJIT::finalizeModule(Module *M) { // Resolve any outstanding relocations. Dyld.resolveRelocations(); - // FIXME: Should this be module specific? - StringRef EHData = Dyld.getEHFrameSection(); - if (!EHData.empty()) - MemMgr.registerEHFrames(EHData); + Dyld.registerEHFrames(); // Set page permissions. MemMgr.finalizeMemory(); diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index 6969ff13c0..fe59288aea 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -51,8 +51,8 @@ public: ClientMM->notifyObjectLoaded(EE, Obj); } - virtual void registerEHFrames(StringRef SectionData) { - ClientMM->registerEHFrames(SectionData); + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) { + ClientMM->registerEHFrames(Addr, LoadAddr, Size); } virtual bool finalizeMemory(std::string *ErrMsg = 0) { diff --git a/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/lib/ExecutionEngine/RTDyldMemoryManager.cpp index de38b38d64..99265760be 100644 --- a/lib/ExecutionEngine/RTDyldMemoryManager.cpp +++ b/lib/ExecutionEngine/RTDyldMemoryManager.cpp @@ -54,10 +54,15 @@ static const char *processFDE(const char *Entry) { } #endif -void RTDyldMemoryManager::registerEHFrames(StringRef SectionData) { +// This implementation handles frame registration for local targets. +// Memory managers for remote targets should re-implement this function +// and use the LoadAddr parameter. +void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, + uint64_t LoadAddr, + size_t Size) { #if HAVE_EHTABLE_SUPPORT - const char *P = SectionData.data(); - const char *End = SectionData.data() + SectionData.size(); + const char *P = (const char *)Addr; + const char *End = P + Size; do { P = processFDE(P); } while(P != End); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 077442d8df..1b9e0bf035 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -29,8 +29,7 @@ RuntimeDyldImpl::~RuntimeDyldImpl() {} namespace llvm { -StringRef RuntimeDyldImpl::getEHFrameSection() { - return StringRef(); +void RuntimeDyldImpl::registerEHFrames() { } // Resolve the relocations for all symbols we currently know about. @@ -171,7 +170,7 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { } // Give the subclasses a chance to tie-up any loose ends. - finalizeLoad(); + finalizeLoad(LocalSections); return obj.take(); } @@ -592,8 +591,8 @@ StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); } -StringRef RuntimeDyld::getEHFrameSection() { - return Dyld->getEHFrameSection(); +void RuntimeDyld::registerEHFrames() { + return Dyld->registerEHFrames(); } } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index a438dcd879..97e03f0694 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -151,12 +151,17 @@ void DyldELFObject::updateSymbolAddress(const SymbolRef &SymRef, namespace llvm { -StringRef RuntimeDyldELF::getEHFrameSection() { - for (int i = 0, e = Sections.size(); i != e; ++i) { - if (Sections[i].Name == ".eh_frame") - return StringRef((const char*)Sections[i].Address, Sections[i].Size); +void RuntimeDyldELF::registerEHFrames() { + if (!MemMgr) + return; + for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { + SID EHFrameSID = UnregisteredEHFrameSections[i]; + uint8_t *EHFrameAddr = Sections[EHFrameSID].Address; + uint64_t EHFrameLoadAddr = Sections[EHFrameSID].LoadAddress; + size_t EHFrameSize = Sections[EHFrameSID].Size; + MemMgr->registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize); } - return StringRef(); + UnregisteredEHFrameSections.clear(); } ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) { @@ -1342,7 +1347,8 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, return 0; } -void RuntimeDyldELF::finalizeLoad() { +void RuntimeDyldELF::finalizeLoad(ObjSectionToIDMap &SectionMap) { + // If necessary, allocate the global offset table if (MemMgr) { // Allocate the GOT if necessary size_t numGOTEntries = GOTEntries.size(); @@ -1365,6 +1371,18 @@ void RuntimeDyldELF::finalizeLoad() { else { report_fatal_error("Unable to allocate memory for GOT!"); } + + // Look for and record the EH frame section. + ObjSectionToIDMap::iterator i, e; + for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { + const SectionRef &Section = i->first; + StringRef Name; + Section.getName(Name); + if (Name == ".eh_frame") { + UnregisteredEHFrameSections.push_back(i->second); + break; + } + } } bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 67dc693b1b..ab6b8bdaf3 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -94,11 +94,15 @@ class RuntimeDyldELF : public RuntimeDyldImpl { // Relocation entries for symbols whose position-independant offset is // updated in a global offset table. - typedef unsigned SID; // Type for SectionIDs typedef SmallVector GOTRelocations; GOTRelocations GOTEntries; // List of entries requiring finalization. SmallVector, 8> GOTs; // Allocated tables. + // When a module is loaded we save the SectionID of the EH frame section + // in a table until we receive a request to register all unregistered + // EH frame sections with the memory manager. + SmallVector UnregisteredEHFrameSections; + public: RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} @@ -112,8 +116,8 @@ public: StubMap &Stubs); virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const; virtual ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); - virtual StringRef getEHFrameSection(); - virtual void finalizeLoad(); + virtual void registerEHFrames(); + virtual void finalizeLoad(ObjSectionToIDMap &SectionMap); virtual ~RuntimeDyldELF(); }; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 11f77febd5..5796c7cd39 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -147,6 +147,9 @@ protected: typedef SmallVector SectionList; SectionList Sections; + typedef unsigned SID; // Type for SectionIDs + #define RTDYLD_INVALID_SECTION_ID ((SID)(-1)) + // Keep a map of sections from object file to the SectionID which // references it. typedef std::map ObjSectionToIDMap; @@ -357,9 +360,9 @@ public: virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; - virtual StringRef getEHFrameSection(); + virtual void registerEHFrames(); - virtual void finalizeLoad() {} + virtual void finalizeLoad(ObjSectionToIDMap &SectionMap) {} }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 1bf47d55a7..5b92867b47 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -55,33 +55,58 @@ static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { return ObjDistance - MemDistance; } -StringRef RuntimeDyldMachO::getEHFrameSection() { - SectionEntry *Text = NULL; - SectionEntry *EHFrame = NULL; - SectionEntry *ExceptTab = NULL; - for (int i = 0, e = Sections.size(); i != e; ++i) { - if (Sections[i].Name == "__eh_frame") - EHFrame = &Sections[i]; - else if (Sections[i].Name == "__text") - Text = &Sections[i]; - else if (Sections[i].Name == "__gcc_except_tab") - ExceptTab = &Sections[i]; - } - if (Text == NULL || EHFrame == NULL) - return StringRef(); - - intptr_t DeltaForText = computeDelta(Text, EHFrame); - intptr_t DeltaForEH = 0; - if (ExceptTab) - DeltaForEH = computeDelta(ExceptTab, EHFrame); +void RuntimeDyldMachO::registerEHFrames() { - unsigned char *P = EHFrame->Address; - unsigned char *End = P + EHFrame->Size; - do { - P = processFDE(P, DeltaForText, DeltaForEH); - } while(P != End); + if (!MemMgr) + return; + for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { + EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; + if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || + SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) + continue; + SectionEntry *Text = &Sections[SectionInfo.TextSID]; + SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; + SectionEntry *ExceptTab = NULL; + if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) + ExceptTab = &Sections[SectionInfo.ExceptTabSID]; + + intptr_t DeltaForText = computeDelta(Text, EHFrame); + intptr_t DeltaForEH = 0; + if (ExceptTab) + DeltaForEH = computeDelta(ExceptTab, EHFrame); + + unsigned char *P = EHFrame->Address; + unsigned char *End = P + EHFrame->Size; + do { + P = processFDE(P, DeltaForText, DeltaForEH); + } while(P != End); + + MemMgr->registerEHFrames(EHFrame->Address, + EHFrame->LoadAddress, + EHFrame->Size); + } + UnregisteredEHFrameSections.clear(); +} - return StringRef((char*)EHFrame->Address, EHFrame->Size); +void RuntimeDyldMachO::finalizeLoad(ObjSectionToIDMap &SectionMap) { + unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; + unsigned TextSID = RTDYLD_INVALID_SECTION_ID; + unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; + ObjSectionToIDMap::iterator i, e; + for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { + const SectionRef &Section = i->first; + StringRef Name; + Section.getName(Name); + if (Name == "__eh_frame") + EHFrameSID = i->second; + else if (Name == "__text") + TextSID = i->second; + else if (Name == "__gcc_except_tab") + ExceptTabSID = i->second; + } + UnregisteredEHFrameSections.push_back(EHFrameRelatedSections(EHFrameSID, + TextSID, + ExceptTabSID)); } // The target location for the relocation is described by RE.SectionID and diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index df8d3bb482..3906c9d56d 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -54,6 +54,22 @@ class RuntimeDyldMachO : public RuntimeDyldImpl { int64_t Addend, bool isPCRel, unsigned Size); + + struct EHFrameRelatedSections { + EHFrameRelatedSections() : EHFrameSID(RTDYLD_INVALID_SECTION_ID), + TextSID(RTDYLD_INVALID_SECTION_ID), + ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {} + EHFrameRelatedSections(SID EH, SID T, SID Ex) + : EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {} + SID EHFrameSID; + SID TextSID; + SID ExceptTabSID; + }; + + // When a module is loaded we save the SectionID of the EH frame section + // in a table until we receive a request to register all unregistered + // EH frame sections with the memory manager. + SmallVector UnregisteredEHFrameSections; public: RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} @@ -65,7 +81,8 @@ public: const SymbolTableMap &Symbols, StubMap &Stubs); virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const; - virtual StringRef getEHFrameSection(); + virtual void registerEHFrames(); + virtual void finalizeLoad(ObjSectionToIDMap &SectionMap); }; } // end namespace llvm diff --git a/test/ExecutionEngine/MCJIT/multi-module-eh-a.ll b/test/ExecutionEngine/MCJIT/multi-module-eh-a.ll new file mode 100644 index 0000000000..89035e65ac --- /dev/null +++ b/test/ExecutionEngine/MCJIT/multi-module-eh-a.ll @@ -0,0 +1,35 @@ +; RUN: %lli_mcjit -extra-modules=%p/multi-module-eh-b.ir %s +; XFAIL: arm, cygwin, win32, mingw +declare i8* @__cxa_allocate_exception(i64) +declare void @__cxa_throw(i8*, i8*, i8*) +declare i32 @__gxx_personality_v0(...) +declare void @__cxa_end_catch() +declare i8* @__cxa_begin_catch(i8*) + +@_ZTIi = external constant i8* + +declare i32 @FB() + +define void @throwException() { + %exception = tail call i8* @__cxa_allocate_exception(i64 4) + call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) + unreachable +} + +define i32 @main() { +entry: + invoke void @throwException() + to label %try.cont unwind label %lpad + +lpad: + %p = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* bitcast (i8** @_ZTIi to i8*) + %e = extractvalue { i8*, i32 } %p, 0 + call i8* @__cxa_begin_catch(i8* %e) + call void @__cxa_end_catch() + br label %try.cont + +try.cont: + %r = call i32 @FB( ) + ret i32 %r +} diff --git a/test/ExecutionEngine/MCJIT/multi-module-eh-b.ir b/test/ExecutionEngine/MCJIT/multi-module-eh-b.ir new file mode 100644 index 0000000000..d7dbb032b5 --- /dev/null +++ b/test/ExecutionEngine/MCJIT/multi-module-eh-b.ir @@ -0,0 +1,30 @@ +declare i8* @__cxa_allocate_exception(i64) +declare void @__cxa_throw(i8*, i8*, i8*) +declare i32 @__gxx_personality_v0(...) +declare void @__cxa_end_catch() +declare i8* @__cxa_begin_catch(i8*) + +@_ZTIi = external constant i8* + +define void @throwException_B() { + %exception = tail call i8* @__cxa_allocate_exception(i64 4) + call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) + unreachable +} + +define i32 @FB() { +entry: + invoke void @throwException_B() + to label %try.cont unwind label %lpad + +lpad: + %p = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* bitcast (i8** @_ZTIi to i8*) + %e = extractvalue { i8*, i32 } %p, 0 + call i8* @__cxa_begin_catch(i8* %e) + call void @__cxa_end_catch() + br label %try.cont + +try.cont: + ret i32 0 +} diff --git a/tools/lli/RemoteMemoryManager.cpp b/tools/lli/RemoteMemoryManager.cpp index 8ccfde8fc7..04fc40e426 100644 --- a/tools/lli/RemoteMemoryManager.cpp +++ b/tools/lli/RemoteMemoryManager.cpp @@ -204,27 +204,3 @@ uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) void RemoteMemoryManager::deallocateFunctionBody(void *Body) { llvm_unreachable("Unexpected!"); } - -static int jit_noop() { - return 0; -} - -void *RemoteMemoryManager::getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure) { - // We should not invoke parent's ctors/dtors from generated main()! - // On Mingw and Cygwin, the symbol __main is resolved to - // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors - // (and register wrong callee's dtors with atexit(3)). - // We expect ExecutionEngine::runStaticConstructorsDestructors() - // is called before ExecutionEngine::runFunctionAsMain() is called. - if (Name == "__main") return (void*)(intptr_t)&jit_noop; - - // FIXME: Would it be responsible to provide GOT? - if (AbortOnFailure) { - if (Name == "_GLOBAL_OFFSET_TABLE_") - report_fatal_error("Program used external function '" + Name + - "' which could not be resolved!"); - } - - return NULL; -} diff --git a/tools/lli/RemoteMemoryManager.h b/tools/lli/RemoteMemoryManager.h index ca157a7929..eabe042fff 100644 --- a/tools/lli/RemoteMemoryManager.h +++ b/tools/lli/RemoteMemoryManager.h @@ -74,13 +74,20 @@ public: unsigned SectionID, StringRef SectionName, bool IsReadOnly); - void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); + // For now, remote symbol resolution is not support in lli. The MCJIT + // interface does support this, but clients must provide their own + // mechanism for finding remote symbol addresses. MCJIT will resolve + // symbols from Modules it contains. + uint64_t getSymbolAddress(const std::string &Name) {} void notifyObjectLoaded(ExecutionEngine *EE, const ObjectImage *Obj); bool finalizeMemory(std::string *ErrMsg); + // For now, remote EH frame registration isn't supported. Remote symbol + // resolution is a prerequisite to supporting remote EH frame registration. + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {} + // This is a non-interface function used by lli void setRemoteTarget(RemoteTarget *T) { Target = T; } -- cgit v1.2.3