123 lines · cpp
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-exception6//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 17using namespace llvm::jitlink;18 19namespace llvm::orc {20 21Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>22UnwindInfoRegistrationPlugin::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 36void 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 44Error 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 else92 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 else103 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::orc123