LLVM 20.0.0git
RegisterEHFrames.cpp
Go to the documentation of this file.
1//===--------- RegisterEHFrames.cpp - Register EH frame 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
10
11#include "llvm/Config/config.h"
15
16#define DEBUG_TYPE "orc"
17
18using namespace llvm;
19using namespace llvm::orc;
20using namespace llvm::orc::shared;
21
22namespace llvm {
23namespace orc {
24
25#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
26 !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
27
28extern "C" void __register_frame(const void *);
29extern "C" void __deregister_frame(const void *);
30
33 return Error::success();
34}
35
38 return Error::success();
39}
40
41#else
42
43// The building compiler does not have __(de)register_frame but
44// it may be found at runtime in a dynamically-loaded library.
45// For example, this happens when building LLVM with Visual C++
46// but using the MingW runtime.
47static Error registerFrameWrapper(const void *P) {
48 static void((*RegisterFrame)(const void *)) = 0;
49
50 if (!RegisterFrame)
51 *(void **)&RegisterFrame =
53
54 if (RegisterFrame) {
55 RegisterFrame(P);
56 return Error::success();
57 }
58
59 return make_error<StringError>("could not register eh-frame: "
60 "__register_frame function not found",
62}
63
64static Error deregisterFrameWrapper(const void *P) {
65 static void((*DeregisterFrame)(const void *)) = 0;
66
67 if (!DeregisterFrame)
68 *(void **)&DeregisterFrame =
70 "__deregister_frame");
71
72 if (DeregisterFrame) {
73 DeregisterFrame(P);
74 return Error::success();
75 }
76
77 return make_error<StringError>("could not deregister eh-frame: "
78 "__deregister_frame function not found",
80}
81#endif
82
83#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
84
85template <typename HandleFDEFn>
86Error walkLibunwindEHFrameSection(const char *const SectionStart,
87 size_t SectionSize, HandleFDEFn HandleFDE) {
88 const char *CurCFIRecord = SectionStart;
89 const char *End = SectionStart + SectionSize;
90 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
91
92 while (CurCFIRecord != End && Size != 0) {
93 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
94 if (Size == 0xffffffff)
95 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
96 else
97 Size += 4;
98 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
99
100 LLVM_DEBUG({
101 dbgs() << "Registering eh-frame section:\n";
102 dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
103 << (void *)CurCFIRecord << ": [";
104 for (unsigned I = 0; I < Size; ++I)
105 dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
106 dbgs() << " ]\n";
107 });
108
109 if (Offset != 0)
110 if (auto Err = HandleFDE(CurCFIRecord))
111 return Err;
112
113 CurCFIRecord += Size;
114
115 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
116 }
117
118 return Error::success();
119}
120
121#endif // HAVE_UNW_ADD_DYNAMIC_FDE || __APPLE__
122
123Error registerEHFrameSection(const void *EHFrameSectionAddr,
124 size_t EHFrameSectionSize) {
125 /* libgcc and libunwind __register_frame behave differently. We use the
126 * presence of __unw_add_dynamic_fde to detect libunwind. */
127#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
128 // With libunwind, __register_frame has to be called for each FDE entry.
129 return walkLibunwindEHFrameSection(
130 static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,
132#else
133 // With libgcc, __register_frame takes a single argument:
134 // a pointer to the start of the .eh_frame section.
135
136 // How can it find the end? Because crtendS.o is linked
137 // in and it has an .eh_frame section with four zero chars.
138 return registerFrameWrapper(EHFrameSectionAddr);
139#endif
140}
141
142Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
143 size_t EHFrameSectionSize) {
144#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
145 return walkLibunwindEHFrameSection(
146 static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,
148#else
149 return deregisterFrameWrapper(EHFrameSectionAddr);
150#endif
151}
152
153} // end namespace orc
154} // end namespace llvm
155
157 return llvm::orc::registerEHFrameSection(EHFrame.Start.toPtr<const void *>(),
158 EHFrame.size());
159}
160
163 EHFrame.Start.toPtr<const void *>(), EHFrame.size());
164}
165
168 return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
170 .release();
171}
172
175 return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
177 .release();
178}
#define LLVM_DEBUG(...)
Definition: Debug.h:106
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
#define I(x, y, z)
Definition: MD5.cpp:58
#define P(N)
orc::shared::CWrapperFunctionResult llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size)
static Error deregisterEHFrameWrapper(ExecutorAddrRange EHFrame)
orc::shared::CWrapperFunctionResult llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size)
static Error registerEHFrameWrapper(ExecutorAddrRange EHFrame)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
static void * SearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName.
@ SectionSize
Definition: COFF.h:60
Error registerFrameWrapper(const void *P)
Error deregisterEHFrameSection(const void *EHFrameSectionAddr, size_t EHFrameSectionSize)
Unregister frames in the given eh-frame section with libunwind.
void __deregister_frame(const void *)
Error registerEHFrameSection(const void *EHFrameSectionAddr, size_t EHFrameSectionSize)
Register frames in the given eh-frame section with libunwind.
void __register_frame(const void *)
Error deregisterFrameWrapper(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:98
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
Represents an address range in the exceutor process.
ExecutorAddrDiff size() const