llvm.org GIT mirror llvm / ab3dba8
[ExecutionEngine] Make RuntimeDyld::MemoryManager responsible for tracking EH frames. RuntimeDyld was previously responsible for tracking allocated EH frames, but it makes more sense to have the RuntimeDyld::MemoryManager track them (since the frames are allocated through the memory manager, and written to memory owned by the memory manager). This patch moves the frame tracking into RTDyldMemoryManager, and changes the deregisterFrames method on RuntimeDyld::MemoryManager from: void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); to: void deregisterEHFrames(); Separating this responsibility will allow ORC to continue to throw the RuntimeDyld instances away post-link (saving a few dozen bytes per lazy function) while properly deregistering frames when modules are unloaded. This patch also updates ORC to call deregisterEHFrames when modules are unloaded. This fixes a bug where an exception that tears down the JIT can then unwind through dangling EH frames that have been deallocated but not deregistered, resulting in UB. For people using SectionMemoryManager this should be pretty much a no-op. For people with custom allocators that override registerEHFrames/deregisterEHFrames, you will now be responsible for tracking allocated EH frames. Reviewed in https://reviews.llvm.org/D32829 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302589 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 3 years ago
18 changed file(s) with 85 addition(s) and 65 deletion(s). Raw diff Collapse all Expand all
171171 return nullptr;
172172 }
173173
174 void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
175 for (auto &BLH : BaseLayerHandles)
176 BaseLayer.removeModuleSet(BLH);
177 }
178
174179 std::unique_ptr ExternalSymbolResolver;
175180 std::unique_ptr> MemMgr;
176181 std::unique_ptr StubsMgr;
203208 CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
204209 CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
205210
211 ~CompileOnDemandLayer() {
212 while (!LogicalDylibs.empty())
213 removeModuleSet(LogicalDylibs.begin());
214 }
215
206216 /// @brief Add a module to the compile-on-demand layer.
207217 template
208218 typename SymbolResolverPtrT>
238248 /// This will remove all modules in the layers below that were derived from
239249 /// the module represented by H.
240250 void removeModuleSet(ModuleSetHandleT H) {
251 H->removeModulesFromBaseLayer(BaseLayer);
241252 LogicalDylibs.erase(H);
242253 }
243254
477488 return 0;
478489 }
479490
491 LD.BaseLayerHandles.push_back(PartH);
492
480493 return CalledAddr;
481494 }
482495
143143
144144 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
145145 size_t Size) override {
146 UnfinalizedEHFrames.push_back(
147 std::make_pair(LoadAddr, static_cast(Size)));
148 }
149
150 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
151 size_t Size) override {
152 auto Err = Client.deregisterEHFrames(LoadAddr, Size);
153 // FIXME: Add error poll.
154 assert(!Err && "Failed to register remote EH frames.");
155 (void)Err;
146 UnfinalizedEHFrames.push_back({LoadAddr, Size});
147 }
148
149 void deregisterEHFrames() override {
150 for (auto &Frame : RegisteredEHFrames) {
151 auto Err = Client.deregisterEHFrames(Frame.Addr, Frame.Size);
152 // FIXME: Add error poll.
153 assert(!Err && "Failed to register remote EH frames.");
154 (void)Err;
155 }
156156 }
157157
158158 void notifyObjectLoaded(RuntimeDyld &Dyld,
319319 Unfinalized.clear();
320320
321321 for (auto &EHFrame : UnfinalizedEHFrames) {
322 if (auto Err = Client.registerEHFrames(EHFrame.first, EHFrame.second)) {
322 if (auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) {
323323 // FIXME: Replace this once finalizeMemory can return an Error.
324324 handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
325325 if (ErrMsg) {
330330 return false;
331331 }
332332 }
333 UnfinalizedEHFrames.clear();
333 RegisteredEHFrames = std::move(UnfinalizedEHFrames);
334 UnfinalizedEHFrames = {};
334335
335336 return false;
336337 }
386387 ResourceIdMgr::ResourceId Id;
387388 std::vector Unmapped;
388389 std::vector Unfinalized;
389 std::vector> UnfinalizedEHFrames;
390
391 struct EHFrame {
392 JITTargetAddress Addr;
393 uint64_t Size;
394 };
395 std::vector UnfinalizedEHFrames;
396 std::vector RegisteredEHFrames;
390397 };
391398
392399 /// Remote indirect stubs manager.
119119 buildInitialSymbolTable(PFC->Objects);
120120 }
121121
122 ~ConcreteLinkedObjectSet() override {
123 MemMgr->deregisterEHFrames();
124 }
125
122126 void setHandle(ObjSetHandleT H) {
123127 PFC->Handle = H;
124128 }
6868 /// Deregister EH frames in the current proces.
6969 static void deregisterEHFramesInProcess(uint8_t *Addr, size_t Size);
7070
71 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
72 registerEHFramesInProcess(Addr, Size);
73 }
74
75 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {
76 deregisterEHFramesInProcess(Addr, Size);
77 }
71 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
72 void deregisterEHFrames() override;
7873
7974 /// This method returns the address of the specified function or variable in
8075 /// the current process.
138133 /// MCJIT or RuntimeDyld. Use getSymbolAddress instead.
139134 virtual void *getPointerToNamedFunction(const std::string &Name,
140135 bool AbortOnFailure = true);
136
137 private:
138 struct EHFrame {
139 uint8_t *Addr;
140 size_t Size;
141 };
142 std::vector EHFrames;
141143 };
142144
143145 // Create wrappers for C Binding types (see CBindingWrapping.h).
149149 /// be the case for local execution) these two values will be the same.
150150 virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
151151 size_t Size) = 0;
152 virtual void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr,
153 size_t Size) = 0;
152 virtual void deregisterEHFrames() = 0;
154153
155154 /// This method is called when object loading is complete and section page
156155 /// permissions can be applied. It is up to the memory manager implementation
9393 return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
9494 }
9595
96 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
97 size_t Size) override {
98 return ClientMM->deregisterEHFrames(Addr, LoadAddr, Size);
96 void deregisterEHFrames() override {
97 return ClientMM->deregisterEHFrames();
9998 }
10099
101100 void notifyObjectLoaded(RuntimeDyld &RTDyld,
132132 }
133133
134134 #endif
135
136 void RTDyldMemoryManager::registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
137 size_t Size) {
138 registerEHFramesInProcess(Addr, Size);
139 EHFrames.push_back({Addr, Size});
140 }
141
142 void RTDyldMemoryManager::deregisterEHFrames() {
143 for (auto &Frame : EHFrames)
144 deregisterEHFramesInProcess(Frame.Addr, Frame.Size);
145 EHFrames.clear();
146 }
135147
136148 static int jit_noop() {
137149 return 0;
7272
7373 void RuntimeDyldImpl::registerEHFrames() {}
7474
75 void RuntimeDyldImpl::deregisterEHFrames() {}
75 void RuntimeDyldImpl::deregisterEHFrames() {
76 MemMgr.deregisterEHFrames();
77 }
7678
7779 #ifndef NDEBUG
7880 static void dumpSectionMemory(const SectionEntry &S, StringRef State) {
220220 uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();
221221 size_t EHFrameSize = Sections[EHFrameSID].getSize();
222222 MemMgr.registerEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
223 RegisteredEHFrameSections.push_back(EHFrameSID);
224223 }
225224 UnregisteredEHFrameSections.clear();
226 }
227
228 void RuntimeDyldELF::deregisterEHFrames() {
229 for (int i = 0, e = RegisteredEHFrameSections.size(); i != e; ++i) {
230 SID EHFrameSID = RegisteredEHFrameSections[i];
231 uint8_t *EHFrameAddr = Sections[EHFrameSID].getAddress();
232 uint64_t EHFrameLoadAddr = Sections[EHFrameSID].getLoadAddress();
233 size_t EHFrameSize = Sections[EHFrameSID].getSize();
234 MemMgr.deregisterEHFrames(EHFrameAddr, EHFrameLoadAddr, EHFrameSize);
235 }
236 RegisteredEHFrameSections.clear();
237225 }
238226
239227 std::unique_ptr
151151 // in a table until we receive a request to register all unregistered
152152 // EH frame sections with the memory manager.
153153 SmallVector UnregisteredEHFrameSections;
154 SmallVector RegisteredEHFrameSections;
155154
156155 // Map between GOT relocation value and corresponding GOT offset
157156 std::map GOTOffsetMap;
179178 StubMap &Stubs) override;
180179 bool isCompatibleFile(const object::ObjectFile &Obj) const override;
181180 void registerEHFrames() override;
182 void deregisterEHFrames() override;
183181 Error finalizeLoad(const ObjectFile &Obj,
184182 ObjSectionToIDMap &SectionMap) override;
185183 };
514514
515515 virtual void registerEHFrames();
516516
517 virtual void deregisterEHFrames();
517 void deregisterEHFrames();
518518
519519 virtual Error finalizeLoad(const ObjectFile &ObjImg,
520520 ObjSectionToIDMap &SectionMap) {
216216 }
217217
218218 void registerEHFrames() override {}
219 void deregisterEHFrames() override {}
220219 };
221220
222221 }
315315 }
316316
317317 void registerEHFrames() override {}
318 void deregisterEHFrames() override {}
319318 };
320319
321320 }
193193 }
194194 UnregisteredEHFrameSections.clear();
195195 }
196 void deregisterEHFrames() override {
197 // Stub
198 }
199196 Error finalizeLoad(const ObjectFile &Obj,
200197 ObjSectionToIDMap &SectionMap) override {
201198 // Look for and record the EH frame section IDs.
117117 MemMgr->registerEHFrames(Addr, LoadAddr, Size);
118118 }
119119
120 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
121 size_t Size) override {
122 MemMgr->deregisterEHFrames(Addr, LoadAddr, Size);
120 void deregisterEHFrames() override {
121 MemMgr->deregisterEHFrames();
123122 }
124123
125124 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
174174
175175 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
176176 size_t Size) override {}
177 void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
178 size_t Size) override {}
177 void deregisterEHFrames() override {}
179178
180179 void preallocateSlab(uint64_t Size) {
181180 std::string Err;
303303 return nullptr;
304304 }
305305 void registerEHFrames(uint8_t *, uint64_t, size_t) override {}
306 void deregisterEHFrames(uint8_t *, uint64_t, size_t) override {}
306 void deregisterEHFrames() override {}
307307 bool finalizeMemory(std::string *) override { return false; }
308308 };
309309
8989 Objs.push_back(OwningObj.getBinary());
9090
9191 bool DebugSectionSeen = false;
92 SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
92 auto SMMW =
93 std::make_shared(DebugSectionSeen);
9394 auto Resolver =
9495 createLambdaResolver(
9596 [](const std::string &Name) {
101102
102103 {
103104 // Test with ProcessAllSections = false (the default).
104 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
105 auto H = ObjLayer.addObjectSet(Objs, SMMW, &*Resolver);
105106 ObjLayer.emitAndFinalize(H);
106107 EXPECT_EQ(DebugSectionSeen, false)
107108 << "Unexpected debug info section";
111112 {
112113 // Test with ProcessAllSections = true.
113114 ObjLayer.setProcessAllSections(true);
114 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
115 auto H = ObjLayer.addObjectSet(Objs, SMMW, &*Resolver);
115116 ObjLayer.emitAndFinalize(H);
116117 EXPECT_EQ(DebugSectionSeen, true)
117118 << "Expected debug info section not seen";
177178 return JITSymbol(nullptr);
178179 });
179180
180 SectionMemoryManagerWrapper SMMW;
181 ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
182 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
181 auto SMMW = std::make_shared();
182 ObjLayer.addObjectSet(std::move(Obj1Set), SMMW, &*Resolver);
183 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), SMMW, &*Resolver);
183184 ObjLayer.emitAndFinalize(H);
184
185 ObjLayer.removeObjectSet(H);
186
185187 // Finalization of module 2 should trigger finalization of module 1.
186188 // Verify that finalize on SMMW is only called once.
187 EXPECT_EQ(SMMW.FinalizationCount, 1)
189 EXPECT_EQ(SMMW->FinalizationCount, 1)
188190 << "Extra call to finalize";
189191 }
190192
237239 std::vector Obj2Set;
238240 Obj2Set.push_back(Obj2.getBinary());
239241
240 SectionMemoryManagerWrapper SMMW;
242 auto SMMW = std::make_shared();
241243 NullResolver NR;
242 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
243 ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
244 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), SMMW, &NR);
245 ObjLayer.addObjectSet(std::move(Obj2Set), SMMW, &NR);
244246 ObjLayer.emitAndFinalize(H);
245
247 ObjLayer.removeObjectSet(H);
248
246249 // Only one call to needsToReserveAllocationSpace should have been made.
247 EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
250 EXPECT_EQ(SMMW->NeedsToReserveAllocationSpaceCount, 1)
248251 << "More than one call to needsToReserveAllocationSpace "
249252 "(multiple unrelated objects loaded prior to finalization)";
250253 }