xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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>>
Create(ExecutionSession & ES)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 
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)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 
addUnwindInfoRegistrationActions(LinkGraph & G)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