xref: /llvm-project/compiler-rt/lib/orc/elfnix_platform.cpp (revision f363f9d61eaff7090a19d226ea8786b2987d4fcc)
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