1 //===----- UnwindInfoRegistrationPlugin.cpp - libunwind registration ------===// 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/UnwindInfoRegistrationPlugin.h" 10 11 #include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h" 12 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 13 #include "llvm/IR/Module.h" 14 15 #define DEBUG_TYPE "orc" 16 17 using namespace llvm::jitlink; 18 19 namespace llvm::orc { 20 21 Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>> 22 UnwindInfoRegistrationPlugin::Create(ExecutionSession &ES) { 23 24 ExecutorAddr Register, Deregister; 25 26 auto &EPC = ES.getExecutorProcessControl(); 27 if (auto Err = EPC.getBootstrapSymbols( 28 {{Register, rt_alt::UnwindInfoManagerRegisterActionName}, 29 {Deregister, rt_alt::UnwindInfoManagerDeregisterActionName}})) 30 return std::move(Err); 31 32 return std::make_shared<UnwindInfoRegistrationPlugin>(ES, Register, 33 Deregister); 34 } 35 36 void UnwindInfoRegistrationPlugin::modifyPassConfig( 37 MaterializationResponsibility &MR, LinkGraph &G, 38 PassConfiguration &PassConfig) { 39 40 PassConfig.PostFixupPasses.push_back( 41 [this](LinkGraph &G) { return addUnwindInfoRegistrationActions(G); }); 42 } 43 44 Error UnwindInfoRegistrationPlugin::addUnwindInfoRegistrationActions( 45 LinkGraph &G) { 46 ExecutorAddrRange EHFrameRange, UnwindInfoRange; 47 48 std::vector<Block *> CodeBlocks; 49 50 auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) { 51 if (Sec.empty()) 52 return; 53 54 SecRange.Start = (*Sec.blocks().begin())->getAddress(); 55 for (auto *B : Sec.blocks()) { 56 auto R = B->getRange(); 57 SecRange.Start = std::min(SecRange.Start, R.Start); 58 SecRange.End = std::max(SecRange.End, R.End); 59 for (auto &E : B->edges()) { 60 if (E.getKind() != Edge::KeepAlive || !E.getTarget().isDefined()) 61 continue; 62 auto &TargetBlock = E.getTarget().getBlock(); 63 auto &TargetSection = TargetBlock.getSection(); 64 if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec) 65 CodeBlocks.push_back(&TargetBlock); 66 } 67 } 68 }; 69 70 if (auto *EHFrame = G.findSectionByName(MachOEHFrameSectionName)) 71 ScanUnwindInfoSection(*EHFrame, EHFrameRange); 72 73 if (auto *UnwindInfo = G.findSectionByName(MachOUnwindInfoSectionName)) 74 ScanUnwindInfoSection(*UnwindInfo, UnwindInfoRange); 75 76 if (CodeBlocks.empty()) 77 return Error::success(); 78 79 if ((EHFrameRange == ExecutorAddrRange() && 80 UnwindInfoRange == ExecutorAddrRange())) 81 return Error::success(); 82 83 llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) { 84 return LHS->getAddress() < RHS->getAddress(); 85 }); 86 87 SmallVector<ExecutorAddrRange> CodeRanges; 88 for (auto *B : CodeBlocks) { 89 if (CodeRanges.empty() || CodeRanges.back().End != B->getAddress()) 90 CodeRanges.push_back(B->getRange()); 91 else 92 CodeRanges.back().End = B->getRange().End; 93 } 94 95 ExecutorAddr DSOBase; 96 if (auto *DSOBaseSym = G.findAbsoluteSymbolByName(DSOBaseName)) 97 DSOBase = DSOBaseSym->getAddress(); 98 else if (auto *DSOBaseSym = G.findExternalSymbolByName(DSOBaseName)) 99 DSOBase = DSOBaseSym->getAddress(); 100 else if (auto *DSOBaseSym = G.findDefinedSymbolByName(DSOBaseName)) 101 DSOBase = DSOBaseSym->getAddress(); 102 else 103 return make_error<StringError>("In " + G.getName() + 104 " could not find dso base symbol", 105 inconvertibleErrorCode()); 106 107 using namespace shared; 108 using SPSRegisterArgs = 109 SPSArgList<SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddr, 110 SPSExecutorAddrRange, SPSExecutorAddrRange>; 111 using SPSDeregisterArgs = SPSArgList<SPSSequence<SPSExecutorAddrRange>>; 112 113 G.allocActions().push_back( 114 {cantFail(WrapperFunctionCall::Create<SPSRegisterArgs>( 115 Register, CodeRanges, DSOBase, EHFrameRange, UnwindInfoRange)), 116 cantFail(WrapperFunctionCall::Create<SPSDeregisterArgs>(Deregister, 117 CodeRanges))}); 118 119 return Error::success(); 120 } 121 122 } // namespace llvm::orc 123