xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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