1 //===---- llvm-jitlink.h - Session and format-specific decls ----*- C++ -*-===//
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 // llvm-jitlink Session class and tool utilities.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_TOOLS_LLVM_JITLINK_LLVM_JITLINK_H
14 #define LLVM_TOOLS_LLVM_JITLINK_LLVM_JITLINK_H
15 
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/ADT/StringSet.h"
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/ExecutionEngine/Orc/Core.h"
20 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
21 #include "llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h"
22 #include "llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h"
23 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
24 #include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
25 #include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
26 #include "llvm/Support/Error.h"
27 #include "llvm/Support/Regex.h"
28 #include "llvm/Support/raw_ostream.h"
29 
30 #include <vector>
31 
32 namespace llvm {
33 
34 struct Session;
35 
36 /// ObjectLinkingLayer with additional support for symbol promotion.
37 class LLVMJITLinkObjectLinkingLayer : public orc::ObjectLinkingLayer {
38 public:
39   using orc::ObjectLinkingLayer::add;
40 
41   LLVMJITLinkObjectLinkingLayer(Session &S,
42                                 jitlink::JITLinkMemoryManager &MemMgr);
43 
44   Error add(orc::ResourceTrackerSP RT,
45             std::unique_ptr<MemoryBuffer> O) override;
46 
47 private:
48   Session &S;
49 };
50 
51 using LLVMJITLinkChannel = orc::shared::FDRawByteChannel;
52 using LLVMJITLinkRPCEndpoint =
53     orc::shared::MultiThreadedRPCEndpoint<LLVMJITLinkChannel>;
54 using LLVMJITLinkRemoteMemoryAccess =
55     orc::OrcRPCTPCMemoryAccess<LLVMJITLinkRPCEndpoint>;
56 
57 class LLVMJITLinkRemoteTargetProcessControl
58     : public orc::OrcRPCTargetProcessControlBase<LLVMJITLinkRPCEndpoint> {
59 public:
60   using BaseT = orc::OrcRPCTargetProcessControlBase<LLVMJITLinkRPCEndpoint>;
61   static Expected<std::unique_ptr<TargetProcessControl>> LaunchExecutor();
62 
63   static Expected<std::unique_ptr<TargetProcessControl>> ConnectToExecutor();
64 
65   Error disconnect() override;
66 
67 private:
68   using LLVMJITLinkRemoteMemoryAccess =
69       orc::OrcRPCTPCMemoryAccess<LLVMJITLinkRemoteTargetProcessControl>;
70 
71   using LLVMJITLinkRemoteMemoryManager =
72       orc::OrcRPCTPCJITLinkMemoryManager<LLVMJITLinkRemoteTargetProcessControl>;
73 
LLVMJITLinkRemoteTargetProcessControl(std::shared_ptr<orc::SymbolStringPool> SSP,std::unique_ptr<LLVMJITLinkChannel> Channel,std::unique_ptr<LLVMJITLinkRPCEndpoint> Endpoint,ErrorReporter ReportError,Error & Err)74   LLVMJITLinkRemoteTargetProcessControl(
75       std::shared_ptr<orc::SymbolStringPool> SSP,
76       std::unique_ptr<LLVMJITLinkChannel> Channel,
77       std::unique_ptr<LLVMJITLinkRPCEndpoint> Endpoint,
78       ErrorReporter ReportError, Error &Err)
79       : BaseT(std::move(SSP), *Endpoint, std::move(ReportError)),
80         Channel(std::move(Channel)), Endpoint(std::move(Endpoint)) {
81     ErrorAsOutParameter _(&Err);
82 
83     ListenerThread = std::thread([&]() {
84       while (!Finished) {
85         if (auto Err = this->Endpoint->handleOne()) {
86           reportError(std::move(Err));
87           return;
88         }
89       }
90     });
91 
92     if (auto Err2 = initializeORCRPCTPCBase()) {
93       Err = joinErrors(std::move(Err2), disconnect());
94       return;
95     }
96 
97     OwnedMemAccess = std::make_unique<LLVMJITLinkRemoteMemoryAccess>(*this);
98     MemAccess = OwnedMemAccess.get();
99     OwnedMemMgr = std::make_unique<LLVMJITLinkRemoteMemoryManager>(*this);
100     MemMgr = OwnedMemMgr.get();
101   }
102 
103   std::unique_ptr<LLVMJITLinkChannel> Channel;
104   std::unique_ptr<LLVMJITLinkRPCEndpoint> Endpoint;
105   std::unique_ptr<TargetProcessControl::MemoryAccess> OwnedMemAccess;
106   std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
107   std::atomic<bool> Finished{false};
108   std::thread ListenerThread;
109 };
110 
111 struct Session {
112   std::unique_ptr<orc::TargetProcessControl> TPC;
113   orc::ExecutionSession ES;
114   orc::JITDylib *MainJD;
115   LLVMJITLinkObjectLinkingLayer ObjLayer;
116   std::vector<orc::JITDylib *> JDSearchOrder;
117 
118   ~Session();
119 
120   static Expected<std::unique_ptr<Session>> Create(Triple TT);
121   void dumpSessionInfo(raw_ostream &OS);
122   void modifyPassConfig(const Triple &FTT,
123                         jitlink::PassConfiguration &PassConfig);
124 
125   using MemoryRegionInfo = RuntimeDyldChecker::MemoryRegionInfo;
126 
127   struct FileInfo {
128     StringMap<MemoryRegionInfo> SectionInfos;
129     StringMap<MemoryRegionInfo> StubInfos;
130     StringMap<MemoryRegionInfo> GOTEntryInfos;
131   };
132 
133   using SymbolInfoMap = StringMap<MemoryRegionInfo>;
134   using FileInfoMap = StringMap<FileInfo>;
135 
136   Expected<FileInfo &> findFileInfo(StringRef FileName);
137   Expected<MemoryRegionInfo &> findSectionInfo(StringRef FileName,
138                                                StringRef SectionName);
139   Expected<MemoryRegionInfo &> findStubInfo(StringRef FileName,
140                                             StringRef TargetName);
141   Expected<MemoryRegionInfo &> findGOTEntryInfo(StringRef FileName,
142                                                 StringRef TargetName);
143 
144   bool isSymbolRegistered(StringRef Name);
145   Expected<MemoryRegionInfo &> findSymbolInfo(StringRef SymbolName,
146                                               Twine ErrorMsgStem);
147 
148   SymbolInfoMap SymbolInfos;
149   FileInfoMap FileInfos;
150   uint64_t SizeBeforePruning = 0;
151   uint64_t SizeAfterFixups = 0;
152 
153   StringSet<> HarnessFiles;
154   StringSet<> HarnessExternals;
155   StringSet<> HarnessDefinitions;
156   DenseMap<StringRef, StringRef> CanonicalWeakDefs;
157 
158 private:
159   Session(std::unique_ptr<orc::TargetProcessControl> TPC, Error &Err);
160 };
161 
162 /// Record symbols, GOT entries, stubs, and sections for ELF file.
163 Error registerELFGraphInfo(Session &S, jitlink::LinkGraph &G);
164 
165 /// Record symbols, GOT entries, stubs, and sections for MachO file.
166 Error registerMachOGraphInfo(Session &S, jitlink::LinkGraph &G);
167 
168 } // end namespace llvm
169 
170 #endif // LLVM_TOOLS_LLVM_JITLINK_LLVM_JITLINK_H
171