1//===------- UnwindInfoManager.cpp - Register unwind info sections --------===//
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/TargetProcess/UnwindInfoManager.h"
10#include "llvm/ExecutionEngine/Orc/Shared/Mangler.h"
11#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
13#include "llvm/TargetParser/Host.h"
14#include "llvm/TargetParser/Triple.h"
15
16#ifdef __APPLE__
17#include <dlfcn.h>
18#endif // __APPLE__
19
20#define DEBUG_TYPE "orc"
21
22using namespace llvm;
23using namespace llvm::orc;
24using namespace llvm::orc::shared;
25
26static orc::shared::CWrapperFunctionBuffer
27llvm_orc_rt_alt_UnwindInfoManager_register(const char *ArgData,
28 size_t ArgSize) {
29 using SPSSig = SPSError(SPSSequence<SPSExecutorAddrRange>, SPSExecutorAddr,
30 SPSExecutorAddrRange, SPSExecutorAddrRange);
31
32 return WrapperFunction<SPSSig>::handle(
33 ArgData, ArgSize,
34 Handler: [](std::vector<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase,
35 ExecutorAddrRange DWARFRange,
36 ExecutorAddrRange CompactUnwindRange) {
37 return UnwindInfoManager::registerSections(
38 CodeRanges, DSOBase, DWARFEHFrame: DWARFRange, CompactUnwind: CompactUnwindRange);
39 })
40 .release();
41}
42
43static orc::shared::CWrapperFunctionBuffer
44llvm_orc_rt_alt_UnwindInfoManager_deregister(const char *ArgData,
45 size_t ArgSize) {
46 using SPSSig = SPSError(SPSSequence<SPSExecutorAddrRange>);
47
48 return WrapperFunction<SPSSig>::handle(
49 ArgData, ArgSize,
50 Handler: [](std::vector<ExecutorAddrRange> CodeRanges) {
51 return UnwindInfoManager::deregisterSections(CodeRanges);
52 })
53 .release();
54}
55
56namespace llvm::orc {
57
58[[maybe_unused]] static const char *AddFnName =
59 "__unw_add_find_dynamic_unwind_sections";
60[[maybe_unused]] static const char *RemoveFnName =
61 "__unw_remove_find_dynamic_unwind_sections";
62static std::unique_ptr<UnwindInfoManager> Instance;
63static int (*RemoveFindDynamicUnwindSections)(void *) = nullptr;
64
65UnwindInfoManager::~UnwindInfoManager() {
66 if (int Err = RemoveFindDynamicUnwindSections((void *)&findSections)) {
67 (void)Err; // Silence unused variable warning in release builds.
68 LLVM_DEBUG({
69 dbgs() << "Failed call to " << RemoveFnName << ": error = " << Err
70 << "\n";
71 });
72 (void)Err;
73 }
74}
75
76bool UnwindInfoManager::TryEnable() {
77#ifdef __APPLE__
78 static std::mutex M;
79 std::lock_guard<std::mutex> Lock(M);
80
81 if (Instance)
82 return true;
83
84 auto AddFn = (int (*)(void *))dlsym(RTLD_DEFAULT, AddFnName);
85 if (!AddFn)
86 return false;
87
88 auto RemoveFn = (int (*)(void *))dlsym(RTLD_DEFAULT, RemoveFnName);
89 if (!RemoveFn)
90 return false;
91
92 Instance.reset(new UnwindInfoManager());
93
94 if (auto Err = AddFn((void *)&findSections)) {
95 (void)Err; // Silence unused variable warning in release builds.
96 LLVM_DEBUG({
97 dbgs() << "Failed call to " << AddFnName << ": error = " << Err << "\n";
98 });
99 Instance = nullptr;
100 return false;
101 }
102
103 RemoveFindDynamicUnwindSections = RemoveFn;
104 return true;
105
106#else
107 return false;
108#endif // __APPLE__
109}
110
111void UnwindInfoManager::addBootstrapSymbols(StringMap<ExecutorAddr> &M) {
112 Mangler Mangle{Triple(sys::getProcessTriple())};
113 M[Mangle.mangledCopy(Name: rt_alt::UnwindInfoManagerRegisterActionName)] =
114 ExecutorAddr::fromPtr(Ptr: llvm_orc_rt_alt_UnwindInfoManager_register);
115 M[Mangle.mangledCopy(Name: rt_alt::UnwindInfoManagerDeregisterActionName)] =
116 ExecutorAddr::fromPtr(Ptr: llvm_orc_rt_alt_UnwindInfoManager_deregister);
117
118 {
119 // Also provide symbols defined by StandaloneMachOUnwindInfoRegistrar
120 // in the new ORC runtime.
121 const auto &SNs = rt::orc_rt_MachOUnwindInfoRegistrarSPSSymbols;
122 M[Mangle.mangledCopy(Name: SNs.RegisterSectionsName)] =
123 ExecutorAddr::fromPtr(Ptr: llvm_orc_rt_alt_UnwindInfoManager_register);
124 M[Mangle.mangledCopy(Name: SNs.DeregisterSectionsName)] =
125 ExecutorAddr::fromPtr(Ptr: llvm_orc_rt_alt_UnwindInfoManager_deregister);
126 }
127}
128
129Error UnwindInfoManager::registerSections(
130 ArrayRef<orc::ExecutorAddrRange> CodeRanges, orc::ExecutorAddr DSOBase,
131 orc::ExecutorAddrRange DWARFEHFrame, orc::ExecutorAddrRange CompactUnwind) {
132 return Instance->registerSectionsImpl(CodeRanges, DSOBase, DWARFEHFrame,
133 CompactUnwind);
134}
135
136Error UnwindInfoManager::deregisterSections(
137 ArrayRef<orc::ExecutorAddrRange> CodeRanges) {
138 return Instance->deregisterSectionsImpl(CodeRanges);
139}
140
141int UnwindInfoManager::findSectionsImpl(uintptr_t Addr, UnwindSections *Info) {
142 std::lock_guard<std::mutex> Lock(M);
143 auto I = UWSecs.upper_bound(x: Addr);
144 if (I == UWSecs.begin())
145 return 0;
146 --I;
147 *Info = I->second;
148 return 1;
149}
150
151int UnwindInfoManager::findSections(uintptr_t Addr, UnwindSections *Info) {
152 return Instance->findSectionsImpl(Addr, Info);
153}
154
155Error UnwindInfoManager::registerSectionsImpl(
156 ArrayRef<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase,
157 ExecutorAddrRange DWARFEHFrame, ExecutorAddrRange CompactUnwind) {
158 std::lock_guard<std::mutex> Lock(M);
159 for (auto &R : CodeRanges)
160 UWSecs[R.Start.getValue()] =
161 UnwindSections{.dso_base: static_cast<uintptr_t>(DSOBase.getValue()),
162 .dwarf_section: static_cast<uintptr_t>(DWARFEHFrame.Start.getValue()),
163 .dwarf_section_length: static_cast<size_t>(DWARFEHFrame.size()),
164 .compact_unwind_section: static_cast<uintptr_t>(CompactUnwind.Start.getValue()),
165 .compact_unwind_section_length: static_cast<size_t>(CompactUnwind.size())};
166 return Error::success();
167}
168
169Error UnwindInfoManager::deregisterSectionsImpl(
170 ArrayRef<ExecutorAddrRange> CodeRanges) {
171 std::lock_guard<std::mutex> Lock(M);
172 for (auto &R : CodeRanges) {
173 auto I = UWSecs.find(x: R.Start.getValue());
174 if (I == UWSecs.end())
175 return make_error<StringError>(
176 Args: "No unwind-info sections registered for range " +
177 formatv(Fmt: "{0:x} - {1:x}", Vals: R.Start, Vals: R.End),
178 Args: inconvertibleErrorCode());
179 UWSecs.erase(position: I);
180 }
181 return Error::success();
182}
183
184} // namespace llvm::orc
185