1*a2c1cf09SLang Hames //===--- SimpleExecutorDylibManager.cpp - Executor-side dylib management --===//
2*a2c1cf09SLang Hames //
3*a2c1cf09SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*a2c1cf09SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5*a2c1cf09SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*a2c1cf09SLang Hames //
7*a2c1cf09SLang Hames //===----------------------------------------------------------------------===//
8*a2c1cf09SLang Hames 
9*a2c1cf09SLang Hames #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h"
10*a2c1cf09SLang Hames 
11*a2c1cf09SLang Hames #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12*a2c1cf09SLang Hames #include "llvm/Support/FormatVariadic.h"
13*a2c1cf09SLang Hames 
14*a2c1cf09SLang Hames #define DEBUG_TYPE "orc"
15*a2c1cf09SLang Hames 
16*a2c1cf09SLang Hames namespace llvm {
17*a2c1cf09SLang Hames namespace orc {
18*a2c1cf09SLang Hames namespace rt_bootstrap {
19*a2c1cf09SLang Hames 
20*a2c1cf09SLang Hames SimpleExecutorDylibManager::~SimpleExecutorDylibManager() {
21*a2c1cf09SLang Hames   assert(Dylibs.empty() && "shutdown not called?");
22*a2c1cf09SLang Hames }
23*a2c1cf09SLang Hames 
24*a2c1cf09SLang Hames Expected<tpctypes::DylibHandle>
25*a2c1cf09SLang Hames SimpleExecutorDylibManager::open(const std::string &Path, uint64_t Mode) {
26*a2c1cf09SLang Hames   if (Mode != 0)
27*a2c1cf09SLang Hames     return make_error<StringError>("open: non-zero mode bits not yet supported",
28*a2c1cf09SLang Hames                                    inconvertibleErrorCode());
29*a2c1cf09SLang Hames 
30*a2c1cf09SLang Hames   const char *PathCStr = Path.empty() ? nullptr : Path.c_str();
31*a2c1cf09SLang Hames   std::string ErrMsg;
32*a2c1cf09SLang Hames 
33*a2c1cf09SLang Hames   auto DL = sys::DynamicLibrary::getPermanentLibrary(PathCStr, &ErrMsg);
34*a2c1cf09SLang Hames   if (!DL.isValid())
35*a2c1cf09SLang Hames     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
36*a2c1cf09SLang Hames 
37*a2c1cf09SLang Hames   std::lock_guard<std::mutex> Lock(M);
38*a2c1cf09SLang Hames   Dylibs[NextId] = std::move(DL);
39*a2c1cf09SLang Hames   return NextId++;
40*a2c1cf09SLang Hames }
41*a2c1cf09SLang Hames 
42*a2c1cf09SLang Hames Expected<std::vector<ExecutorAddress>>
43*a2c1cf09SLang Hames SimpleExecutorDylibManager::lookup(tpctypes::DylibHandle H,
44*a2c1cf09SLang Hames                                    const RemoteSymbolLookupSet &L) {
45*a2c1cf09SLang Hames   std::vector<ExecutorAddress> Result;
46*a2c1cf09SLang Hames 
47*a2c1cf09SLang Hames   std::lock_guard<std::mutex> Lock(M);
48*a2c1cf09SLang Hames   auto I = Dylibs.find(H);
49*a2c1cf09SLang Hames   if (I == Dylibs.end())
50*a2c1cf09SLang Hames     return make_error<StringError>("No dylib for handle " + formatv("{0:x}", H),
51*a2c1cf09SLang Hames                                    inconvertibleErrorCode());
52*a2c1cf09SLang Hames   auto &DL = I->second;
53*a2c1cf09SLang Hames 
54*a2c1cf09SLang Hames   for (const auto &E : L) {
55*a2c1cf09SLang Hames 
56*a2c1cf09SLang Hames     if (E.Name.empty()) {
57*a2c1cf09SLang Hames       if (E.Required)
58*a2c1cf09SLang Hames         return make_error<StringError>("Required address for empty symbol \"\"",
59*a2c1cf09SLang Hames                                        inconvertibleErrorCode());
60*a2c1cf09SLang Hames       else
61*a2c1cf09SLang Hames         Result.push_back(ExecutorAddress());
62*a2c1cf09SLang Hames     } else {
63*a2c1cf09SLang Hames 
64*a2c1cf09SLang Hames       const char *DemangledSymName = E.Name.c_str();
65*a2c1cf09SLang Hames #ifdef __APPLE__
66*a2c1cf09SLang Hames       if (E.Name.front() != '_')
67*a2c1cf09SLang Hames         return make_error<StringError>(Twine("MachO symbol \"") + E.Name +
68*a2c1cf09SLang Hames                                            "\" missing leading '_'",
69*a2c1cf09SLang Hames                                        inconvertibleErrorCode());
70*a2c1cf09SLang Hames       ++DemangledSymName;
71*a2c1cf09SLang Hames #endif
72*a2c1cf09SLang Hames 
73*a2c1cf09SLang Hames       void *Addr = DL.getAddressOfSymbol(DemangledSymName);
74*a2c1cf09SLang Hames       if (!Addr && E.Required)
75*a2c1cf09SLang Hames         return make_error<StringError>(Twine("Missing definition for ") +
76*a2c1cf09SLang Hames                                            DemangledSymName,
77*a2c1cf09SLang Hames                                        inconvertibleErrorCode());
78*a2c1cf09SLang Hames 
79*a2c1cf09SLang Hames       Result.push_back(ExecutorAddress::fromPtr(Addr));
80*a2c1cf09SLang Hames     }
81*a2c1cf09SLang Hames   }
82*a2c1cf09SLang Hames 
83*a2c1cf09SLang Hames   return Result;
84*a2c1cf09SLang Hames }
85*a2c1cf09SLang Hames 
86*a2c1cf09SLang Hames Error SimpleExecutorDylibManager::shutdown() {
87*a2c1cf09SLang Hames 
88*a2c1cf09SLang Hames   DylibsMap DM;
89*a2c1cf09SLang Hames   {
90*a2c1cf09SLang Hames     std::lock_guard<std::mutex> Lock(M);
91*a2c1cf09SLang Hames     std::swap(DM, Dylibs);
92*a2c1cf09SLang Hames   }
93*a2c1cf09SLang Hames 
94*a2c1cf09SLang Hames   // There is no removal of dylibs at the moment, so nothing to do here.
95*a2c1cf09SLang Hames   return Error::success();
96*a2c1cf09SLang Hames }
97*a2c1cf09SLang Hames 
98*a2c1cf09SLang Hames void SimpleExecutorDylibManager::addBootstrapSymbols(
99*a2c1cf09SLang Hames     StringMap<ExecutorAddress> &M) {
100*a2c1cf09SLang Hames   M[rt::SimpleExecutorDylibManagerInstanceName] =
101*a2c1cf09SLang Hames       ExecutorAddress::fromPtr(this);
102*a2c1cf09SLang Hames   M[rt::SimpleExecutorDylibManagerOpenWrapperName] =
103*a2c1cf09SLang Hames       ExecutorAddress::fromPtr(&openWrapper);
104*a2c1cf09SLang Hames   M[rt::SimpleExecutorDylibManagerLookupWrapperName] =
105*a2c1cf09SLang Hames       ExecutorAddress::fromPtr(&lookupWrapper);
106*a2c1cf09SLang Hames }
107*a2c1cf09SLang Hames 
108*a2c1cf09SLang Hames llvm::orc::shared::detail::CWrapperFunctionResult
109*a2c1cf09SLang Hames SimpleExecutorDylibManager::openWrapper(const char *ArgData, size_t ArgSize) {
110*a2c1cf09SLang Hames   return shared::
111*a2c1cf09SLang Hames       WrapperFunction<rt::SPSSimpleExecutorDylibManagerOpenSignature>::handle(
112*a2c1cf09SLang Hames              ArgData, ArgSize,
113*a2c1cf09SLang Hames              shared::makeMethodWrapperHandler(
114*a2c1cf09SLang Hames                  &SimpleExecutorDylibManager::open))
115*a2c1cf09SLang Hames           .release();
116*a2c1cf09SLang Hames }
117*a2c1cf09SLang Hames 
118*a2c1cf09SLang Hames llvm::orc::shared::detail::CWrapperFunctionResult
119*a2c1cf09SLang Hames SimpleExecutorDylibManager::lookupWrapper(const char *ArgData, size_t ArgSize) {
120*a2c1cf09SLang Hames   return shared::
121*a2c1cf09SLang Hames       WrapperFunction<rt::SPSSimpleExecutorDylibManagerLookupSignature>::handle(
122*a2c1cf09SLang Hames              ArgData, ArgSize,
123*a2c1cf09SLang Hames              shared::makeMethodWrapperHandler(
124*a2c1cf09SLang Hames                  &SimpleExecutorDylibManager::lookup))
125*a2c1cf09SLang Hames           .release();
126*a2c1cf09SLang Hames }
127*a2c1cf09SLang Hames 
128*a2c1cf09SLang Hames } // namespace rt_bootstrap
129*a2c1cf09SLang Hames } // end namespace orc
130*a2c1cf09SLang Hames } // end namespace llvm
131