xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1e8d8bef9SDimitry Andric //===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric //                     The LLVM Compiler Infrastructure
4e8d8bef9SDimitry Andric //
5e8d8bef9SDimitry Andric // This file is distributed under the University of Illinois Open Source
6e8d8bef9SDimitry Andric // License. See LICENSE.TXT for details.
7e8d8bef9SDimitry Andric //
8e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
9e8d8bef9SDimitry Andric 
10e8d8bef9SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
11e8d8bef9SDimitry Andric 
12e8d8bef9SDimitry Andric #include "llvm/Config/config.h"
13e8d8bef9SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h"
14e8d8bef9SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
15e8d8bef9SDimitry Andric #include "llvm/Support/Compiler.h"
16e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h"
17e8d8bef9SDimitry Andric #include "llvm/Support/DynamicLibrary.h"
18e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h"
19e8d8bef9SDimitry Andric 
20e8d8bef9SDimitry Andric #include "llvm/Support/FormatVariadic.h"
21e8d8bef9SDimitry Andric 
22e8d8bef9SDimitry Andric #define DEBUG_TYPE "orc"
23e8d8bef9SDimitry Andric 
24e8d8bef9SDimitry Andric using namespace llvm;
25e8d8bef9SDimitry Andric using namespace llvm::orc;
26*fe6060f1SDimitry Andric using namespace llvm::orc::shared;
27e8d8bef9SDimitry Andric 
28e8d8bef9SDimitry Andric namespace llvm {
29e8d8bef9SDimitry Andric namespace orc {
30e8d8bef9SDimitry Andric 
31e8d8bef9SDimitry Andric #if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) &&          \
32e8d8bef9SDimitry Andric     !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
33e8d8bef9SDimitry Andric 
34e8d8bef9SDimitry Andric extern "C" void __register_frame(const void *);
35e8d8bef9SDimitry Andric extern "C" void __deregister_frame(const void *);
36e8d8bef9SDimitry Andric 
37e8d8bef9SDimitry Andric Error registerFrameWrapper(const void *P) {
38e8d8bef9SDimitry Andric   __register_frame(P);
39e8d8bef9SDimitry Andric   return Error::success();
40e8d8bef9SDimitry Andric }
41e8d8bef9SDimitry Andric 
42e8d8bef9SDimitry Andric Error deregisterFrameWrapper(const void *P) {
43e8d8bef9SDimitry Andric   __deregister_frame(P);
44e8d8bef9SDimitry Andric   return Error::success();
45e8d8bef9SDimitry Andric }
46e8d8bef9SDimitry Andric 
47e8d8bef9SDimitry Andric #else
48e8d8bef9SDimitry Andric 
49e8d8bef9SDimitry Andric // The building compiler does not have __(de)register_frame but
50e8d8bef9SDimitry Andric // it may be found at runtime in a dynamically-loaded library.
51e8d8bef9SDimitry Andric // For example, this happens when building LLVM with Visual C++
52e8d8bef9SDimitry Andric // but using the MingW runtime.
53e8d8bef9SDimitry Andric static Error registerFrameWrapper(const void *P) {
54e8d8bef9SDimitry Andric   static void((*RegisterFrame)(const void *)) = 0;
55e8d8bef9SDimitry Andric 
56e8d8bef9SDimitry Andric   if (!RegisterFrame)
57e8d8bef9SDimitry Andric     *(void **)&RegisterFrame =
58e8d8bef9SDimitry Andric         llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
59e8d8bef9SDimitry Andric 
60e8d8bef9SDimitry Andric   if (RegisterFrame) {
61e8d8bef9SDimitry Andric     RegisterFrame(P);
62e8d8bef9SDimitry Andric     return Error::success();
63e8d8bef9SDimitry Andric   }
64e8d8bef9SDimitry Andric 
65e8d8bef9SDimitry Andric   return make_error<StringError>("could not register eh-frame: "
66e8d8bef9SDimitry Andric                                  "__register_frame function not found",
67e8d8bef9SDimitry Andric                                  inconvertibleErrorCode());
68e8d8bef9SDimitry Andric }
69e8d8bef9SDimitry Andric 
70e8d8bef9SDimitry Andric static Error deregisterFrameWrapper(const void *P) {
71e8d8bef9SDimitry Andric   static void((*DeregisterFrame)(const void *)) = 0;
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric   if (!DeregisterFrame)
74e8d8bef9SDimitry Andric     *(void **)&DeregisterFrame =
75e8d8bef9SDimitry Andric         llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
76e8d8bef9SDimitry Andric             "__deregister_frame");
77e8d8bef9SDimitry Andric 
78e8d8bef9SDimitry Andric   if (DeregisterFrame) {
79e8d8bef9SDimitry Andric     DeregisterFrame(P);
80e8d8bef9SDimitry Andric     return Error::success();
81e8d8bef9SDimitry Andric   }
82e8d8bef9SDimitry Andric 
83e8d8bef9SDimitry Andric   return make_error<StringError>("could not deregister eh-frame: "
84e8d8bef9SDimitry Andric                                  "__deregister_frame function not found",
85e8d8bef9SDimitry Andric                                  inconvertibleErrorCode());
86e8d8bef9SDimitry Andric }
87e8d8bef9SDimitry Andric #endif
88e8d8bef9SDimitry Andric 
89e8d8bef9SDimitry Andric #ifdef __APPLE__
90e8d8bef9SDimitry Andric 
91e8d8bef9SDimitry Andric template <typename HandleFDEFn>
92e8d8bef9SDimitry Andric Error walkAppleEHFrameSection(const char *const SectionStart,
93e8d8bef9SDimitry Andric                               size_t SectionSize, HandleFDEFn HandleFDE) {
94e8d8bef9SDimitry Andric   const char *CurCFIRecord = SectionStart;
95e8d8bef9SDimitry Andric   const char *End = SectionStart + SectionSize;
96e8d8bef9SDimitry Andric   uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
97e8d8bef9SDimitry Andric 
98e8d8bef9SDimitry Andric   while (CurCFIRecord != End && Size != 0) {
99e8d8bef9SDimitry Andric     const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
100e8d8bef9SDimitry Andric     if (Size == 0xffffffff)
101e8d8bef9SDimitry Andric       Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
102e8d8bef9SDimitry Andric     else
103e8d8bef9SDimitry Andric       Size += 4;
104e8d8bef9SDimitry Andric     uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
105e8d8bef9SDimitry Andric 
106e8d8bef9SDimitry Andric     LLVM_DEBUG({
107e8d8bef9SDimitry Andric       dbgs() << "Registering eh-frame section:\n";
108e8d8bef9SDimitry Andric       dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
109e8d8bef9SDimitry Andric              << (void *)CurCFIRecord << ": [";
110e8d8bef9SDimitry Andric       for (unsigned I = 0; I < Size; ++I)
111e8d8bef9SDimitry Andric         dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
112e8d8bef9SDimitry Andric       dbgs() << " ]\n";
113e8d8bef9SDimitry Andric     });
114e8d8bef9SDimitry Andric 
115e8d8bef9SDimitry Andric     if (Offset != 0)
116e8d8bef9SDimitry Andric       if (auto Err = HandleFDE(CurCFIRecord))
117e8d8bef9SDimitry Andric         return Err;
118e8d8bef9SDimitry Andric 
119e8d8bef9SDimitry Andric     CurCFIRecord += Size;
120e8d8bef9SDimitry Andric 
121e8d8bef9SDimitry Andric     Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
122e8d8bef9SDimitry Andric   }
123e8d8bef9SDimitry Andric 
124e8d8bef9SDimitry Andric   return Error::success();
125e8d8bef9SDimitry Andric }
126e8d8bef9SDimitry Andric 
127e8d8bef9SDimitry Andric #endif // __APPLE__
128e8d8bef9SDimitry Andric 
129e8d8bef9SDimitry Andric Error registerEHFrameSection(const void *EHFrameSectionAddr,
130e8d8bef9SDimitry Andric                              size_t EHFrameSectionSize) {
131e8d8bef9SDimitry Andric #ifdef __APPLE__
132e8d8bef9SDimitry Andric   // On Darwin __register_frame has to be called for each FDE entry.
133e8d8bef9SDimitry Andric   return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
134e8d8bef9SDimitry Andric                                  EHFrameSectionSize, registerFrameWrapper);
135e8d8bef9SDimitry Andric #else
136e8d8bef9SDimitry Andric   // On Linux __register_frame takes a single argument:
137e8d8bef9SDimitry Andric   // a pointer to the start of the .eh_frame section.
138e8d8bef9SDimitry Andric 
139e8d8bef9SDimitry Andric   // How can it find the end? Because crtendS.o is linked
140e8d8bef9SDimitry Andric   // in and it has an .eh_frame section with four zero chars.
141e8d8bef9SDimitry Andric   return registerFrameWrapper(EHFrameSectionAddr);
142e8d8bef9SDimitry Andric #endif
143e8d8bef9SDimitry Andric }
144e8d8bef9SDimitry Andric 
145e8d8bef9SDimitry Andric Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
146e8d8bef9SDimitry Andric                                size_t EHFrameSectionSize) {
147e8d8bef9SDimitry Andric #ifdef __APPLE__
148e8d8bef9SDimitry Andric   return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
149e8d8bef9SDimitry Andric                                  EHFrameSectionSize, deregisterFrameWrapper);
150e8d8bef9SDimitry Andric #else
151e8d8bef9SDimitry Andric   return deregisterFrameWrapper(EHFrameSectionAddr);
152e8d8bef9SDimitry Andric #endif
153e8d8bef9SDimitry Andric }
154e8d8bef9SDimitry Andric 
155e8d8bef9SDimitry Andric } // end namespace orc
156e8d8bef9SDimitry Andric } // end namespace llvm
157e8d8bef9SDimitry Andric 
158*fe6060f1SDimitry Andric static Error registerEHFrameWrapper(JITTargetAddress Addr, uint64_t Size) {
159*fe6060f1SDimitry Andric   return llvm::orc::registerEHFrameSection(
160*fe6060f1SDimitry Andric       jitTargetAddressToPointer<const void *>(Addr), Size);
161*fe6060f1SDimitry Andric }
162*fe6060f1SDimitry Andric 
163*fe6060f1SDimitry Andric static Error deregisterEHFrameWrapper(JITTargetAddress Addr, uint64_t Size) {
164*fe6060f1SDimitry Andric   return llvm::orc::deregisterEHFrameSection(
165*fe6060f1SDimitry Andric       jitTargetAddressToPointer<const void *>(Addr), Size);
166*fe6060f1SDimitry Andric }
167*fe6060f1SDimitry Andric 
168*fe6060f1SDimitry Andric extern "C" orc::shared::detail::CWrapperFunctionResult
169*fe6060f1SDimitry Andric llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size) {
170*fe6060f1SDimitry Andric   return WrapperFunction<SPSError(SPSExecutorAddress, uint64_t)>::handle(
171*fe6060f1SDimitry Andric              Data, Size, registerEHFrameWrapper)
172e8d8bef9SDimitry Andric       .release();
173e8d8bef9SDimitry Andric }
174e8d8bef9SDimitry Andric 
175*fe6060f1SDimitry Andric extern "C" orc::shared::detail::CWrapperFunctionResult
176*fe6060f1SDimitry Andric llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size) {
177*fe6060f1SDimitry Andric   return WrapperFunction<SPSError(SPSExecutorAddress, uint64_t)>::handle(
178*fe6060f1SDimitry Andric              Data, Size, deregisterEHFrameWrapper)
179e8d8bef9SDimitry Andric       .release();
180e8d8bef9SDimitry Andric }
181