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