869 lines · cpp
1//===- elfnix_platform.cpp ------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains code required to load the rest of the ELF-on-*IX runtime.10//11//===----------------------------------------------------------------------===//12 13#include "elfnix_platform.h"14#include "common.h"15#include "compiler.h"16#include "error.h"17#include "jit_dispatch.h"18#include "record_section_tracker.h"19#include "wrapper_function_utils.h"20 21#include <algorithm>22#include <map>23#include <mutex>24#include <sstream>25#include <string_view>26#include <unordered_map>27#include <vector>28 29using namespace orc_rt;30using namespace orc_rt::elfnix;31 32// Declare function tags for functions in the JIT process.33ORC_RT_JIT_DISPATCH_TAG(__orc_rt_reoptimize_tag)34ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_push_initializers_tag)35ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_symbol_lookup_tag)36 37// eh-frame registration functions, made available via aliases38// installed by the Platform39extern "C" void __register_frame(const void *);40extern "C" void __deregister_frame(const void *);41 42extern "C" void43__unw_add_dynamic_eh_frame_section(const void *) ORC_RT_WEAK_IMPORT;44extern "C" void45__unw_remove_dynamic_eh_frame_section(const void *) ORC_RT_WEAK_IMPORT;46 47namespace {48 49struct TLSInfoEntry {50 unsigned long Key = 0;51 unsigned long DataAddress = 0;52};53 54struct TLSDescriptor {55 void (*Resolver)(void *);56 TLSInfoEntry *InfoEntry;57};58 59class ELFNixPlatformRuntimeState {60private:61 struct AtExitEntry {62 void (*Func)(void *);63 void *Arg;64 };65 66 using AtExitsVector = std::vector<AtExitEntry>;67 68 struct PerJITDylibState {69 std::string Name;70 void *Header = nullptr;71 size_t RefCount = 0;72 size_t LinkedAgainstRefCount = 0;73 bool AllowReinitialization = false;74 AtExitsVector AtExits;75 std::vector<PerJITDylibState *> Deps;76 RecordSectionsTracker<void (*)()> RecordedInits;77 78 bool referenced() const {79 return LinkedAgainstRefCount != 0 || RefCount != 0;80 }81 };82 83public:84 static void initialize(void *DSOHandle);85 static ELFNixPlatformRuntimeState &get();86 static void destroy();87 88 ELFNixPlatformRuntimeState(void *DSOHandle);89 90 // Delete copy and move constructors.91 ELFNixPlatformRuntimeState(const ELFNixPlatformRuntimeState &) = delete;92 ELFNixPlatformRuntimeState &93 operator=(const ELFNixPlatformRuntimeState &) = delete;94 ELFNixPlatformRuntimeState(ELFNixPlatformRuntimeState &&) = delete;95 ELFNixPlatformRuntimeState &operator=(ELFNixPlatformRuntimeState &&) = delete;96 97 Error registerObjectSections(ELFNixPerObjectSectionsToRegister POSR);98 Error registerJITDylib(std::string &Name, void *Handle);99 Error deregisterJITDylib(void *Handle);100 Error registerInits(ExecutorAddr HeaderAddr,101 std::vector<ExecutorAddrRange> Inits);102 Error deregisterInits(ExecutorAddr HeaderAddr,103 std::vector<ExecutorAddrRange> Inits);104 Error deregisterObjectSections(ELFNixPerObjectSectionsToRegister POSR);105 106 const char *dlerror();107 void *dlopen(std::string_view Name, int Mode);108 int dlupdate(void *DSOHandle);109 int dlclose(void *DSOHandle);110 void *dlsym(void *DSOHandle, std::string_view Symbol);111 112 int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle);113 void runAtExits(void *DSOHandle);114 void runAtExits(std::unique_lock<std::recursive_mutex> &JDStateLock,115 PerJITDylibState &JDS);116 117 /// Returns the base address of the section containing ThreadData.118 Expected<std::pair<const char *, size_t>>119 getThreadDataSectionFor(const char *ThreadData);120 121 void *getPlatformJDDSOHandle() { return PlatformJDDSOHandle; }122 123private:124 PerJITDylibState *getJITDylibStateByHeaderAddr(void *DSOHandle);125 PerJITDylibState *getJITDylibStateByName(std::string_view Path);126 127 Error registerThreadDataSection(span<const char> ThreadDataSection);128 129 Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,130 std::string_view Symbol);131 132 Error runInits(std::unique_lock<std::recursive_mutex> &JDStatesLock,133 PerJITDylibState &JDS);134 Expected<void *> dlopenImpl(std::string_view Path, int Mode);135 Error dlopenFull(std::unique_lock<std::recursive_mutex> &JDStatesLock,136 PerJITDylibState &JDS);137 Error dlopenInitialize(std::unique_lock<std::recursive_mutex> &JDStatesLock,138 PerJITDylibState &JDS,139 ELFNixJITDylibDepInfoMap &DepInfo);140 Error dlupdateImpl(void *DSOHandle);141 Error dlupdateFull(std::unique_lock<std::recursive_mutex> &JDStatesLock,142 PerJITDylibState &JDS);143 144 Error dlcloseImpl(void *DSOHandle);145 Error dlcloseInitialize(std::unique_lock<std::recursive_mutex> &JDStatesLock,146 PerJITDylibState &JDS);147 148 static ELFNixPlatformRuntimeState *MOPS;149 150 void *PlatformJDDSOHandle;151 152 // Frame registration functions:153 void (*registerEHFrameSection)(const void *) = nullptr;154 void (*deregisterEHFrameSection)(const void *) = nullptr;155 156 // FIXME: Move to thread-state.157 std::string DLFcnError;158 159 std::recursive_mutex JDStatesMutex;160 std::unordered_map<void *, PerJITDylibState> JDStates;161 std::unordered_map<std::string, void *> JDNameToHeader;162 163 std::mutex ThreadDataSectionsMutex;164 std::map<const char *, size_t> ThreadDataSections;165};166 167ELFNixPlatformRuntimeState *ELFNixPlatformRuntimeState::MOPS = nullptr;168 169void ELFNixPlatformRuntimeState::initialize(void *DSOHandle) {170 assert(!MOPS && "ELFNixPlatformRuntimeState should be null");171 MOPS = new ELFNixPlatformRuntimeState(DSOHandle);172}173 174ELFNixPlatformRuntimeState &ELFNixPlatformRuntimeState::get() {175 assert(MOPS && "ELFNixPlatformRuntimeState not initialized");176 return *MOPS;177}178 179void ELFNixPlatformRuntimeState::destroy() {180 assert(MOPS && "ELFNixPlatformRuntimeState not initialized");181 delete MOPS;182}183 184ELFNixPlatformRuntimeState::ELFNixPlatformRuntimeState(void *DSOHandle)185 : PlatformJDDSOHandle(DSOHandle) {186 if (__unw_add_dynamic_eh_frame_section &&187 __unw_remove_dynamic_eh_frame_section) {188 registerEHFrameSection = __unw_add_dynamic_eh_frame_section;189 deregisterEHFrameSection = __unw_remove_dynamic_eh_frame_section;190 } else {191 registerEHFrameSection = __register_frame;192 deregisterEHFrameSection = __deregister_frame;193 }194}195 196Error ELFNixPlatformRuntimeState::registerObjectSections(197 ELFNixPerObjectSectionsToRegister POSR) {198 if (POSR.EHFrameSection.Start)199 registerEHFrameSection(POSR.EHFrameSection.Start.toPtr<const char *>());200 201 if (POSR.ThreadDataSection.Start) {202 if (auto Err = registerThreadDataSection(203 POSR.ThreadDataSection.toSpan<const char>()))204 return Err;205 }206 207 return Error::success();208}209 210Error ELFNixPlatformRuntimeState::deregisterObjectSections(211 ELFNixPerObjectSectionsToRegister POSR) {212 if (POSR.EHFrameSection.Start)213 deregisterEHFrameSection(POSR.EHFrameSection.Start.toPtr<const char *>());214 215 return Error::success();216}217 218Error ELFNixPlatformRuntimeState::registerJITDylib(std::string &Name,219 void *Handle) {220 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);221 222 if (JDStates.count(Handle)) {223 std::ostringstream ErrStream;224 ErrStream << "Duplicate JITDylib registration for header " << Handle225 << " (name = " << Name << ")";226 return make_error<StringError>(ErrStream.str());227 }228 229 if (JDNameToHeader.count(Name)) {230 std::ostringstream ErrStream;231 ErrStream << "Duplicate JITDylib registration for header " << Handle232 << " (header = " << Handle << ")";233 return make_error<StringError>(ErrStream.str());234 }235 236 auto &JD = JDStates[Handle];237 JD.Header = Handle;238 JD.Name = std::move(Name);239 JDNameToHeader[JD.Name] = Handle;240 return Error::success();241}242 243Error ELFNixPlatformRuntimeState::deregisterJITDylib(void *Handle) {244 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);245 246 auto I = JDStates.find(Handle);247 if (I == JDStates.end()) {248 std::ostringstream ErrStream;249 ErrStream << "Attempted to deregister unrecognized header " << Handle;250 return make_error<StringError>(ErrStream.str());251 }252 253 auto J = JDNameToHeader.find(254 std::string(I->second.Name.data(), I->second.Name.size()));255 assert(J != JDNameToHeader.end() &&256 "Missing JDNameToHeader entry for JITDylib");257 JDNameToHeader.erase(J);258 JDStates.erase(I);259 return Error::success();260}261 262Error ELFNixPlatformRuntimeState::registerInits(263 ExecutorAddr HeaderAddr, std::vector<ExecutorAddrRange> Inits) {264 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);265 PerJITDylibState *JDS =266 getJITDylibStateByHeaderAddr(HeaderAddr.toPtr<void *>());267 268 if (!JDS) {269 std::ostringstream ErrStream;270 ErrStream << "Could not register object platform sections for "271 "unrecognized header "272 << HeaderAddr.toPtr<void *>();273 return make_error<StringError>(ErrStream.str());274 }275 276 for (auto &I : Inits) {277 JDS->RecordedInits.add(I.toSpan<void (*)()>());278 }279 280 return Error::success();281}282 283Error ELFNixPlatformRuntimeState::deregisterInits(284 ExecutorAddr HeaderAddr, std::vector<ExecutorAddrRange> Inits) {285 286 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);287 PerJITDylibState *JDS =288 getJITDylibStateByHeaderAddr(HeaderAddr.toPtr<void *>());289 290 if (!JDS) {291 std::ostringstream ErrStream;292 ErrStream << "Could not register object platform sections for unrecognized "293 "header "294 << HeaderAddr.toPtr<void *>();295 return make_error<StringError>(ErrStream.str());296 }297 298 for (auto &I : Inits) {299 JDS->RecordedInits.removeIfPresent(I);300 }301 302 return Error::success();303}304 305const char *ELFNixPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }306 307void *ELFNixPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {308 if (auto H = dlopenImpl(Path, Mode))309 return *H;310 else {311 // FIXME: Make dlerror thread safe.312 DLFcnError = toString(H.takeError());313 return nullptr;314 }315}316 317int ELFNixPlatformRuntimeState::dlupdate(void *DSOHandle) {318 if (auto Err = dlupdateImpl(DSOHandle)) {319 // FIXME: Make dlerror thread safe.320 DLFcnError = toString(std::move(Err));321 return -1;322 }323 return 0;324}325 326int ELFNixPlatformRuntimeState::dlclose(void *DSOHandle) {327 if (auto Err = dlcloseImpl(DSOHandle)) {328 DLFcnError = toString(std::move(Err));329 return -1;330 }331 return 0;332}333 334void *ELFNixPlatformRuntimeState::dlsym(void *DSOHandle,335 std::string_view Symbol) {336 auto Addr = lookupSymbolInJITDylib(DSOHandle, Symbol);337 if (!Addr) {338 DLFcnError = toString(Addr.takeError());339 return 0;340 }341 342 return Addr->toPtr<void *>();343}344 345int ELFNixPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg,346 void *DSOHandle) {347 // FIXME: Handle out-of-memory errors, returning -1 if OOM.348 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);349 auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);350 assert(JDS && "JITDylib state not initialized");351 JDS->AtExits.push_back({F, Arg});352 return 0;353}354 355void ELFNixPlatformRuntimeState::runAtExits(void *DSOHandle) {356 std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);357 PerJITDylibState *JDS = getJITDylibStateByHeaderAddr(DSOHandle);358 359 if (JDS)360 runAtExits(Lock, *JDS);361}362 363void ELFNixPlatformRuntimeState::runAtExits(364 std::unique_lock<std::recursive_mutex> &JDStateLock,365 PerJITDylibState &JDS) {366 AtExitsVector V = std::move(JDS.AtExits);367 368 while (!V.empty()) {369 auto &AE = V.back();370 AE.Func(AE.Arg);371 V.pop_back();372 }373}374 375Expected<std::pair<const char *, size_t>>376ELFNixPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {377 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);378 auto I = ThreadDataSections.upper_bound(ThreadData);379 // Check that we have a valid entry conovering this address.380 if (I == ThreadDataSections.begin())381 return make_error<StringError>("No thread local data section for key");382 I = std::prev(I);383 if (ThreadData >= I->first + I->second)384 return make_error<StringError>("No thread local data section for key");385 return *I;386}387 388ELFNixPlatformRuntimeState::PerJITDylibState *389ELFNixPlatformRuntimeState::getJITDylibStateByHeaderAddr(void *DSOHandle) {390 auto I = JDStates.find(DSOHandle);391 if (I == JDStates.end())392 return nullptr;393 394 return &I->second;395}396 397ELFNixPlatformRuntimeState::PerJITDylibState *398ELFNixPlatformRuntimeState::getJITDylibStateByName(std::string_view Name) {399 // FIXME: Avoid creating string copy here.400 auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));401 if (I == JDNameToHeader.end())402 return nullptr;403 void *H = I->second;404 auto J = JDStates.find(H);405 assert(J != JDStates.end() &&406 "JITDylib has name map entry but no header map entry");407 return &J->second;408}409 410Error ELFNixPlatformRuntimeState::registerThreadDataSection(411 span<const char> ThreadDataSection) {412 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);413 auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());414 if (I != ThreadDataSections.begin()) {415 auto J = std::prev(I);416 if (J->first + J->second > ThreadDataSection.data())417 return make_error<StringError>("Overlapping .tdata sections");418 }419 ThreadDataSections.insert(420 I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));421 return Error::success();422}423 424Expected<ExecutorAddr>425ELFNixPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,426 std::string_view Sym) {427 Expected<ExecutorAddr> Result((ExecutorAddr()));428 if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddr>(429 SPSExecutorAddr,430 SPSString)>::call(JITDispatch(&__orc_rt_elfnix_symbol_lookup_tag),431 Result, ExecutorAddr::fromPtr(DSOHandle), Sym))432 return std::move(Err);433 return Result;434}435 436Error ELFNixPlatformRuntimeState::runInits(437 std::unique_lock<std::recursive_mutex> &JDStatesLock,438 PerJITDylibState &JDS) {439 std::vector<span<void (*)()>> InitSections;440 InitSections.reserve(JDS.RecordedInits.numNewSections());441 442 JDS.RecordedInits.processNewSections(443 [&](span<void (*)()> Inits) { InitSections.push_back(Inits); });444 445 JDStatesLock.unlock();446 for (auto Sec : InitSections)447 for (auto *Init : Sec)448 Init();449 450 JDStatesLock.lock();451 452 return Error::success();453}454 455Expected<void *> ELFNixPlatformRuntimeState::dlopenImpl(std::string_view Path,456 int Mode) {457 std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);458 PerJITDylibState *JDS = getJITDylibStateByName(Path);459 460 if (!JDS)461 return make_error<StringError>("No registered JTIDylib for path " +462 std::string(Path.data(), Path.size()));463 464 if (auto Err = dlopenFull(Lock, *JDS))465 return std::move(Err);466 467 ++JDS->RefCount;468 469 return JDS->Header;470}471 472Error ELFNixPlatformRuntimeState::dlopenFull(473 std::unique_lock<std::recursive_mutex> &JDStateLock,474 PerJITDylibState &JDS) {475 Expected<ELFNixJITDylibDepInfoMap> DepInfo((ELFNixJITDylibDepInfoMap()));476 JDStateLock.unlock();477 if (auto Err = WrapperFunction<SPSExpected<SPSELFNixJITDylibDepInfoMap>(478 SPSExecutorAddr)>::479 call(JITDispatch(&__orc_rt_elfnix_push_initializers_tag), DepInfo,480 ExecutorAddr::fromPtr(JDS.Header)))481 return Err;482 JDStateLock.lock();483 484 if (!DepInfo)485 return DepInfo.takeError();486 487 if (auto Err = dlopenInitialize(JDStateLock, JDS, *DepInfo))488 return Err;489 490 if (!DepInfo->empty()) {491 std::ostringstream ErrStream;492 ErrStream << "Encountered unrecognized dep-info key headers "493 "while processing dlopen of "494 << JDS.Name;495 return make_error<StringError>(ErrStream.str());496 }497 498 return Error::success();499}500 501Error ELFNixPlatformRuntimeState::dlopenInitialize(502 std::unique_lock<std::recursive_mutex> &JDStatesLock, PerJITDylibState &JDS,503 ELFNixJITDylibDepInfoMap &DepInfo) {504 505 auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header));506 if (I == DepInfo.end())507 return Error::success();508 509 auto Deps = std::move(I->second);510 DepInfo.erase(I);511 512 std::vector<PerJITDylibState *> OldDeps;513 std::swap(JDS.Deps, OldDeps);514 JDS.Deps.reserve(Deps.size());515 for (auto H : Deps) {516 PerJITDylibState *DepJDS = getJITDylibStateByHeaderAddr(H.toPtr<void *>());517 if (!DepJDS) {518 std::ostringstream ErrStream;519 ErrStream << "Encountered unrecognized dep header " << H.toPtr<void *>()520 << " while initializing " << JDS.Name;521 return make_error<StringError>(ErrStream.str());522 }523 ++DepJDS->LinkedAgainstRefCount;524 if (auto Err = dlopenInitialize(JDStatesLock, *DepJDS, DepInfo))525 return Err;526 }527 528 if (auto Err = runInits(JDStatesLock, JDS))529 return Err;530 531 for (auto *DepJDS : OldDeps) {532 --DepJDS->LinkedAgainstRefCount;533 if (!DepJDS->referenced())534 if (auto Err = dlcloseInitialize(JDStatesLock, *DepJDS))535 return Err;536 }537 return Error::success();538}539 540Error ELFNixPlatformRuntimeState::dlupdateImpl(void *DSOHandle) {541 std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);542 543 // Try to find JITDylib state by name.544 auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);545 546 if (!JDS) {547 std::ostringstream ErrStream;548 ErrStream << "No registered JITDylib for " << DSOHandle;549 return make_error<StringError>(ErrStream.str());550 }551 552 if (!JDS->referenced())553 return make_error<StringError>("dlupdate failed, JITDylib must be open.");554 555 if (auto Err = dlupdateFull(Lock, *JDS))556 return Err;557 558 return Error::success();559}560 561Error ELFNixPlatformRuntimeState::dlupdateFull(562 std::unique_lock<std::recursive_mutex> &JDStatesLock,563 PerJITDylibState &JDS) {564 // Call back to the JIT to push the initializers.565 Expected<ELFNixJITDylibDepInfoMap> DepInfo((ELFNixJITDylibDepInfoMap()));566 // Unlock so that we can accept the initializer update.567 JDStatesLock.unlock();568 if (auto Err = WrapperFunction<SPSExpected<SPSELFNixJITDylibDepInfoMap>(569 SPSExecutorAddr)>::570 call(JITDispatch(&__orc_rt_elfnix_push_initializers_tag), DepInfo,571 ExecutorAddr::fromPtr(JDS.Header)))572 return Err;573 JDStatesLock.lock();574 575 if (!DepInfo)576 return DepInfo.takeError();577 578 if (auto Err = runInits(JDStatesLock, JDS))579 return Err;580 581 return Error::success();582}583 584Error ELFNixPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {585 586 std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);587 PerJITDylibState *JDS = getJITDylibStateByHeaderAddr(DSOHandle);588 589 if (!JDS) {590 std::ostringstream ErrStream;591 ErrStream << "No registered JITDylib for " << DSOHandle;592 return make_error<StringError>(ErrStream.str());593 }594 595 --JDS->RefCount;596 597 if (!JDS->referenced())598 return dlcloseInitialize(Lock, *JDS);599 600 return Error::success();601}602 603Error ELFNixPlatformRuntimeState::dlcloseInitialize(604 std::unique_lock<std::recursive_mutex> &JDStatesLock,605 PerJITDylibState &JDS) {606 runAtExits(JDStatesLock, JDS);607 JDS.RecordedInits.reset();608 for (auto *DepJDS : JDS.Deps)609 if (!JDS.referenced())610 if (auto Err = dlcloseInitialize(JDStatesLock, *DepJDS))611 return Err;612 613 return Error::success();614}615 616class ELFNixPlatformRuntimeTLVManager {617public:618 void *getInstance(const char *ThreadData);619 620private:621 std::unordered_map<const char *, char *> Instances;622 std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;623};624 625void *ELFNixPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {626 auto I = Instances.find(ThreadData);627 if (I != Instances.end())628 return I->second;629 auto TDS =630 ELFNixPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);631 if (!TDS) {632 __orc_rt_log_error(toString(TDS.takeError()).c_str());633 return nullptr;634 }635 636 auto &Allocated = AllocatedSections[TDS->first];637 if (!Allocated) {638 Allocated = std::make_unique<char[]>(TDS->second);639 memcpy(Allocated.get(), TDS->first, TDS->second);640 }641 size_t ThreadDataDelta = ThreadData - TDS->first;642 assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");643 644 char *Instance = Allocated.get() + ThreadDataDelta;645 Instances[ThreadData] = Instance;646 return Instance;647}648 649void destroyELFNixTLVMgr(void *ELFNixTLVMgr) {650 delete static_cast<ELFNixPlatformRuntimeTLVManager *>(ELFNixTLVMgr);651}652 653} // end anonymous namespace654 655//------------------------------------------------------------------------------656// JIT entry points657//------------------------------------------------------------------------------658 659ORC_RT_INTERFACE orc_rt_WrapperFunctionResult660__orc_rt_elfnix_platform_bootstrap(char *ArgData, size_t ArgSize) {661 return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(662 ArgData, ArgSize,663 [](ExecutorAddr DSOHandle) {664 ELFNixPlatformRuntimeState::initialize(665 DSOHandle.toPtr<void *>());666 return Error::success();667 })668 .release();669}670 671ORC_RT_INTERFACE orc_rt_WrapperFunctionResult672__orc_rt_elfnix_platform_shutdown(char *ArgData, size_t ArgSize) {673 return WrapperFunction<SPSError()>::handle(674 ArgData, ArgSize,675 []() {676 ELFNixPlatformRuntimeState::destroy();677 return Error::success();678 })679 .release();680}681 682ORC_RT_INTERFACE orc_rt_WrapperFunctionResult683__orc_rt_elfnix_register_jitdylib(char *ArgData, size_t ArgSize) {684 return WrapperFunction<SPSError(SPSString, SPSExecutorAddr)>::handle(685 ArgData, ArgSize,686 [](std::string &JDName, ExecutorAddr HeaderAddr) {687 return ELFNixPlatformRuntimeState::get().registerJITDylib(688 JDName, HeaderAddr.toPtr<void *>());689 })690 .release();691}692 693ORC_RT_INTERFACE orc_rt_WrapperFunctionResult694__orc_rt_elfnix_deregister_jitdylib(char *ArgData, size_t ArgSize) {695 return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(696 ArgData, ArgSize,697 [](ExecutorAddr HeaderAddr) {698 return ELFNixPlatformRuntimeState::get().deregisterJITDylib(699 HeaderAddr.toPtr<void *>());700 })701 .release();702}703 704ORC_RT_INTERFACE orc_rt_WrapperFunctionResult705__orc_rt_elfnix_register_init_sections(char *ArgData, size_t ArgSize) {706 return WrapperFunction<SPSError(SPSExecutorAddr,707 SPSSequence<SPSExecutorAddrRange>)>::708 handle(ArgData, ArgSize,709 [](ExecutorAddr HeaderAddr,710 std::vector<ExecutorAddrRange> &Inits) {711 return ELFNixPlatformRuntimeState::get().registerInits(712 HeaderAddr, std::move(Inits));713 })714 .release();715}716 717ORC_RT_INTERFACE orc_rt_WrapperFunctionResult718__orc_rt_elfnix_deregister_init_sections(char *ArgData, size_t ArgSize) {719 return WrapperFunction<SPSError(SPSExecutorAddr,720 SPSSequence<SPSExecutorAddrRange>)>::721 handle(ArgData, ArgSize,722 [](ExecutorAddr HeaderAddr,723 std::vector<ExecutorAddrRange> &Inits) {724 return ELFNixPlatformRuntimeState::get().deregisterInits(725 HeaderAddr, std::move(Inits));726 })727 .release();728}729 730/// Wrapper function for registering metadata on a per-object basis.731ORC_RT_INTERFACE orc_rt_WrapperFunctionResult732__orc_rt_elfnix_register_object_sections(char *ArgData, size_t ArgSize) {733 return WrapperFunction<SPSError(SPSELFNixPerObjectSectionsToRegister)>::734 handle(ArgData, ArgSize,735 [](ELFNixPerObjectSectionsToRegister &POSR) {736 return ELFNixPlatformRuntimeState::get().registerObjectSections(737 std::move(POSR));738 })739 .release();740}741 742/// Wrapper for releasing per-object metadat.743ORC_RT_INTERFACE orc_rt_WrapperFunctionResult744__orc_rt_elfnix_deregister_object_sections(char *ArgData, size_t ArgSize) {745 return WrapperFunction<SPSError(SPSELFNixPerObjectSectionsToRegister)>::746 handle(ArgData, ArgSize,747 [](ELFNixPerObjectSectionsToRegister &POSR) {748 return ELFNixPlatformRuntimeState::get()749 .deregisterObjectSections(std::move(POSR));750 })751 .release();752}753 754//------------------------------------------------------------------------------755// TLV support756//------------------------------------------------------------------------------757 758ORC_RT_INTERFACE void *__orc_rt_elfnix_tls_get_addr_impl(TLSInfoEntry *D) {759 auto *TLVMgr = static_cast<ELFNixPlatformRuntimeTLVManager *>(760 pthread_getspecific(D->Key));761 if (!TLVMgr)762 TLVMgr = new ELFNixPlatformRuntimeTLVManager();763 if (pthread_setspecific(D->Key, TLVMgr)) {764 __orc_rt_log_error("Call to pthread_setspecific failed");765 return nullptr;766 }767 768 return TLVMgr->getInstance(769 reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));770}771 772ORC_RT_INTERFACE ptrdiff_t ___orc_rt_elfnix_tlsdesc_resolver_impl(773 TLSDescriptor *D, const char *ThreadPointer) {774 const char *TLVPtr = reinterpret_cast<const char *>(775 __orc_rt_elfnix_tls_get_addr_impl(D->InfoEntry));776 return TLVPtr - ThreadPointer;777}778 779ORC_RT_INTERFACE orc_rt_WrapperFunctionResult780__orc_rt_elfnix_create_pthread_key(char *ArgData, size_t ArgSize) {781 return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(782 ArgData, ArgSize,783 []() -> Expected<uint64_t> {784 pthread_key_t Key;785 if (int Err = pthread_key_create(&Key, destroyELFNixTLVMgr)) {786 __orc_rt_log_error("Call to pthread_key_create failed");787 return make_error<StringError>(strerror(Err));788 }789 return static_cast<uint64_t>(Key);790 })791 .release();792}793 794//------------------------------------------------------------------------------795// cxa_atexit support796//------------------------------------------------------------------------------797 798int __orc_rt_elfnix_cxa_atexit(void (*func)(void *), void *arg,799 void *dso_handle) {800 return ELFNixPlatformRuntimeState::get().registerAtExit(func, arg,801 dso_handle);802}803 804int __orc_rt_elfnix_atexit(void (*func)(void *)) {805 auto &PlatformRTState = ELFNixPlatformRuntimeState::get();806 return ELFNixPlatformRuntimeState::get().registerAtExit(807 func, NULL, PlatformRTState.getPlatformJDDSOHandle());808}809 810void __orc_rt_elfnix_cxa_finalize(void *dso_handle) {811 ELFNixPlatformRuntimeState::get().runAtExits(dso_handle);812}813 814//------------------------------------------------------------------------------815// JIT'd dlfcn alternatives.816//------------------------------------------------------------------------------817 818const char *__orc_rt_elfnix_jit_dlerror() {819 return ELFNixPlatformRuntimeState::get().dlerror();820}821 822void *__orc_rt_elfnix_jit_dlopen(const char *path, int mode) {823 return ELFNixPlatformRuntimeState::get().dlopen(path, mode);824}825 826int __orc_rt_elfnix_jit_dlupdate(void *dso_handle) {827 return ELFNixPlatformRuntimeState::get().dlupdate(dso_handle);828}829 830int __orc_rt_elfnix_jit_dlclose(void *dso_handle) {831 return ELFNixPlatformRuntimeState::get().dlclose(dso_handle);832}833 834void *__orc_rt_elfnix_jit_dlsym(void *dso_handle, const char *symbol) {835 return ELFNixPlatformRuntimeState::get().dlsym(dso_handle, symbol);836}837 838//------------------------------------------------------------------------------839// ELFNix Run Program840//------------------------------------------------------------------------------841 842ORC_RT_INTERFACE int64_t __orc_rt_elfnix_run_program(843 const char *JITDylibName, const char *EntrySymbolName, int argc,844 char *argv[]) {845 using MainTy = int (*)(int, char *[]);846 847 void *H = __orc_rt_elfnix_jit_dlopen(JITDylibName,848 orc_rt::elfnix::ORC_RT_RTLD_LAZY);849 if (!H) {850 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());851 return -1;852 }853 854 auto *Main =855 reinterpret_cast<MainTy>(__orc_rt_elfnix_jit_dlsym(H, EntrySymbolName));856 857 if (!Main) {858 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());859 return -1;860 }861 862 int Result = Main(argc, argv);863 864 if (__orc_rt_elfnix_jit_dlclose(H) == -1)865 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());866 867 return Result;868}869