xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp (revision 2ed24e28d1d95c62cc37ca3534d4d33360b4cef2)
1  //===---- ExecutorProcessControl.cpp -- Executor process control APIs -----===//
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  #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
10  
11  #include "llvm/ExecutionEngine/Orc/Core.h"
12  #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
13  #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
14  #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
15  #include "llvm/Support/FormatVariadic.h"
16  #include "llvm/Support/Process.h"
17  #include "llvm/TargetParser/Host.h"
18  
19  #define DEBUG_TYPE "orc"
20  
21  namespace llvm {
22  namespace orc {
23  
24  ExecutorProcessControl::MemoryAccess::~MemoryAccess() = default;
25  
26  ExecutorProcessControl::~ExecutorProcessControl() = default;
27  
28  SelfExecutorProcessControl::SelfExecutorProcessControl(
29      std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
30      Triple TargetTriple, unsigned PageSize,
31      std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
32      : ExecutorProcessControl(std::move(SSP), std::move(D)),
33        InProcessMemoryAccess(TargetTriple.isArch64Bit()) {
34  
35    OwnedMemMgr = std::move(MemMgr);
36    if (!OwnedMemMgr)
37      OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(
38          sys::Process::getPageSizeEstimate());
39  
40    this->TargetTriple = std::move(TargetTriple);
41    this->PageSize = PageSize;
42    this->MemMgr = OwnedMemMgr.get();
43    this->MemAccess = this;
44    this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager),
45                 ExecutorAddr::fromPtr(this)};
46    if (this->TargetTriple.isOSBinFormatMachO())
47      GlobalManglingPrefix = '_';
48  
49    this->BootstrapSymbols[rt::RegisterEHFrameSectionWrapperName] =
50        ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper);
51    this->BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] =
52        ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);
53  }
54  
55  Expected<std::unique_ptr<SelfExecutorProcessControl>>
56  SelfExecutorProcessControl::Create(
57      std::shared_ptr<SymbolStringPool> SSP,
58      std::unique_ptr<TaskDispatcher> D,
59      std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
60  
61    if (!SSP)
62      SSP = std::make_shared<SymbolStringPool>();
63  
64    if (!D)
65      D = std::make_unique<InPlaceTaskDispatcher>();
66  
67    auto PageSize = sys::Process::getPageSize();
68    if (!PageSize)
69      return PageSize.takeError();
70  
71    Triple TT(sys::getProcessTriple());
72  
73    return std::make_unique<SelfExecutorProcessControl>(
74        std::move(SSP), std::move(D), std::move(TT), *PageSize,
75        std::move(MemMgr));
76  }
77  
78  Expected<tpctypes::DylibHandle>
79  SelfExecutorProcessControl::loadDylib(const char *DylibPath) {
80    std::string ErrMsg;
81    auto Dylib = sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg);
82    if (!Dylib.isValid())
83      return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
84    return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle());
85  }
86  
87  void SelfExecutorProcessControl::lookupSymbolsAsync(
88      ArrayRef<LookupRequest> Request,
89      ExecutorProcessControl::SymbolLookupCompleteFn Complete) {
90    std::vector<tpctypes::LookupResult> R;
91  
92    for (auto &Elem : Request) {
93      sys::DynamicLibrary Dylib(Elem.Handle.toPtr<void *>());
94      R.push_back(std::vector<ExecutorSymbolDef>());
95      for (auto &KV : Elem.Symbols) {
96        auto &Sym = KV.first;
97        std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
98                        (*Sym).size() - !!GlobalManglingPrefix);
99        void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str());
100        if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
101          // FIXME: Collect all failing symbols before erroring out.
102          SymbolNameVector MissingSymbols;
103          MissingSymbols.push_back(Sym);
104          return Complete(
105              make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)));
106        }
107        // FIXME: determine accurate JITSymbolFlags.
108        R.back().push_back(
109            {ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
110      }
111    }
112  
113    Complete(std::move(R));
114  }
115  
116  Expected<int32_t>
117  SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr,
118                                        ArrayRef<std::string> Args) {
119    using MainTy = int (*)(int, char *[]);
120    return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);
121  }
122  
123  Expected<int32_t>
124  SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
125    using VoidTy = int (*)();
126    return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());
127  }
128  
129  Expected<int32_t>
130  SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) {
131    using IntTy = int (*)(int);
132    return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);
133  }
134  
135  void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr,
136                                                    IncomingWFRHandler SendResult,
137                                                    ArrayRef<char> ArgBuffer) {
138    using WrapperFnTy =
139        shared::CWrapperFunctionResult (*)(const char *Data, size_t Size);
140    auto *WrapperFn = WrapperFnAddr.toPtr<WrapperFnTy>();
141    SendResult(WrapperFn(ArgBuffer.data(), ArgBuffer.size()));
142  }
143  
144  Error SelfExecutorProcessControl::disconnect() {
145    D->shutdown();
146    return Error::success();
147  }
148  
149  void InProcessMemoryAccess::writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
150                                               WriteResultFn OnWriteComplete) {
151    for (auto &W : Ws)
152      *W.Addr.toPtr<uint8_t *>() = W.Value;
153    OnWriteComplete(Error::success());
154  }
155  
156  void InProcessMemoryAccess::writeUInt16sAsync(
157      ArrayRef<tpctypes::UInt16Write> Ws, WriteResultFn OnWriteComplete) {
158    for (auto &W : Ws)
159      *W.Addr.toPtr<uint16_t *>() = W.Value;
160    OnWriteComplete(Error::success());
161  }
162  
163  void InProcessMemoryAccess::writeUInt32sAsync(
164      ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) {
165    for (auto &W : Ws)
166      *W.Addr.toPtr<uint32_t *>() = W.Value;
167    OnWriteComplete(Error::success());
168  }
169  
170  void InProcessMemoryAccess::writeUInt64sAsync(
171      ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) {
172    for (auto &W : Ws)
173      *W.Addr.toPtr<uint64_t *>() = W.Value;
174    OnWriteComplete(Error::success());
175  }
176  
177  void InProcessMemoryAccess::writeBuffersAsync(
178      ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) {
179    for (auto &W : Ws)
180      memcpy(W.Addr.toPtr<char *>(), W.Buffer.data(), W.Buffer.size());
181    OnWriteComplete(Error::success());
182  }
183  
184  void InProcessMemoryAccess::writePointersAsync(
185      ArrayRef<tpctypes::PointerWrite> Ws, WriteResultFn OnWriteComplete) {
186    if (IsArch64Bit) {
187      for (auto &W : Ws)
188        *W.Addr.toPtr<uint64_t *>() = W.Value.getValue();
189    } else {
190      for (auto &W : Ws)
191        *W.Addr.toPtr<uint32_t *>() = static_cast<uint32_t>(W.Value.getValue());
192    }
193  
194    OnWriteComplete(Error::success());
195  }
196  
197  shared::CWrapperFunctionResult
198  SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
199      void *Ctx, const void *FnTag, const char *Data, size_t Size) {
200  
201    LLVM_DEBUG({
202      dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size
203             << " byte payload.\n";
204    });
205  
206    std::promise<shared::WrapperFunctionResult> ResultP;
207    auto ResultF = ResultP.get_future();
208    static_cast<SelfExecutorProcessControl *>(Ctx)
209        ->getExecutionSession()
210        .runJITDispatchHandler(
211            [ResultP = std::move(ResultP)](
212                shared::WrapperFunctionResult Result) mutable {
213              ResultP.set_value(std::move(Result));
214            },
215            ExecutorAddr::fromPtr(FnTag), {Data, Size});
216  
217    return ResultF.get().release();
218  }
219  
220  } // end namespace orc
221  } // end namespace llvm
222