blob: 6510976704363a741f0efbb2931718dbb8f2391b [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking ---*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Contains the definition for an RTDyld-based, in-process object linking layer.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
15#define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
16
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/StringMap.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ExecutionEngine/JITSymbol.h"
21#include "llvm/ExecutionEngine/Orc/Core.h"
Andrew Scullcdfcccc2018-10-05 20:58:37 +010022#include "llvm/ExecutionEngine/Orc/Layer.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010023#include "llvm/ExecutionEngine/Orc/Legacy.h"
24#include "llvm/ExecutionEngine/RuntimeDyld.h"
25#include "llvm/Object/ObjectFile.h"
26#include "llvm/Support/Error.h"
27#include <algorithm>
28#include <cassert>
29#include <functional>
30#include <list>
31#include <memory>
32#include <string>
33#include <utility>
34#include <vector>
35
36namespace llvm {
37namespace orc {
38
Andrew Scullcdfcccc2018-10-05 20:58:37 +010039class RTDyldObjectLinkingLayer2 : public ObjectLayer {
40public:
41 /// Functor for receiving object-loaded notifications.
42 using NotifyLoadedFunction =
43 std::function<void(VModuleKey, const object::ObjectFile &Obj,
44 const RuntimeDyld::LoadedObjectInfo &)>;
45
46 /// Functor for receiving finalization notifications.
47 using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
48
49 using GetMemoryManagerFunction =
50 std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>;
51
52 /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
53 /// and NotifyFinalized functors.
54 RTDyldObjectLinkingLayer2(
55 ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
56 NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
57 NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction());
58
59 /// Emit the object.
60 void emit(MaterializationResponsibility R, VModuleKey K,
61 std::unique_ptr<MemoryBuffer> O) override;
62
63 /// Map section addresses for the object associated with the
64 /// VModuleKey K.
65 void mapSectionAddress(VModuleKey K, const void *LocalAddress,
66 JITTargetAddress TargetAddr) const;
67
68 /// Set the 'ProcessAllSections' flag.
69 ///
70 /// If set to true, all sections in each object file will be allocated using
71 /// the memory manager, rather than just the sections required for execution.
72 ///
73 /// This is kludgy, and may be removed in the future.
74 void setProcessAllSections(bool ProcessAllSections) {
75 this->ProcessAllSections = ProcessAllSections;
76 }
77
78private:
79 mutable std::mutex RTDyldLayerMutex;
80 GetMemoryManagerFunction GetMemoryManager;
81 NotifyLoadedFunction NotifyLoaded;
82 NotifyFinalizedFunction NotifyFinalized;
83 bool ProcessAllSections;
84 std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds;
85 std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
86};
87
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010088class RTDyldObjectLinkingLayerBase {
89public:
90 using ObjectPtr = std::unique_ptr<MemoryBuffer>;
91
92protected:
93
Andrew Scullcdfcccc2018-10-05 20:58:37 +010094 /// Holds an object to be allocated/linked as a unit in the JIT.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010095 ///
96 /// An instance of this class will be created for each object added
97 /// via JITObjectLayer::addObject. Deleting the instance (via
98 /// removeObject) frees its memory, removing all symbol definitions that
99 /// had been provided by this instance. Higher level layers are responsible
100 /// for taking any action required to handle the missing symbols.
101 class LinkedObject {
102 public:
103 LinkedObject() = default;
104 LinkedObject(const LinkedObject&) = delete;
105 void operator=(const LinkedObject&) = delete;
106 virtual ~LinkedObject() = default;
107
108 virtual Error finalize() = 0;
109
110 virtual JITSymbol::GetAddressFtor
111 getSymbolMaterializer(std::string Name) = 0;
112
113 virtual void mapSectionAddress(const void *LocalAddress,
114 JITTargetAddress TargetAddr) const = 0;
115
116 JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
117 auto SymEntry = SymbolTable.find(Name);
118 if (SymEntry == SymbolTable.end())
119 return nullptr;
120 if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
121 return nullptr;
122 if (!Finalized)
123 return JITSymbol(getSymbolMaterializer(Name),
124 SymEntry->second.getFlags());
125 return JITSymbol(SymEntry->second);
126 }
127
128 protected:
129 StringMap<JITEvaluatedSymbol> SymbolTable;
130 bool Finalized = false;
131 };
132};
133
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100134/// Bare bones object linking layer.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100135///
136/// This class is intended to be used as the base layer for a JIT. It allows
137/// object files to be loaded into memory, linked, and the addresses of their
138/// symbols queried. All objects added to this layer can see each other's
139/// symbols.
140class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
141public:
142
143 using RTDyldObjectLinkingLayerBase::ObjectPtr;
144
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100145 /// Functor for receiving object-loaded notifications.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100146 using NotifyLoadedFtor =
147 std::function<void(VModuleKey, const object::ObjectFile &Obj,
148 const RuntimeDyld::LoadedObjectInfo &)>;
149
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100150 /// Functor for receiving finalization notifications.
151 using NotifyFinalizedFtor =
152 std::function<void(VModuleKey, const object::ObjectFile &Obj,
153 const RuntimeDyld::LoadedObjectInfo &)>;
154
155 /// Functor for receiving deallocation notifications.
156 using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100157
158private:
159 using OwnedObject = object::OwningBinary<object::ObjectFile>;
160
161 template <typename MemoryManagerPtrT>
162 class ConcreteLinkedObject : public LinkedObject {
163 public:
164 ConcreteLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
165 OwnedObject Obj, MemoryManagerPtrT MemMgr,
166 std::shared_ptr<SymbolResolver> Resolver,
167 bool ProcessAllSections)
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100168 : K(std::move(K)),
169 Parent(Parent),
170 MemMgr(std::move(MemMgr)),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100171 PFC(llvm::make_unique<PreFinalizeContents>(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100172 std::move(Obj), std::move(Resolver),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100173 ProcessAllSections)) {
174 buildInitialSymbolTable(PFC->Obj);
175 }
176
177 ~ConcreteLinkedObject() override {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100178 if (this->Parent.NotifyFreed)
179 this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
180
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100181 MemMgr->deregisterEHFrames();
182 }
183
184 Error finalize() override {
185 assert(PFC && "mapSectionAddress called on finalized LinkedObject");
186
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100187 JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
188 nullptr);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100189 PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
190 PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
191
192 Finalized = true;
193
194 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
195 PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
196
197 // Copy the symbol table out of the RuntimeDyld instance.
198 {
199 auto SymTab = PFC->RTDyld->getSymbolTable();
200 for (auto &KV : SymTab)
201 SymbolTable[KV.first] = KV.second;
202 }
203
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100204 if (Parent.NotifyLoaded)
205 Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100206
207 PFC->RTDyld->finalizeWithMemoryManagerLocking();
208
209 if (PFC->RTDyld->hasError())
210 return make_error<StringError>(PFC->RTDyld->getErrorString(),
211 inconvertibleErrorCode());
212
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100213 if (Parent.NotifyFinalized)
214 Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100215
216 // Release resources.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100217 if (this->Parent.NotifyFreed)
218 ObjForNotify = std::move(PFC->Obj); // needed for callback
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100219 PFC = nullptr;
220 return Error::success();
221 }
222
223 JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
224 return [this, Name]() -> Expected<JITTargetAddress> {
225 // The symbol may be materialized between the creation of this lambda
226 // and its execution, so we need to double check.
227 if (!this->Finalized)
228 if (auto Err = this->finalize())
229 return std::move(Err);
230 return this->getSymbol(Name, false).getAddress();
231 };
232 }
233
234 void mapSectionAddress(const void *LocalAddress,
235 JITTargetAddress TargetAddr) const override {
236 assert(PFC && "mapSectionAddress called on finalized LinkedObject");
237 assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
238 PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
239 }
240
241 private:
242 void buildInitialSymbolTable(const OwnedObject &Obj) {
243 for (auto &Symbol : Obj.getBinary()->symbols()) {
244 if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
245 continue;
246 Expected<StringRef> SymbolName = Symbol.getName();
247 // FIXME: Raise an error for bad symbols.
248 if (!SymbolName) {
249 consumeError(SymbolName.takeError());
250 continue;
251 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100252 // FIXME: Raise an error for bad symbols.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100253 auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100254 if (!Flags) {
255 consumeError(Flags.takeError());
256 continue;
257 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100258 SymbolTable.insert(
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100259 std::make_pair(*SymbolName, JITEvaluatedSymbol(0, *Flags)));
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100260 }
261 }
262
263 // Contains the information needed prior to finalization: the object files,
264 // memory manager, resolver, and flags needed for RuntimeDyld.
265 struct PreFinalizeContents {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100266 PreFinalizeContents(OwnedObject Obj,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100267 std::shared_ptr<SymbolResolver> Resolver,
268 bool ProcessAllSections)
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100269 : Obj(std::move(Obj)),
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100270 Resolver(std::move(Resolver)),
271 ProcessAllSections(ProcessAllSections) {}
272
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100273 OwnedObject Obj;
274 std::shared_ptr<SymbolResolver> Resolver;
275 bool ProcessAllSections;
276 std::unique_ptr<RuntimeDyld> RTDyld;
277 };
278
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100279 VModuleKey K;
280 RTDyldObjectLinkingLayer &Parent;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100281 MemoryManagerPtrT MemMgr;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100282 OwnedObject ObjForNotify;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100283 std::unique_ptr<PreFinalizeContents> PFC;
284 };
285
286 template <typename MemoryManagerPtrT>
287 std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
288 createLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
289 OwnedObject Obj, MemoryManagerPtrT MemMgr,
290 std::shared_ptr<SymbolResolver> Resolver,
291 bool ProcessAllSections) {
292 using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
293 return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
294 std::move(MemMgr), std::move(Resolver),
295 ProcessAllSections);
296 }
297
298public:
299 struct Resources {
300 std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
301 std::shared_ptr<SymbolResolver> Resolver;
302 };
303
304 using ResourcesGetter = std::function<Resources(VModuleKey)>;
305
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100306 /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100307 /// and NotifyFinalized functors.
308 RTDyldObjectLinkingLayer(
309 ExecutionSession &ES, ResourcesGetter GetResources,
310 NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100311 NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
312 NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100313 : ES(ES), GetResources(std::move(GetResources)),
314 NotifyLoaded(std::move(NotifyLoaded)),
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100315 NotifyFinalized(std::move(NotifyFinalized)),
316 NotifyFreed(std::move(NotifyFreed)),
317 ProcessAllSections(false) {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100318 }
319
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100320 /// Set the 'ProcessAllSections' flag.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100321 ///
322 /// If set to true, all sections in each object file will be allocated using
323 /// the memory manager, rather than just the sections required for execution.
324 ///
325 /// This is kludgy, and may be removed in the future.
326 void setProcessAllSections(bool ProcessAllSections) {
327 this->ProcessAllSections = ProcessAllSections;
328 }
329
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100330 /// Add an object to the JIT.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100331 Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
332
333 auto Obj =
334 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
335 if (!Obj)
336 return Obj.takeError();
337
338 assert(!LinkedObjects.count(K) && "VModuleKey already in use");
339
340 auto R = GetResources(K);
341
342 LinkedObjects[K] = createLinkedObject(
343 *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
344 std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
345
346 return Error::success();
347 }
348
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100349 /// Remove the object associated with VModuleKey K.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100350 ///
351 /// All memory allocated for the object will be freed, and the sections and
352 /// symbols it provided will no longer be available. No attempt is made to
353 /// re-emit the missing symbols, and any use of these symbols (directly or
354 /// indirectly) will result in undefined behavior. If dependence tracking is
355 /// required to detect or resolve such issues it should be added at a higher
356 /// layer.
357 Error removeObject(VModuleKey K) {
358 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
359 // How do we invalidate the symbols in H?
360 LinkedObjects.erase(K);
361 return Error::success();
362 }
363
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100364 /// Search for the given named symbol.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100365 /// @param Name The name of the symbol to search for.
366 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
367 /// @return A handle for the given named symbol, if it exists.
368 JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
369 for (auto &KV : LinkedObjects)
370 if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
371 return Sym;
372 else if (auto Err = Sym.takeError())
373 return std::move(Err);
374
375 return nullptr;
376 }
377
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100378 /// Search for the given named symbol in the context of the loaded
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100379 /// object represented by the VModuleKey K.
380 /// @param K The VModuleKey for the object to search in.
381 /// @param Name The name of the symbol to search for.
382 /// @param ExportedSymbolsOnly If true, search only for exported symbols.
383 /// @return A handle for the given named symbol, if it is found in the
384 /// given object.
385 JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
386 bool ExportedSymbolsOnly) {
387 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
388 return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
389 }
390
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100391 /// Map section addresses for the object associated with the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100392 /// VModuleKey K.
393 void mapSectionAddress(VModuleKey K, const void *LocalAddress,
394 JITTargetAddress TargetAddr) {
395 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
396 LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
397 }
398
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100399 /// Immediately emit and finalize the object represented by the given
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100400 /// VModuleKey.
401 /// @param K VModuleKey for object to emit/finalize.
402 Error emitAndFinalize(VModuleKey K) {
403 assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
404 return LinkedObjects[K]->finalize();
405 }
406
407private:
408 ExecutionSession &ES;
409
410 std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
411 ResourcesGetter GetResources;
412 NotifyLoadedFtor NotifyLoaded;
413 NotifyFinalizedFtor NotifyFinalized;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100414 NotifyFreedFtor NotifyFreed;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100415 bool ProcessAllSections = false;
416};
417
418} // end namespace orc
419} // end namespace llvm
420
421#endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H