1 //===- elfnix_platform.cpp ------------------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains code required to load the rest of the ELF-on-*IX runtime.
11 //===----------------------------------------------------------------------===//
13 #include "elfnix_platform.h"
17 #include "jit_dispatch.h"
18 #include "record_section_tracker.h"
19 #include "wrapper_function_utils.h"
25 #include <string_view>
26 #include <unordered_map>
29 using namespace orc_rt
;
30 using namespace orc_rt::elfnix
;
32 // Declare function tags for functions in the JIT process.
33 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_reoptimize_tag
)
34 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_push_initializers_tag
)
35 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_symbol_lookup_tag
)
37 // eh-frame registration functions, made available via aliases
38 // installed by the Platform
39 extern "C" void __register_frame(const void *);
40 extern "C" void __deregister_frame(const void *);
43 __unw_add_dynamic_eh_frame_section(const void *) ORC_RT_WEAK_IMPORT
;
45 __unw_remove_dynamic_eh_frame_section(const void *) ORC_RT_WEAK_IMPORT
;
50 unsigned long Key
= 0;
51 unsigned long DataAddress
= 0;
54 struct TLSDescriptor
{
55 void (*Resolver
)(void *);
56 TLSInfoEntry
*InfoEntry
;
59 class ELFNixPlatformRuntimeState
{
66 using AtExitsVector
= std::vector
<AtExitEntry
>;
68 struct PerJITDylibState
{
70 void *Header
= nullptr;
72 size_t LinkedAgainstRefCount
= 0;
73 bool AllowReinitialization
= false;
74 AtExitsVector AtExits
;
75 std::vector
<PerJITDylibState
*> Deps
;
76 RecordSectionsTracker
<void (*)()> RecordedInits
;
78 bool referenced() const {
79 return LinkedAgainstRefCount
!= 0 || RefCount
!= 0;
84 static void initialize(void *DSOHandle
);
85 static ELFNixPlatformRuntimeState
&get();
86 static void destroy();
88 ELFNixPlatformRuntimeState(void *DSOHandle
);
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;
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
);
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
);
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
);
117 /// Returns the base address of the section containing ThreadData.
118 Expected
<std::pair
<const char *, size_t>>
119 getThreadDataSectionFor(const char *ThreadData
);
121 void *getPlatformJDDSOHandle() { return PlatformJDDSOHandle
; }
124 PerJITDylibState
*getJITDylibStateByHeaderAddr(void *DSOHandle
);
125 PerJITDylibState
*getJITDylibStateByName(std::string_view Path
);
127 Error
registerThreadDataSection(span
<const char> ThreadDataSection
);
129 Expected
<ExecutorAddr
> lookupSymbolInJITDylib(void *DSOHandle
,
130 std::string_view Symbol
);
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
);
144 Error
dlcloseImpl(void *DSOHandle
);
145 Error
dlcloseInitialize(std::unique_lock
<std::recursive_mutex
> &JDStatesLock
,
146 PerJITDylibState
&JDS
);
148 static ELFNixPlatformRuntimeState
*MOPS
;
150 void *PlatformJDDSOHandle
;
152 // Frame registration functions:
153 void (*registerEHFrameSection
)(const void *) = nullptr;
154 void (*deregisterEHFrameSection
)(const void *) = nullptr;
156 // FIXME: Move to thread-state.
157 std::string DLFcnError
;
159 std::recursive_mutex JDStatesMutex
;
160 std::unordered_map
<void *, PerJITDylibState
> JDStates
;
161 std::unordered_map
<std::string
, void *> JDNameToHeader
;
163 std::mutex ThreadDataSectionsMutex
;
164 std::map
<const char *, size_t> ThreadDataSections
;
167 ELFNixPlatformRuntimeState
*ELFNixPlatformRuntimeState::MOPS
= nullptr;
169 void ELFNixPlatformRuntimeState::initialize(void *DSOHandle
) {
170 assert(!MOPS
&& "ELFNixPlatformRuntimeState should be null");
171 MOPS
= new ELFNixPlatformRuntimeState(DSOHandle
);
174 ELFNixPlatformRuntimeState
&ELFNixPlatformRuntimeState::get() {
175 assert(MOPS
&& "ELFNixPlatformRuntimeState not initialized");
179 void ELFNixPlatformRuntimeState::destroy() {
180 assert(MOPS
&& "ELFNixPlatformRuntimeState not initialized");
184 ELFNixPlatformRuntimeState::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
;
191 registerEHFrameSection
= __register_frame
;
192 deregisterEHFrameSection
= __deregister_frame
;
196 Error
ELFNixPlatformRuntimeState::registerObjectSections(
197 ELFNixPerObjectSectionsToRegister POSR
) {
198 if (POSR
.EHFrameSection
.Start
)
199 registerEHFrameSection(POSR
.EHFrameSection
.Start
.toPtr
<const char *>());
201 if (POSR
.ThreadDataSection
.Start
) {
202 if (auto Err
= registerThreadDataSection(
203 POSR
.ThreadDataSection
.toSpan
<const char>()))
207 return Error::success();
210 Error
ELFNixPlatformRuntimeState::deregisterObjectSections(
211 ELFNixPerObjectSectionsToRegister POSR
) {
212 if (POSR
.EHFrameSection
.Start
)
213 deregisterEHFrameSection(POSR
.EHFrameSection
.Start
.toPtr
<const char *>());
215 return Error::success();
218 Error
ELFNixPlatformRuntimeState::registerJITDylib(std::string
&Name
,
220 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
222 if (JDStates
.count(Handle
)) {
223 std::ostringstream ErrStream
;
224 ErrStream
<< "Duplicate JITDylib registration for header " << Handle
225 << " (name = " << Name
<< ")";
226 return make_error
<StringError
>(ErrStream
.str());
229 if (JDNameToHeader
.count(Name
)) {
230 std::ostringstream ErrStream
;
231 ErrStream
<< "Duplicate JITDylib registration for header " << Handle
232 << " (header = " << Handle
<< ")";
233 return make_error
<StringError
>(ErrStream
.str());
236 auto &JD
= JDStates
[Handle
];
238 JD
.Name
= std::move(Name
);
239 JDNameToHeader
[JD
.Name
] = Handle
;
240 return Error::success();
243 Error
ELFNixPlatformRuntimeState::deregisterJITDylib(void *Handle
) {
244 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
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());
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
);
259 return Error::success();
262 Error
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 *>());
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());
276 for (auto &I
: Inits
) {
277 JDS
->RecordedInits
.add(I
.toSpan
<void (*)()>());
280 return Error::success();
283 Error
ELFNixPlatformRuntimeState::deregisterInits(
284 ExecutorAddr HeaderAddr
, std::vector
<ExecutorAddrRange
> Inits
) {
286 std::lock_guard
<std::recursive_mutex
> Lock(JDStatesMutex
);
287 PerJITDylibState
*JDS
=
288 getJITDylibStateByHeaderAddr(HeaderAddr
.toPtr
<void *>());
291 std::ostringstream ErrStream
;
292 ErrStream
<< "Could not register object platform sections for unrecognized "
294 << HeaderAddr
.toPtr
<void *>();
295 return make_error
<StringError
>(ErrStream
.str());
298 for (auto &I
: Inits
) {
299 JDS
->RecordedInits
.removeIfPresent(I
);
302 return Error::success();
305 const char *ELFNixPlatformRuntimeState::dlerror() { return DLFcnError
.c_str(); }
307 void *ELFNixPlatformRuntimeState::dlopen(std::string_view Path
, int Mode
) {
308 if (auto H
= dlopenImpl(Path
, Mode
))
311 // FIXME: Make dlerror thread safe.
312 DLFcnError
= toString(H
.takeError());
317 int ELFNixPlatformRuntimeState::dlupdate(void *DSOHandle
) {
318 if (auto Err
= dlupdateImpl(DSOHandle
)) {
319 // FIXME: Make dlerror thread safe.
320 DLFcnError
= toString(std::move(Err
));
326 int ELFNixPlatformRuntimeState::dlclose(void *DSOHandle
) {
327 if (auto Err
= dlcloseImpl(DSOHandle
)) {
328 DLFcnError
= toString(std::move(Err
));
334 void *ELFNixPlatformRuntimeState::dlsym(void *DSOHandle
,
335 std::string_view Symbol
) {
336 auto Addr
= lookupSymbolInJITDylib(DSOHandle
, Symbol
);
338 DLFcnError
= toString(Addr
.takeError());
342 return Addr
->toPtr
<void *>();
345 int ELFNixPlatformRuntimeState::registerAtExit(void (*F
)(void *), void *Arg
,
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
});
355 void ELFNixPlatformRuntimeState::runAtExits(void *DSOHandle
) {
356 std::unique_lock
<std::recursive_mutex
> Lock(JDStatesMutex
);
357 PerJITDylibState
*JDS
= getJITDylibStateByHeaderAddr(DSOHandle
);
360 runAtExits(Lock
, *JDS
);
363 void ELFNixPlatformRuntimeState::runAtExits(
364 std::unique_lock
<std::recursive_mutex
> &JDStateLock
,
365 PerJITDylibState
&JDS
) {
366 AtExitsVector V
= std::move(JDS
.AtExits
);
375 Expected
<std::pair
<const char *, size_t>>
376 ELFNixPlatformRuntimeState::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");
383 if (ThreadData
>= I
->first
+ I
->second
)
384 return make_error
<StringError
>("No thread local data section for key");
388 ELFNixPlatformRuntimeState::PerJITDylibState
*
389 ELFNixPlatformRuntimeState::getJITDylibStateByHeaderAddr(void *DSOHandle
) {
390 auto I
= JDStates
.find(DSOHandle
);
391 if (I
== JDStates
.end())
397 ELFNixPlatformRuntimeState::PerJITDylibState
*
398 ELFNixPlatformRuntimeState::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())
404 auto J
= JDStates
.find(H
);
405 assert(J
!= JDStates
.end() &&
406 "JITDylib has name map entry but no header map entry");
410 Error
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");
419 ThreadDataSections
.insert(
420 I
, std::make_pair(ThreadDataSection
.data(), ThreadDataSection
.size()));
421 return Error::success();
424 Expected
<ExecutorAddr
>
425 ELFNixPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle
,
426 std::string_view Sym
) {
427 Expected
<ExecutorAddr
> Result((ExecutorAddr()));
428 if (auto Err
= WrapperFunction
<SPSExpected
<SPSExecutorAddr
>(
430 SPSString
)>::call(JITDispatch(&__orc_rt_elfnix_symbol_lookup_tag
),
431 Result
, ExecutorAddr::fromPtr(DSOHandle
), Sym
))
432 return std::move(Err
);
436 Error
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());
442 JDS
.RecordedInits
.processNewSections(
443 [&](span
<void (*)()> Inits
) { InitSections
.push_back(Inits
); });
445 JDStatesLock
.unlock();
446 for (auto Sec
: InitSections
)
447 for (auto *Init
: Sec
)
452 return Error::success();
455 Expected
<void *> ELFNixPlatformRuntimeState::dlopenImpl(std::string_view Path
,
457 std::unique_lock
<std::recursive_mutex
> Lock(JDStatesMutex
);
458 PerJITDylibState
*JDS
= getJITDylibStateByName(Path
);
461 return make_error
<StringError
>("No registered JTIDylib for path " +
462 std::string(Path
.data(), Path
.size()));
464 if (auto Err
= dlopenFull(Lock
, *JDS
))
465 return std::move(Err
);
472 Error
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
>(
479 call(JITDispatch(&__orc_rt_elfnix_push_initializers_tag
), DepInfo
,
480 ExecutorAddr::fromPtr(JDS
.Header
)))
485 return DepInfo
.takeError();
487 if (auto Err
= dlopenInitialize(JDStateLock
, JDS
, *DepInfo
))
490 if (!DepInfo
->empty()) {
491 std::ostringstream ErrStream
;
492 ErrStream
<< "Encountered unrecognized dep-info key headers "
493 "while processing dlopen of "
495 return make_error
<StringError
>(ErrStream
.str());
498 return Error::success();
501 Error
ELFNixPlatformRuntimeState::dlopenInitialize(
502 std::unique_lock
<std::recursive_mutex
> &JDStatesLock
, PerJITDylibState
&JDS
,
503 ELFNixJITDylibDepInfoMap
&DepInfo
) {
505 auto I
= DepInfo
.find(ExecutorAddr::fromPtr(JDS
.Header
));
506 if (I
== DepInfo
.end())
507 return Error::success();
509 auto Deps
= std::move(I
->second
);
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 *>());
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());
523 ++DepJDS
->LinkedAgainstRefCount
;
524 if (auto Err
= dlopenInitialize(JDStatesLock
, *DepJDS
, DepInfo
))
528 if (auto Err
= runInits(JDStatesLock
, JDS
))
531 for (auto *DepJDS
: OldDeps
) {
532 --DepJDS
->LinkedAgainstRefCount
;
533 if (!DepJDS
->referenced())
534 if (auto Err
= dlcloseInitialize(JDStatesLock
, *DepJDS
))
537 return Error::success();
540 Error
ELFNixPlatformRuntimeState::dlupdateImpl(void *DSOHandle
) {
541 std::unique_lock
<std::recursive_mutex
> Lock(JDStatesMutex
);
543 // Try to find JITDylib state by name.
544 auto *JDS
= getJITDylibStateByHeaderAddr(DSOHandle
);
547 std::ostringstream ErrStream
;
548 ErrStream
<< "No registered JITDylib for " << DSOHandle
;
549 return make_error
<StringError
>(ErrStream
.str());
552 if (!JDS
->referenced())
553 return make_error
<StringError
>("dlupdate failed, JITDylib must be open.");
555 if (auto Err
= dlupdateFull(Lock
, *JDS
))
558 return Error::success();
561 Error
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
>(
570 call(JITDispatch(&__orc_rt_elfnix_push_initializers_tag
), DepInfo
,
571 ExecutorAddr::fromPtr(JDS
.Header
)))
576 return DepInfo
.takeError();
578 if (auto Err
= runInits(JDStatesLock
, JDS
))
581 return Error::success();
584 Error
ELFNixPlatformRuntimeState::dlcloseImpl(void *DSOHandle
) {
586 std::unique_lock
<std::recursive_mutex
> Lock(JDStatesMutex
);
587 PerJITDylibState
*JDS
= getJITDylibStateByHeaderAddr(DSOHandle
);
590 std::ostringstream ErrStream
;
591 ErrStream
<< "No registered JITDylib for " << DSOHandle
;
592 return make_error
<StringError
>(ErrStream
.str());
597 if (!JDS
->referenced())
598 return dlcloseInitialize(Lock
, *JDS
);
600 return Error::success();
603 Error
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
))
613 return Error::success();
616 class ELFNixPlatformRuntimeTLVManager
{
618 void *getInstance(const char *ThreadData
);
621 std::unordered_map
<const char *, char *> Instances
;
622 std::unordered_map
<const char *, std::unique_ptr
<char[]>> AllocatedSections
;
625 void *ELFNixPlatformRuntimeTLVManager::getInstance(const char *ThreadData
) {
626 auto I
= Instances
.find(ThreadData
);
627 if (I
!= Instances
.end())
630 ELFNixPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData
);
632 __orc_rt_log_error(toString(TDS
.takeError()).c_str());
636 auto &Allocated
= AllocatedSections
[TDS
->first
];
638 Allocated
= std::make_unique
<char[]>(TDS
->second
);
639 memcpy(Allocated
.get(), TDS
->first
, TDS
->second
);
641 size_t ThreadDataDelta
= ThreadData
- TDS
->first
;
642 assert(ThreadDataDelta
<= TDS
->second
&& "ThreadData outside section bounds");
644 char *Instance
= Allocated
.get() + ThreadDataDelta
;
645 Instances
[ThreadData
] = Instance
;
649 void destroyELFNixTLVMgr(void *ELFNixTLVMgr
) {
650 delete static_cast<ELFNixPlatformRuntimeTLVManager
*>(ELFNixTLVMgr
);
653 } // end anonymous namespace
655 //------------------------------------------------------------------------------
657 //------------------------------------------------------------------------------
659 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
660 __orc_rt_elfnix_platform_bootstrap(char *ArgData
, size_t ArgSize
) {
661 return WrapperFunction
<SPSError(SPSExecutorAddr
)>::handle(
663 [](ExecutorAddr DSOHandle
) {
664 ELFNixPlatformRuntimeState::initialize(
665 DSOHandle
.toPtr
<void *>());
666 return Error::success();
671 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
672 __orc_rt_elfnix_platform_shutdown(char *ArgData
, size_t ArgSize
) {
673 return WrapperFunction
<SPSError()>::handle(
676 ELFNixPlatformRuntimeState::destroy();
677 return Error::success();
682 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
683 __orc_rt_elfnix_register_jitdylib(char *ArgData
, size_t ArgSize
) {
684 return WrapperFunction
<SPSError(SPSString
, SPSExecutorAddr
)>::handle(
686 [](std::string
&JDName
, ExecutorAddr HeaderAddr
) {
687 return ELFNixPlatformRuntimeState::get().registerJITDylib(
688 JDName
, HeaderAddr
.toPtr
<void *>());
693 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
694 __orc_rt_elfnix_deregister_jitdylib(char *ArgData
, size_t ArgSize
) {
695 return WrapperFunction
<SPSError(SPSExecutorAddr
)>::handle(
697 [](ExecutorAddr HeaderAddr
) {
698 return ELFNixPlatformRuntimeState::get().deregisterJITDylib(
699 HeaderAddr
.toPtr
<void *>());
704 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
705 __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
));
717 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
718 __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
));
730 /// Wrapper function for registering metadata on a per-object basis.
731 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
732 __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(
742 /// Wrapper for releasing per-object metadat.
743 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
744 __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
));
754 //------------------------------------------------------------------------------
756 //------------------------------------------------------------------------------
758 ORC_RT_INTERFACE
void *__orc_rt_elfnix_tls_get_addr_impl(TLSInfoEntry
*D
) {
759 auto *TLVMgr
= static_cast<ELFNixPlatformRuntimeTLVManager
*>(
760 pthread_getspecific(D
->Key
));
762 TLVMgr
= new ELFNixPlatformRuntimeTLVManager();
763 if (pthread_setspecific(D
->Key
, TLVMgr
)) {
764 __orc_rt_log_error("Call to pthread_setspecific failed");
768 return TLVMgr
->getInstance(
769 reinterpret_cast<char *>(static_cast<uintptr_t>(D
->DataAddress
)));
772 ORC_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
;
779 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
780 __orc_rt_elfnix_create_pthread_key(char *ArgData
, size_t ArgSize
) {
781 return WrapperFunction
<SPSExpected
<uint64_t>(void)>::handle(
783 []() -> Expected
<uint64_t> {
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
));
789 return static_cast<uint64_t>(Key
);
794 //------------------------------------------------------------------------------
795 // cxa_atexit support
796 //------------------------------------------------------------------------------
798 int __orc_rt_elfnix_cxa_atexit(void (*func
)(void *), void *arg
,
800 return ELFNixPlatformRuntimeState::get().registerAtExit(func
, arg
,
804 int __orc_rt_elfnix_atexit(void (*func
)(void *)) {
805 auto &PlatformRTState
= ELFNixPlatformRuntimeState::get();
806 return ELFNixPlatformRuntimeState::get().registerAtExit(
807 func
, NULL
, PlatformRTState
.getPlatformJDDSOHandle());
810 void __orc_rt_elfnix_cxa_finalize(void *dso_handle
) {
811 ELFNixPlatformRuntimeState::get().runAtExits(dso_handle
);
814 //------------------------------------------------------------------------------
815 // JIT'd dlfcn alternatives.
816 //------------------------------------------------------------------------------
818 const char *__orc_rt_elfnix_jit_dlerror() {
819 return ELFNixPlatformRuntimeState::get().dlerror();
822 void *__orc_rt_elfnix_jit_dlopen(const char *path
, int mode
) {
823 return ELFNixPlatformRuntimeState::get().dlopen(path
, mode
);
826 int __orc_rt_elfnix_jit_dlupdate(void *dso_handle
) {
827 return ELFNixPlatformRuntimeState::get().dlupdate(dso_handle
);
830 int __orc_rt_elfnix_jit_dlclose(void *dso_handle
) {
831 return ELFNixPlatformRuntimeState::get().dlclose(dso_handle
);
834 void *__orc_rt_elfnix_jit_dlsym(void *dso_handle
, const char *symbol
) {
835 return ELFNixPlatformRuntimeState::get().dlsym(dso_handle
, symbol
);
838 //------------------------------------------------------------------------------
839 // ELFNix Run Program
840 //------------------------------------------------------------------------------
842 ORC_RT_INTERFACE
int64_t __orc_rt_elfnix_run_program(
843 const char *JITDylibName
, const char *EntrySymbolName
, int argc
,
845 using MainTy
= int (*)(int, char *[]);
847 void *H
= __orc_rt_elfnix_jit_dlopen(JITDylibName
,
848 orc_rt::elfnix::ORC_RT_RTLD_LAZY
);
850 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());
855 reinterpret_cast<MainTy
>(__orc_rt_elfnix_jit_dlsym(H
, EntrySymbolName
));
858 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());
862 int Result
= Main(argc
, argv
);
864 if (__orc_rt_elfnix_jit_dlclose(H
) == -1)
865 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());