1 //===------ TargetProcessControl.cpp -- Target 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/TargetProcessControl.h"
10 
11 #include "llvm/ExecutionEngine/Orc/Core.h"
12 #include "llvm/Support/Host.h"
13 #include "llvm/Support/Process.h"
14 
15 #include <mutex>
16 
17 namespace llvm {
18 namespace orc {
19 
~MemoryAccess()20 TargetProcessControl::MemoryAccess::~MemoryAccess() {}
21 
~TargetProcessControl()22 TargetProcessControl::~TargetProcessControl() {}
23 
SelfTargetProcessControl(Triple TT,unsigned PageSize,std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)24 SelfTargetProcessControl::SelfTargetProcessControl(
25     Triple TT, unsigned PageSize,
26     std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
27 
28   OwnedMemMgr = std::move(MemMgr);
29   if (!OwnedMemMgr)
30     OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>();
31 
32   this->TT = std::move(TT);
33   this->PageSize = PageSize;
34   this->MemMgr = OwnedMemMgr.get();
35   this->MemAccess = this;
36   if (this->TT.isOSBinFormatMachO())
37     GlobalManglingPrefix = '_';
38 }
39 
40 Expected<std::unique_ptr<SelfTargetProcessControl>>
Create(std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)41 SelfTargetProcessControl::Create(
42     std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
43   auto PageSize = sys::Process::getPageSize();
44   if (!PageSize)
45     return PageSize.takeError();
46 
47   Triple TT(sys::getProcessTriple());
48 
49   return std::make_unique<SelfTargetProcessControl>(std::move(TT), *PageSize,
50                                                     std::move(MemMgr));
51 }
52 
53 Expected<TargetProcessControl::DylibHandle>
loadDylib(const char * DylibPath)54 SelfTargetProcessControl::loadDylib(const char *DylibPath) {
55   std::string ErrMsg;
56   auto Dylib = std::make_unique<sys::DynamicLibrary>(
57       sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg));
58   if (!Dylib->isValid())
59     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
60   DynamicLibraries.push_back(std::move(Dylib));
61   return pointerToJITTargetAddress(DynamicLibraries.back().get());
62 }
63 
64 Expected<TargetProcessControl::LookupResult>
lookupSymbols(LookupRequest Request)65 SelfTargetProcessControl::lookupSymbols(LookupRequest Request) {
66   LookupResult R;
67 
68   for (auto &Elem : Request) {
69     auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle);
70     assert(llvm::find_if(DynamicLibraries,
71                          [=](const std::unique_ptr<sys::DynamicLibrary> &DL) {
72                            return DL.get() == Dylib;
73                          }) != DynamicLibraries.end() &&
74            "Invalid handle");
75 
76     R.push_back(std::vector<JITTargetAddress>());
77     for (auto &KV : Elem.Symbols) {
78       auto &Sym = KV.first;
79       std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
80                       (*Sym).size() - !!GlobalManglingPrefix);
81       void *Addr = Dylib->getAddressOfSymbol(Tmp.c_str());
82       if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
83         // FIXME: Collect all failing symbols before erroring out.
84         SymbolNameVector MissingSymbols;
85         MissingSymbols.push_back(Sym);
86         return make_error<SymbolsNotFound>(std::move(MissingSymbols));
87       }
88       R.back().push_back(pointerToJITTargetAddress(Addr));
89     }
90   }
91 
92   return R;
93 }
94 
writeUInt8s(ArrayRef<UInt8Write> Ws,WriteResultFn OnWriteComplete)95 void SelfTargetProcessControl::writeUInt8s(ArrayRef<UInt8Write> Ws,
96                                            WriteResultFn OnWriteComplete) {
97   for (auto &W : Ws)
98     *jitTargetAddressToPointer<uint8_t *>(W.Address) = W.Value;
99   OnWriteComplete(Error::success());
100 }
101 
writeUInt16s(ArrayRef<UInt16Write> Ws,WriteResultFn OnWriteComplete)102 void SelfTargetProcessControl::writeUInt16s(ArrayRef<UInt16Write> Ws,
103                                             WriteResultFn OnWriteComplete) {
104   for (auto &W : Ws)
105     *jitTargetAddressToPointer<uint16_t *>(W.Address) = W.Value;
106   OnWriteComplete(Error::success());
107 }
108 
writeUInt32s(ArrayRef<UInt32Write> Ws,WriteResultFn OnWriteComplete)109 void SelfTargetProcessControl::writeUInt32s(ArrayRef<UInt32Write> Ws,
110                                             WriteResultFn OnWriteComplete) {
111   for (auto &W : Ws)
112     *jitTargetAddressToPointer<uint32_t *>(W.Address) = W.Value;
113   OnWriteComplete(Error::success());
114 }
115 
writeUInt64s(ArrayRef<UInt64Write> Ws,WriteResultFn OnWriteComplete)116 void SelfTargetProcessControl::writeUInt64s(ArrayRef<UInt64Write> Ws,
117                                             WriteResultFn OnWriteComplete) {
118   for (auto &W : Ws)
119     *jitTargetAddressToPointer<uint64_t *>(W.Address) = W.Value;
120   OnWriteComplete(Error::success());
121 }
122 
writeBuffers(ArrayRef<BufferWrite> Ws,WriteResultFn OnWriteComplete)123 void SelfTargetProcessControl::writeBuffers(ArrayRef<BufferWrite> Ws,
124                                             WriteResultFn OnWriteComplete) {
125   for (auto &W : Ws)
126     memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
127            W.Buffer.size());
128   OnWriteComplete(Error::success());
129 }
130 
131 } // end namespace orc
132 } // end namespace llvm
133