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-exception
6 //
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 "error.h"
16 #include "wrapper_function_utils.h"
17
18 #include <algorithm>
19 #include <map>
20 #include <mutex>
21 #include <sstream>
22 #include <unordered_map>
23 #include <vector>
24
25 using namespace __orc_rt;
26 using namespace __orc_rt::elfnix;
27
28 // Declare function tags for functions in the JIT process.
29 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_get_initializers_tag)
30 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_get_deinitializers_tag)
31 ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_symbol_lookup_tag)
32
33 // eh-frame registration functions, made available via aliases
34 // installed by the Platform
35 extern "C" void __orc_rt_register_eh_frame_section(const void *);
36 extern "C" void __orc_rt_deregister_eh_frame_section(const void *);
37
38 namespace {
39
validatePointerSectionExtent(const char * SectionName,const ExecutorAddrRange & SE)40 Error validatePointerSectionExtent(const char *SectionName,
41 const ExecutorAddrRange &SE) {
42 if (SE.size().getValue() % sizeof(uintptr_t)) {
43 std::ostringstream ErrMsg;
44 ErrMsg << std::hex << "Size of " << SectionName << " 0x"
45 << SE.Start.getValue() << " -- 0x" << SE.End.getValue()
46 << " is not a pointer multiple";
47 return make_error<StringError>(ErrMsg.str());
48 }
49 return Error::success();
50 }
51
runInitArray(const std::vector<ExecutorAddrRange> & InitArraySections,const ELFNixJITDylibInitializers & MOJDIs)52 Error runInitArray(const std::vector<ExecutorAddrRange> &InitArraySections,
53 const ELFNixJITDylibInitializers &MOJDIs) {
54
55 for (const auto &ModInits : InitArraySections) {
56 if (auto Err = validatePointerSectionExtent(".init_array", ModInits))
57 return Err;
58
59 using InitFunc = void (*)();
60 for (auto *Init : ModInits.toSpan<InitFunc>())
61 (*Init)();
62 }
63
64 return Error::success();
65 }
66
67 struct TLSInfoEntry {
68 unsigned long Key = 0;
69 unsigned long DataAddress = 0;
70 };
71
72 struct TLSDescriptor {
73 void (*Resolver)(void *);
74 TLSInfoEntry *InfoEntry;
75 };
76
77 class ELFNixPlatformRuntimeState {
78 private:
79 struct AtExitEntry {
80 void (*Func)(void *);
81 void *Arg;
82 };
83
84 using AtExitsVector = std::vector<AtExitEntry>;
85
86 struct PerJITDylibState {
87 void *Header = nullptr;
88 size_t RefCount = 0;
89 bool AllowReinitialization = false;
90 AtExitsVector AtExits;
91 };
92
93 public:
94 static void initialize(void *DSOHandle);
95 static ELFNixPlatformRuntimeState &get();
96 static void destroy();
97
ELFNixPlatformRuntimeState(void * DSOHandle)98 ELFNixPlatformRuntimeState(void *DSOHandle)
99 : PlatformJDDSOHandle(DSOHandle) {}
100
101 // Delete copy and move constructors.
102 ELFNixPlatformRuntimeState(const ELFNixPlatformRuntimeState &) = delete;
103 ELFNixPlatformRuntimeState &
104 operator=(const ELFNixPlatformRuntimeState &) = delete;
105 ELFNixPlatformRuntimeState(ELFNixPlatformRuntimeState &&) = delete;
106 ELFNixPlatformRuntimeState &operator=(ELFNixPlatformRuntimeState &&) = delete;
107
108 Error registerObjectSections(ELFNixPerObjectSectionsToRegister POSR);
109 Error deregisterObjectSections(ELFNixPerObjectSectionsToRegister POSR);
110
111 const char *dlerror();
112 void *dlopen(string_view Name, int Mode);
113 int dlclose(void *DSOHandle);
114 void *dlsym(void *DSOHandle, string_view Symbol);
115
116 int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle);
117 void runAtExits(void *DSOHandle);
118
119 /// Returns the base address of the section containing ThreadData.
120 Expected<std::pair<const char *, size_t>>
121 getThreadDataSectionFor(const char *ThreadData);
122
getPlatformJDDSOHandle()123 void *getPlatformJDDSOHandle() { return PlatformJDDSOHandle; }
124
125 private:
126 PerJITDylibState *getJITDylibStateByHeaderAddr(void *DSOHandle);
127 PerJITDylibState *getJITDylibStateByName(string_view Path);
128 PerJITDylibState &
129 getOrCreateJITDylibState(ELFNixJITDylibInitializers &MOJDIs);
130
131 Error registerThreadDataSection(span<const char> ThreadDataSection);
132
133 Expected<ExecutorAddr> lookupSymbolInJITDylib(void *DSOHandle,
134 string_view Symbol);
135
136 Expected<ELFNixJITDylibInitializerSequence>
137 getJITDylibInitializersByName(string_view Path);
138 Expected<void *> dlopenInitialize(string_view Path, int Mode);
139 Error initializeJITDylib(ELFNixJITDylibInitializers &MOJDIs);
140
141 static ELFNixPlatformRuntimeState *MOPS;
142
143 void *PlatformJDDSOHandle;
144
145 // FIXME: Move to thread-state.
146 std::string DLFcnError;
147
148 std::recursive_mutex JDStatesMutex;
149 std::unordered_map<void *, PerJITDylibState> JDStates;
150 std::unordered_map<std::string, void *> JDNameToHeader;
151
152 std::mutex ThreadDataSectionsMutex;
153 std::map<const char *, size_t> ThreadDataSections;
154 };
155
156 ELFNixPlatformRuntimeState *ELFNixPlatformRuntimeState::MOPS = nullptr;
157
initialize(void * DSOHandle)158 void ELFNixPlatformRuntimeState::initialize(void *DSOHandle) {
159 assert(!MOPS && "ELFNixPlatformRuntimeState should be null");
160 MOPS = new ELFNixPlatformRuntimeState(DSOHandle);
161 }
162
get()163 ELFNixPlatformRuntimeState &ELFNixPlatformRuntimeState::get() {
164 assert(MOPS && "ELFNixPlatformRuntimeState not initialized");
165 return *MOPS;
166 }
167
destroy()168 void ELFNixPlatformRuntimeState::destroy() {
169 assert(MOPS && "ELFNixPlatformRuntimeState not initialized");
170 delete MOPS;
171 }
172
registerObjectSections(ELFNixPerObjectSectionsToRegister POSR)173 Error ELFNixPlatformRuntimeState::registerObjectSections(
174 ELFNixPerObjectSectionsToRegister POSR) {
175 if (POSR.EHFrameSection.Start)
176 __orc_rt_register_eh_frame_section(
177 POSR.EHFrameSection.Start.toPtr<const char *>());
178
179 if (POSR.ThreadDataSection.Start) {
180 if (auto Err = registerThreadDataSection(
181 POSR.ThreadDataSection.toSpan<const char>()))
182 return Err;
183 }
184
185 return Error::success();
186 }
187
deregisterObjectSections(ELFNixPerObjectSectionsToRegister POSR)188 Error ELFNixPlatformRuntimeState::deregisterObjectSections(
189 ELFNixPerObjectSectionsToRegister POSR) {
190 if (POSR.EHFrameSection.Start)
191 __orc_rt_deregister_eh_frame_section(
192 POSR.EHFrameSection.Start.toPtr<const char *>());
193
194 return Error::success();
195 }
196
dlerror()197 const char *ELFNixPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); }
198
dlopen(string_view Path,int Mode)199 void *ELFNixPlatformRuntimeState::dlopen(string_view Path, int Mode) {
200 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
201
202 // Use fast path if all JITDylibs are already loaded and don't require
203 // re-running initializers.
204 if (auto *JDS = getJITDylibStateByName(Path)) {
205 if (!JDS->AllowReinitialization) {
206 ++JDS->RefCount;
207 return JDS->Header;
208 }
209 }
210
211 auto H = dlopenInitialize(Path, Mode);
212 if (!H) {
213 DLFcnError = toString(H.takeError());
214 return nullptr;
215 }
216
217 return *H;
218 }
219
dlclose(void * DSOHandle)220 int ELFNixPlatformRuntimeState::dlclose(void *DSOHandle) {
221 runAtExits(DSOHandle);
222 return 0;
223 }
224
dlsym(void * DSOHandle,string_view Symbol)225 void *ELFNixPlatformRuntimeState::dlsym(void *DSOHandle, string_view Symbol) {
226 auto Addr = lookupSymbolInJITDylib(DSOHandle, Symbol);
227 if (!Addr) {
228 DLFcnError = toString(Addr.takeError());
229 return 0;
230 }
231
232 return Addr->toPtr<void *>();
233 }
234
registerAtExit(void (* F)(void *),void * Arg,void * DSOHandle)235 int ELFNixPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg,
236 void *DSOHandle) {
237 // FIXME: Handle out-of-memory errors, returning -1 if OOM.
238 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
239 auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
240 assert(JDS && "JITDylib state not initialized");
241 JDS->AtExits.push_back({F, Arg});
242 return 0;
243 }
244
runAtExits(void * DSOHandle)245 void ELFNixPlatformRuntimeState::runAtExits(void *DSOHandle) {
246 // FIXME: Should atexits be allowed to run concurrently with access to
247 // JDState?
248 AtExitsVector V;
249 {
250 std::lock_guard<std::recursive_mutex> Lock(JDStatesMutex);
251 auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
252 assert(JDS && "JITDlybi state not initialized");
253 std::swap(V, JDS->AtExits);
254 }
255
256 while (!V.empty()) {
257 auto &AE = V.back();
258 AE.Func(AE.Arg);
259 V.pop_back();
260 }
261 }
262
263 Expected<std::pair<const char *, size_t>>
getThreadDataSectionFor(const char * ThreadData)264 ELFNixPlatformRuntimeState::getThreadDataSectionFor(const char *ThreadData) {
265 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
266 auto I = ThreadDataSections.upper_bound(ThreadData);
267 // Check that we have a valid entry conovering this address.
268 if (I == ThreadDataSections.begin())
269 return make_error<StringError>("No thread local data section for key");
270 I = std::prev(I);
271 if (ThreadData >= I->first + I->second)
272 return make_error<StringError>("No thread local data section for key");
273 return *I;
274 }
275
276 ELFNixPlatformRuntimeState::PerJITDylibState *
getJITDylibStateByHeaderAddr(void * DSOHandle)277 ELFNixPlatformRuntimeState::getJITDylibStateByHeaderAddr(void *DSOHandle) {
278 auto I = JDStates.find(DSOHandle);
279 if (I == JDStates.end())
280 return nullptr;
281 return &I->second;
282 }
283
284 ELFNixPlatformRuntimeState::PerJITDylibState *
getJITDylibStateByName(string_view Name)285 ELFNixPlatformRuntimeState::getJITDylibStateByName(string_view Name) {
286 // FIXME: Avoid creating string copy here.
287 auto I = JDNameToHeader.find(std::string(Name.data(), Name.size()));
288 if (I == JDNameToHeader.end())
289 return nullptr;
290 void *H = I->second;
291 auto J = JDStates.find(H);
292 assert(J != JDStates.end() &&
293 "JITDylib has name map entry but no header map entry");
294 return &J->second;
295 }
296
297 ELFNixPlatformRuntimeState::PerJITDylibState &
getOrCreateJITDylibState(ELFNixJITDylibInitializers & MOJDIs)298 ELFNixPlatformRuntimeState::getOrCreateJITDylibState(
299 ELFNixJITDylibInitializers &MOJDIs) {
300 void *Header = MOJDIs.DSOHandleAddress.toPtr<void *>();
301
302 auto &JDS = JDStates[Header];
303
304 // If this entry hasn't been created yet.
305 if (!JDS.Header) {
306 assert(!JDNameToHeader.count(MOJDIs.Name) &&
307 "JITDylib has header map entry but no name map entry");
308 JDNameToHeader[MOJDIs.Name] = Header;
309 JDS.Header = Header;
310 }
311
312 return JDS;
313 }
314
registerThreadDataSection(span<const char> ThreadDataSection)315 Error ELFNixPlatformRuntimeState::registerThreadDataSection(
316 span<const char> ThreadDataSection) {
317 std::lock_guard<std::mutex> Lock(ThreadDataSectionsMutex);
318 auto I = ThreadDataSections.upper_bound(ThreadDataSection.data());
319 if (I != ThreadDataSections.begin()) {
320 auto J = std::prev(I);
321 if (J->first + J->second > ThreadDataSection.data())
322 return make_error<StringError>("Overlapping .tdata sections");
323 }
324 ThreadDataSections.insert(
325 I, std::make_pair(ThreadDataSection.data(), ThreadDataSection.size()));
326 return Error::success();
327 }
328
329 Expected<ExecutorAddr>
lookupSymbolInJITDylib(void * DSOHandle,string_view Sym)330 ELFNixPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle,
331 string_view Sym) {
332 Expected<ExecutorAddr> Result((ExecutorAddr()));
333 if (auto Err = WrapperFunction<SPSExpected<SPSExecutorAddr>(
334 SPSExecutorAddr, SPSString)>::call(&__orc_rt_elfnix_symbol_lookup_tag,
335 Result,
336 ExecutorAddr::fromPtr(DSOHandle),
337 Sym))
338 return std::move(Err);
339 return Result;
340 }
341
342 Expected<ELFNixJITDylibInitializerSequence>
getJITDylibInitializersByName(string_view Path)343 ELFNixPlatformRuntimeState::getJITDylibInitializersByName(string_view Path) {
344 Expected<ELFNixJITDylibInitializerSequence> Result(
345 (ELFNixJITDylibInitializerSequence()));
346 std::string PathStr(Path.data(), Path.size());
347 if (auto Err =
348 WrapperFunction<SPSExpected<SPSELFNixJITDylibInitializerSequence>(
349 SPSString)>::call(&__orc_rt_elfnix_get_initializers_tag, Result,
350 Path))
351 return std::move(Err);
352 return Result;
353 }
354
dlopenInitialize(string_view Path,int Mode)355 Expected<void *> ELFNixPlatformRuntimeState::dlopenInitialize(string_view Path,
356 int Mode) {
357 // Either our JITDylib wasn't loaded, or it or one of its dependencies allows
358 // reinitialization. We need to call in to the JIT to see if there's any new
359 // work pending.
360 auto InitSeq = getJITDylibInitializersByName(Path);
361 if (!InitSeq)
362 return InitSeq.takeError();
363
364 // Init sequences should be non-empty.
365 if (InitSeq->empty())
366 return make_error<StringError>(
367 "__orc_rt_elfnix_get_initializers returned an "
368 "empty init sequence");
369
370 // Otherwise register and run initializers for each JITDylib.
371 for (auto &MOJDIs : *InitSeq)
372 if (auto Err = initializeJITDylib(MOJDIs))
373 return std::move(Err);
374
375 // Return the header for the last item in the list.
376 auto *JDS = getJITDylibStateByHeaderAddr(
377 InitSeq->back().DSOHandleAddress.toPtr<void *>());
378 assert(JDS && "Missing state entry for JD");
379 return JDS->Header;
380 }
381
getPriority(const std::string & name)382 long getPriority(const std::string &name) {
383 auto pos = name.find_last_not_of("0123456789");
384 if (pos == name.size() - 1)
385 return 65535;
386 else
387 return std::strtol(name.c_str() + pos + 1, nullptr, 10);
388 }
389
initializeJITDylib(ELFNixJITDylibInitializers & MOJDIs)390 Error ELFNixPlatformRuntimeState::initializeJITDylib(
391 ELFNixJITDylibInitializers &MOJDIs) {
392
393 auto &JDS = getOrCreateJITDylibState(MOJDIs);
394 ++JDS.RefCount;
395
396 using SectionList = std::vector<ExecutorAddrRange>;
397 std::sort(MOJDIs.InitSections.begin(), MOJDIs.InitSections.end(),
398 [](const std::pair<std::string, SectionList> &LHS,
399 const std::pair<std::string, SectionList> &RHS) -> bool {
400 return getPriority(LHS.first) < getPriority(RHS.first);
401 });
402 for (auto &Entry : MOJDIs.InitSections)
403 if (auto Err = runInitArray(Entry.second, MOJDIs))
404 return Err;
405
406 return Error::success();
407 }
408 class ELFNixPlatformRuntimeTLVManager {
409 public:
410 void *getInstance(const char *ThreadData);
411
412 private:
413 std::unordered_map<const char *, char *> Instances;
414 std::unordered_map<const char *, std::unique_ptr<char[]>> AllocatedSections;
415 };
416
getInstance(const char * ThreadData)417 void *ELFNixPlatformRuntimeTLVManager::getInstance(const char *ThreadData) {
418 auto I = Instances.find(ThreadData);
419 if (I != Instances.end())
420 return I->second;
421 auto TDS =
422 ELFNixPlatformRuntimeState::get().getThreadDataSectionFor(ThreadData);
423 if (!TDS) {
424 __orc_rt_log_error(toString(TDS.takeError()).c_str());
425 return nullptr;
426 }
427
428 auto &Allocated = AllocatedSections[TDS->first];
429 if (!Allocated) {
430 Allocated = std::make_unique<char[]>(TDS->second);
431 memcpy(Allocated.get(), TDS->first, TDS->second);
432 }
433 size_t ThreadDataDelta = ThreadData - TDS->first;
434 assert(ThreadDataDelta <= TDS->second && "ThreadData outside section bounds");
435
436 char *Instance = Allocated.get() + ThreadDataDelta;
437 Instances[ThreadData] = Instance;
438 return Instance;
439 }
440
destroyELFNixTLVMgr(void * ELFNixTLVMgr)441 void destroyELFNixTLVMgr(void *ELFNixTLVMgr) {
442 delete static_cast<ELFNixPlatformRuntimeTLVManager *>(ELFNixTLVMgr);
443 }
444
445 } // end anonymous namespace
446
447 //------------------------------------------------------------------------------
448 // JIT entry points
449 //------------------------------------------------------------------------------
450
451 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_elfnix_platform_bootstrap(char * ArgData,size_t ArgSize)452 __orc_rt_elfnix_platform_bootstrap(char *ArgData, size_t ArgSize) {
453 return WrapperFunction<void(uint64_t)>::handle(
454 ArgData, ArgSize,
455 [](uint64_t &DSOHandle) {
456 ELFNixPlatformRuntimeState::initialize(
457 reinterpret_cast<void *>(DSOHandle));
458 })
459 .release();
460 }
461
462 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_elfnix_platform_shutdown(char * ArgData,size_t ArgSize)463 __orc_rt_elfnix_platform_shutdown(char *ArgData, size_t ArgSize) {
464 ELFNixPlatformRuntimeState::destroy();
465 return WrapperFunctionResult().release();
466 }
467
468 /// Wrapper function for registering metadata on a per-object basis.
469 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_elfnix_register_object_sections(char * ArgData,size_t ArgSize)470 __orc_rt_elfnix_register_object_sections(char *ArgData, size_t ArgSize) {
471 return WrapperFunction<SPSError(SPSELFNixPerObjectSectionsToRegister)>::
472 handle(ArgData, ArgSize,
473 [](ELFNixPerObjectSectionsToRegister &POSR) {
474 return ELFNixPlatformRuntimeState::get().registerObjectSections(
475 std::move(POSR));
476 })
477 .release();
478 }
479
480 /// Wrapper for releasing per-object metadat.
481 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_elfnix_deregister_object_sections(char * ArgData,size_t ArgSize)482 __orc_rt_elfnix_deregister_object_sections(char *ArgData, size_t ArgSize) {
483 return WrapperFunction<SPSError(SPSELFNixPerObjectSectionsToRegister)>::
484 handle(ArgData, ArgSize,
485 [](ELFNixPerObjectSectionsToRegister &POSR) {
486 return ELFNixPlatformRuntimeState::get()
487 .deregisterObjectSections(std::move(POSR));
488 })
489 .release();
490 }
491
492 //------------------------------------------------------------------------------
493 // TLV support
494 //------------------------------------------------------------------------------
495
__orc_rt_elfnix_tls_get_addr_impl(TLSInfoEntry * D)496 ORC_RT_INTERFACE void *__orc_rt_elfnix_tls_get_addr_impl(TLSInfoEntry *D) {
497 auto *TLVMgr = static_cast<ELFNixPlatformRuntimeTLVManager *>(
498 pthread_getspecific(D->Key));
499 if (!TLVMgr)
500 TLVMgr = new ELFNixPlatformRuntimeTLVManager();
501 if (pthread_setspecific(D->Key, TLVMgr)) {
502 __orc_rt_log_error("Call to pthread_setspecific failed");
503 return nullptr;
504 }
505
506 return TLVMgr->getInstance(
507 reinterpret_cast<char *>(static_cast<uintptr_t>(D->DataAddress)));
508 }
509
___orc_rt_elfnix_tlsdesc_resolver_impl(TLSDescriptor * D,const char * ThreadPointer)510 ORC_RT_INTERFACE ptrdiff_t ___orc_rt_elfnix_tlsdesc_resolver_impl(
511 TLSDescriptor *D, const char *ThreadPointer) {
512 const char *TLVPtr = reinterpret_cast<const char *>(
513 __orc_rt_elfnix_tls_get_addr_impl(D->InfoEntry));
514 return TLVPtr - ThreadPointer;
515 }
516
517 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_elfnix_create_pthread_key(char * ArgData,size_t ArgSize)518 __orc_rt_elfnix_create_pthread_key(char *ArgData, size_t ArgSize) {
519 return WrapperFunction<SPSExpected<uint64_t>(void)>::handle(
520 ArgData, ArgSize,
521 []() -> Expected<uint64_t> {
522 pthread_key_t Key;
523 if (int Err = pthread_key_create(&Key, destroyELFNixTLVMgr)) {
524 __orc_rt_log_error("Call to pthread_key_create failed");
525 return make_error<StringError>(strerror(Err));
526 }
527 return static_cast<uint64_t>(Key);
528 })
529 .release();
530 }
531
532 //------------------------------------------------------------------------------
533 // cxa_atexit support
534 //------------------------------------------------------------------------------
535
__orc_rt_elfnix_cxa_atexit(void (* func)(void *),void * arg,void * dso_handle)536 int __orc_rt_elfnix_cxa_atexit(void (*func)(void *), void *arg,
537 void *dso_handle) {
538 return ELFNixPlatformRuntimeState::get().registerAtExit(func, arg,
539 dso_handle);
540 }
541
__orc_rt_elfnix_atexit(void (* func)(void *))542 int __orc_rt_elfnix_atexit(void (*func)(void *)) {
543 auto &PlatformRTState = ELFNixPlatformRuntimeState::get();
544 return ELFNixPlatformRuntimeState::get().registerAtExit(
545 func, NULL, PlatformRTState.getPlatformJDDSOHandle());
546 }
547
__orc_rt_elfnix_cxa_finalize(void * dso_handle)548 void __orc_rt_elfnix_cxa_finalize(void *dso_handle) {
549 ELFNixPlatformRuntimeState::get().runAtExits(dso_handle);
550 }
551
552 //------------------------------------------------------------------------------
553 // JIT'd dlfcn alternatives.
554 //------------------------------------------------------------------------------
555
__orc_rt_elfnix_jit_dlerror()556 const char *__orc_rt_elfnix_jit_dlerror() {
557 return ELFNixPlatformRuntimeState::get().dlerror();
558 }
559
__orc_rt_elfnix_jit_dlopen(const char * path,int mode)560 void *__orc_rt_elfnix_jit_dlopen(const char *path, int mode) {
561 return ELFNixPlatformRuntimeState::get().dlopen(path, mode);
562 }
563
__orc_rt_elfnix_jit_dlclose(void * dso_handle)564 int __orc_rt_elfnix_jit_dlclose(void *dso_handle) {
565 return ELFNixPlatformRuntimeState::get().dlclose(dso_handle);
566 }
567
__orc_rt_elfnix_jit_dlsym(void * dso_handle,const char * symbol)568 void *__orc_rt_elfnix_jit_dlsym(void *dso_handle, const char *symbol) {
569 return ELFNixPlatformRuntimeState::get().dlsym(dso_handle, symbol);
570 }
571
572 //------------------------------------------------------------------------------
573 // ELFNix Run Program
574 //------------------------------------------------------------------------------
575
__orc_rt_elfnix_run_program(const char * JITDylibName,const char * EntrySymbolName,int argc,char * argv[])576 ORC_RT_INTERFACE int64_t __orc_rt_elfnix_run_program(
577 const char *JITDylibName, const char *EntrySymbolName, int argc,
578 char *argv[]) {
579 using MainTy = int (*)(int, char *[]);
580
581 void *H = __orc_rt_elfnix_jit_dlopen(JITDylibName,
582 __orc_rt::elfnix::ORC_RT_RTLD_LAZY);
583 if (!H) {
584 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());
585 return -1;
586 }
587
588 auto *Main =
589 reinterpret_cast<MainTy>(__orc_rt_elfnix_jit_dlsym(H, EntrySymbolName));
590
591 if (!Main) {
592 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());
593 return -1;
594 }
595
596 int Result = Main(argc, argv);
597
598 if (__orc_rt_elfnix_jit_dlclose(H) == -1)
599 __orc_rt_log_error(__orc_rt_elfnix_jit_dlerror());
600
601 return Result;
602 }
603