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