llvm.org GIT mirror llvm / 357f4e4
[ORC] Add a 'plugin' interface to ObjectLinkingLayer for events/configuration. ObjectLinkingLayer::Plugin provides event notifications when objects are loaded, emitted, and removed. It also provides a modifyPassConfig callback that allows plugins to modify the JITLink pass configuration. This patch moves eh-frame registration into its own plugin, and teaches llvm-jitlink to only add that plugin when performing execution runs on non-Windows platforms. This should allow us to re-enable the test case that was removed in r359198. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359357 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 1 year, 6 months ago
6 changed file(s) with 247 addition(s) and 108 deletion(s). Raw diff Collapse all Expand all
2626 /// Deregisters all FDEs in the given eh-frame section with the current process.
2727 Error deregisterEHFrameSection(const void *EHFrameSectionAddr);
2828
29 using StoreFrameAddressFunction = std::function;
30
2931 /// Creates a pass that records the address of the EH frame section. If no
3032 /// eh-frame section is found, it will set EHFrameAddr to zero.
3133 ///
3234 /// Authors of JITLinkContexts can use this function to register a post-fixup
3335 /// pass that records the address of the eh-frame section. This address can
3436 /// be used after finalization to register and deregister the frame.
35 AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
36 JITTargetAddress &EHFrameAddr);
37 AtomGraphPassFunction
38 createEHFrameRecorderPass(const Triple &TT,
39 StoreFrameAddressFunction StoreFrameAddress);
3740
3841 } // end namespace jitlink
3942 } // end namespace llvm
4040
4141 class ObjectLinkingLayerJITLinkContext;
4242
43 /// An ObjectLayer implementation built on JITLink.
44 ///
45 /// Clients can use this class to add relocatable object files to an
46 /// ExecutionSession, and it typically serves as the base layer (underneath
47 /// a compiling layer like IRCompileLayer) for the rest of the JIT.
4348 class ObjectLinkingLayer : public ObjectLayer {
4449 friend class ObjectLinkingLayerJITLinkContext;
4550
4651 public:
47 /// Function object for receiving object-loaded notifications.
48 using NotifyLoadedFunction = std::function;
49
50 /// Function object for receiving finalization notifications.
51 using NotifyEmittedFunction = std::function;
52
53 /// Function object for modifying PassConfiguration objects.
54 using ModifyPassConfigFunction =
55 std::function;
52 /// Plugin instances can be added to the ObjectLinkingLayer to receive
53 /// callbacks when code is loaded or emitted, and when JITLink is being
54 /// configured.
55 class Plugin {
56 public:
57 virtual ~Plugin();
58 virtual void modifyPassConfig(MaterializationResponsibility &MR,
59 const Triple &TT,
60 jitlink::PassConfiguration &Config) {}
61 virtual void notifyLoaded(MaterializationResponsibility &MR) {}
62 virtual Error notifyEmitted(MaterializationResponsibility &MR) {
63 return Error::success();
64 }
65 virtual Error notifyRemovingModule(VModuleKey K) {
66 return Error::success();
67 }
68 virtual Error notifyRemovingAllModules() { return Error::success(); }
69 };
5670
5771 /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
58 /// and NotifyEmitted functors.
59 ObjectLinkingLayer(
60 ExecutionSession &ES, jitlink::JITLinkMemoryManager &MemMgr,
61 NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
62 NotifyEmittedFunction NotifyEmitted = NotifyEmittedFunction(),
63 ModifyPassConfigFunction ModifyPassConfig = ModifyPassConfigFunction());
72 /// and NotifyEmitted functors.
73 ObjectLinkingLayer(ExecutionSession &ES,
74 jitlink::JITLinkMemoryManager &MemMgr);
75
76 /// Destruct an ObjectLinkingLayer.
77 ~ObjectLinkingLayer();
78
79 /// Add a pass-config modifier.
80 ObjectLinkingLayer &addPlugin(std::unique_ptr P) {
81 std::lock_guard Lock(LayerMutex);
82 Plugins.push_back(std::move(P));
83 return *this;
84 }
6485
6586 /// Emit the object.
6687 void emit(MaterializationResponsibility R,
100121 private:
101122 using AllocPtr = std::unique_ptr;
102123
103 class ObjectResources {
104 public:
105 ObjectResources() = default;
106 ObjectResources(AllocPtr Alloc, JITTargetAddress EHFrameAddr);
107 ObjectResources(ObjectResources &&Other);
108 ObjectResources &operator=(ObjectResources &&Other);
109 ~ObjectResources();
124 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
125 jitlink::PassConfiguration &PassConfig);
126 void notifyLoaded(MaterializationResponsibility &MR);
127 Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
110128
111 private:
112 AllocPtr Alloc;
113 JITTargetAddress EHFrameAddr = 0;
114 };
115
116 void notifyFinalized(ObjectResources OR) {
117 ObjResources.push_back(std::move(OR));
118 }
129 Error removeModule(VModuleKey K);
130 Error removeAllModules();
119131
120132 mutable std::mutex LayerMutex;
121133 jitlink::JITLinkMemoryManager &MemMgr;
122 NotifyLoadedFunction NotifyLoaded;
123 NotifyEmittedFunction NotifyEmitted;
124 ModifyPassConfigFunction ModifyPassConfig;
125134 bool OverrideObjectFlags = false;
126135 bool AutoClaimObjectSymbols = false;
127 std::vector ObjResources;
136 DenseMap TrackedAllocs;
137 std::vector UntrackedAllocs;
138 std::vector> Plugins;
139 };
140
141 class LocalEHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
142 public:
143 Error notifyEmitted(MaterializationResponsibility &MR) override;
144 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
145 jitlink::PassConfiguration &PassConfig) override;
146 Error notifyRemovingModule(VModuleKey K) override;
147 Error notifyRemovingAllModules() override;
148
149 private:
150 DenseMap InProcessLinks;
151 DenseMap TrackedEHFrameAddrs;
152 std::vector UntrackedEHFrameAddrs;
128153 };
129154
130155 } // end namespace orc
506506 #endif
507507 }
508508
509 AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
510 JITTargetAddress &EHFrameAddr) {
509 AtomGraphPassFunction
510 createEHFrameRecorderPass(const Triple &TT,
511 StoreFrameAddressFunction StoreFrameAddress) {
511512 const char *EHFrameSectionName = nullptr;
512513 if (TT.getObjectFormat() == Triple::MachO)
513514 EHFrameSectionName = "__eh_frame";
515516 EHFrameSectionName = ".eh_frame";
516517
517518 auto RecordEHFrame = [EHFrameSectionName,
518 &EHFrameAddr](AtomGraph &G) -> Error {
519 StoreFrameAddress](AtomGraph &G) -> Error {
519520 // Search for a non-empty eh-frame and record the address of the first atom
520521 // in it.
521522 JITTargetAddress Addr = 0;
528529 break;
529530 }
530531
531 EHFrameAddr = Addr;
532 StoreFrameAddress(Addr);
532533 return Error::success();
533534 };
534535
132132
133133 MR.resolve(InternedResult);
134134
135 if (Layer.NotifyLoaded)
136 Layer.NotifyLoaded(MR.getVModuleKey());
135 Layer.notifyLoaded(MR);
137136 }
138137
139138 void notifyFinalized(
140139 std::unique_ptr A) override {
141140
142 if (EHFrameAddr) {
143 // If there is an eh-frame then try to register it.
144 if (auto Err = registerEHFrameSection((void *)EHFrameAddr)) {
145 Layer.getExecutionSession().reportError(std::move(Err));
146 MR.failMaterialization();
147 return;
148 }
141 if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
142 Layer.getExecutionSession().reportError(std::move(Err));
143 MR.failMaterialization();
144
145 return;
149146 }
150
151147 MR.emit();
152 Layer.notifyFinalized(
153 ObjectLinkingLayer::ObjectResources(std::move(A), EHFrameAddr));
154148 }
155149
156150 AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
165159 Config.PostPrunePasses.push_back(
166160 [this](AtomGraph &G) { return computeNamedSymbolDependencies(G); });
167161
168 Config.PostFixupPasses.push_back(
169 createEHFrameRecorderPass(TT, EHFrameAddr));
170
171 if (Layer.ModifyPassConfig)
172 Layer.ModifyPassConfig(TT, Config);
162 Layer.modifyPassConfig(MR, TT, Config);
173163
174164 return Error::success();
175165 }
327317 MaterializationResponsibility MR;
328318 std::unique_ptr ObjBuffer;
329319 DenseMap NamedSymbolDeps;
330 JITTargetAddress EHFrameAddr = 0;
331320 };
332321
333 ObjectLinkingLayer::ObjectLinkingLayer(
334 ExecutionSession &ES, JITLinkMemoryManager &MemMgr,
335 NotifyLoadedFunction NotifyLoaded, NotifyEmittedFunction NotifyEmitted,
336 ModifyPassConfigFunction ModifyPassConfig)
337 : ObjectLayer(ES), MemMgr(MemMgr), NotifyLoaded(std::move(NotifyLoaded)),
338 NotifyEmitted(std::move(NotifyEmitted)),
339 ModifyPassConfig(std::move(ModifyPassConfig)) {}
322 ObjectLinkingLayer::Plugin::~Plugin() {}
323
324 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
325 JITLinkMemoryManager &MemMgr)
326 : ObjectLayer(ES), MemMgr(MemMgr) {}
327
328 ObjectLinkingLayer::~ObjectLinkingLayer() {
329 if (auto Err = removeAllModules())
330 getExecutionSession().reportError(std::move(Err));
331 }
340332
341333 void ObjectLinkingLayer::emit(MaterializationResponsibility R,
342334 std::unique_ptr O) {
345337 *this, std::move(R), std::move(O)));
346338 }
347339
348 ObjectLinkingLayer::ObjectResources::ObjectResources(
349 AllocPtr Alloc, JITTargetAddress EHFrameAddr)
350 : Alloc(std::move(Alloc)), EHFrameAddr(EHFrameAddr) {}
351
352 ObjectLinkingLayer::ObjectResources::ObjectResources(ObjectResources &&Other)
353 : Alloc(std::move(Other.Alloc)), EHFrameAddr(Other.EHFrameAddr) {
354 Other.EHFrameAddr = 0;
355 }
356
357 ObjectLinkingLayer::ObjectResources &
358 ObjectLinkingLayer::ObjectResources::operator=(ObjectResources &&Other) {
359 std::swap(Alloc, Other.Alloc);
360 std::swap(EHFrameAddr, Other.EHFrameAddr);
361 return *this;
362 }
363
364 ObjectLinkingLayer::ObjectResources::~ObjectResources() {
365 const char *ErrBanner =
366 "ObjectLinkingLayer received error deallocating object resources:";
367
368 assert((EHFrameAddr == 0 || Alloc) &&
369 "Non-null EHFrameAddr must have an associated allocation");
370
371 if (EHFrameAddr)
372 if (auto Err = deregisterEHFrameSection((void *)EHFrameAddr))
373 logAllUnhandledErrors(std::move(Err), llvm::errs(), ErrBanner);
374
375 if (Alloc)
376 if (auto Err = Alloc->deallocate())
377 logAllUnhandledErrors(std::move(Err), llvm::errs(), ErrBanner);
340 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
341 const Triple &TT,
342 PassConfiguration &PassConfig) {
343 for (auto &P : Plugins)
344 P->modifyPassConfig(MR, TT, PassConfig);
345 }
346
347 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
348 for (auto &P : Plugins)
349 P->notifyLoaded(MR);
350 }
351
352 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
353 AllocPtr Alloc) {
354 Error Err = Error::success();
355 for (auto &P : Plugins)
356 Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
357
358 if (Err)
359 return Err;
360
361 {
362 std::lock_guard Lock(LayerMutex);
363 UntrackedAllocs.push_back(std::move(Alloc));
364 }
365
366 return Error::success();
367 }
368
369 Error ObjectLinkingLayer::removeModule(VModuleKey K) {
370 Error Err = Error::success();
371
372 for (auto &P : Plugins)
373 Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
374
375 AllocPtr Alloc;
376
377 {
378 std::lock_guard Lock(LayerMutex);
379 auto AllocItr = TrackedAllocs.find(K);
380 Alloc = std::move(AllocItr->second);
381 TrackedAllocs.erase(AllocItr);
382 }
383
384 assert(Alloc && "No allocation for key K");
385
386 return joinErrors(std::move(Err), Alloc->deallocate());
387 }
388
389 Error ObjectLinkingLayer::removeAllModules() {
390
391 Error Err = Error::success();
392
393 for (auto &P : Plugins)
394 Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
395
396 std::vector Allocs;
397 {
398 std::lock_guard Lock(LayerMutex);
399 Allocs = std::move(UntrackedAllocs);
400
401 for (auto &KV : TrackedAllocs)
402 Allocs.push_back(std::move(KV.second));
403
404 TrackedAllocs.clear();
405 }
406
407 while (!Allocs.empty()) {
408 Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
409 Allocs.pop_back();
410 }
411
412 return Err;
413 }
414
415 void LocalEHFrameRegistrationPlugin::modifyPassConfig(
416 MaterializationResponsibility &MR, const Triple &TT,
417 PassConfiguration &PassConfig) {
418 assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
419
420 PassConfig.PostFixupPasses.push_back(
421 createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
422 if (Addr)
423 InProcessLinks[&MR] = jitTargetAddressToPointer(Addr);
424 }));
425 }
426
427 Error LocalEHFrameRegistrationPlugin::notifyEmitted(
428 MaterializationResponsibility &MR) {
429
430 auto EHFrameAddrItr = InProcessLinks.find(&MR);
431 if (EHFrameAddrItr == InProcessLinks.end())
432 return Error::success();
433
434 const void *EHFrameAddr = EHFrameAddrItr->second;
435 assert(EHFrameAddr && "eh-frame addr to register can not be null");
436
437 InProcessLinks.erase(EHFrameAddrItr);
438 if (auto Key = MR.getVModuleKey())
439 TrackedEHFrameAddrs[Key] = EHFrameAddr;
440 else
441 UntrackedEHFrameAddrs.push_back(EHFrameAddr);
442
443 return registerEHFrameSection(EHFrameAddr);
444 }
445
446 Error LocalEHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
447 auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
448 if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
449 return Error::success();
450
451 const void *EHFrameAddr = EHFrameAddrItr->second;
452 assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
453
454 TrackedEHFrameAddrs.erase(EHFrameAddrItr);
455
456 return deregisterEHFrameSection(EHFrameAddr);
457 }
458
459 Error LocalEHFrameRegistrationPlugin::notifyRemovingAllModules() {
460
461 std::vector EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
462 EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
463
464 for (auto &KV : TrackedEHFrameAddrs)
465 EHFrameAddrs.push_back(KV.second);
466
467 TrackedEHFrameAddrs.clear();
468
469 Error Err = Error::success();
470
471 while (!EHFrameAddrs.empty()) {
472 const void *EHFrameAddr = EHFrameAddrs.back();
473 assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
474 EHFrameAddrs.pop_back();
475 Err = joinErrors(std::move(Err), deregisterEHFrameSection(EHFrameAddr));
476 }
477
478 return Err;
378479 }
379480
380481 } // End namespace orc.
None # RUN: llvm-jitlink -noexec %S/Inputs/MachO_x86-64_ehframe.o
1 #
2 # FIXME: Produces these errors:
3 # JIT session error: Symbols not found: { __ZTIi, ___gxx_personality_v0 }
4 # llvm-jitlink.exe: Failed to materialize symbols: { biz, _main, baz }
5 # XFAIL: windows-msvc
0 # RUN: llvm-jitlink -noexec -define-abs __ZTIi=0x1 -define-abs ___gxx_personality_v0=0x2 %S/Inputs/MachO_x86-64_ehframe.o
61 #
72 # Perform a no-exec link of MachO_x86-64_ehframe and verify that it does not
83 # generate any errors despite the last FDE referring to the first CIE (rather
213213 }
214214 }
215215
216 Session::Session(Triple TT)
217 : ObjLayer(ES, MemMgr, ObjectLinkingLayer::NotifyLoadedFunction(),
218 ObjectLinkingLayer::NotifyEmittedFunction(),
219 [this](const Triple &TT, PassConfiguration &PassConfig) {
220 modifyPassConfig(TT, PassConfig);
221 }),
222 TT(std::move(TT)) {}
216 Session::Session(Triple TT) : ObjLayer(ES, MemMgr), TT(std::move(TT)) {
217
218 /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
219 /// Session.
220 class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {
221 public:
222 JITLinkSessionPlugin(Session &S) : S(S) {}
223 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
224 PassConfiguration &PassConfig) {
225 S.modifyPassConfig(TT, PassConfig);
226 }
227
228 private:
229 Session &S;
230 };
231
232 if (!NoExec && !TT.isOSWindows())
233 ObjLayer.addPlugin(llvm::make_unique());
234
235 ObjLayer.addPlugin(llvm::make_unique(*this));
236 }
223237
224238 void Session::dumpSessionInfo(raw_ostream &OS) {
225239 OS << "Registered addresses:\n" << SymbolInfos << FileInfos;