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