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