LLVM 17.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#include "llvm/Support/Debug.h"
18
20
21#define DEBUG_TYPE "orc"
22
23using namespace llvm;
24using namespace llvm::orc;
25using namespace llvm::orc::shared;
26
27namespace llvm {
28namespace orc {
29
30#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
31 !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
32
33extern "C" void __register_frame(const void *);
34extern "C" void __deregister_frame(const void *);
35
38 return Error::success();
39}
40
43 return Error::success();
44}
45
46#else
47
48// The building compiler does not have __(de)register_frame but
49// it may be found at runtime in a dynamically-loaded library.
50// For example, this happens when building LLVM with Visual C++
51// but using the MingW runtime.
52static Error registerFrameWrapper(const void *P) {
53 static void((*RegisterFrame)(const void *)) = 0;
54
55 if (!RegisterFrame)
56 *(void **)&RegisterFrame =
58
59 if (RegisterFrame) {
60 RegisterFrame(P);
61 return Error::success();
62 }
63
64 return make_error<StringError>("could not register eh-frame: "
65 "__register_frame function not found",
67}
68
69static Error deregisterFrameWrapper(const void *P) {
70 static void((*DeregisterFrame)(const void *)) = 0;
71
72 if (!DeregisterFrame)
73 *(void **)&DeregisterFrame =
75 "__deregister_frame");
76
77 if (DeregisterFrame) {
78 DeregisterFrame(P);
79 return Error::success();
80 }
81
82 return make_error<StringError>("could not deregister eh-frame: "
83 "__deregister_frame function not found",
85}
86#endif
87
88#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
89
90template <typename HandleFDEFn>
91Error walkLibunwindEHFrameSection(const char *const SectionStart,
92 size_t SectionSize, HandleFDEFn HandleFDE) {
93 const char *CurCFIRecord = SectionStart;
94 const char *End = SectionStart + SectionSize;
95 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
96
97 while (CurCFIRecord != End && Size != 0) {
98 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
99 if (Size == 0xffffffff)
100 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
101 else
102 Size += 4;
103 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
104
105 LLVM_DEBUG({
106 dbgs() << "Registering eh-frame section:\n";
107 dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
108 << (void *)CurCFIRecord << ": [";
109 for (unsigned I = 0; I < Size; ++I)
110 dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
111 dbgs() << " ]\n";
112 });
113
114 if (Offset != 0)
115 if (auto Err = HandleFDE(CurCFIRecord))
116 return Err;
117
118 CurCFIRecord += Size;
119
120 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
121 }
122
123 return Error::success();
124}
125
126#endif // HAVE_UNW_ADD_DYNAMIC_FDE || __APPLE__
127
128Error registerEHFrameSection(const void *EHFrameSectionAddr,
129 size_t EHFrameSectionSize) {
130 /* libgcc and libunwind __register_frame behave differently. We use the
131 * presence of __unw_add_dynamic_fde to detect libunwind. */
132#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
133 // With libunwind, __register_frame has to be called for each FDE entry.
134 return walkLibunwindEHFrameSection(
135 static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,
137#else
138 // With libgcc, __register_frame takes a single argument:
139 // a pointer to the start of the .eh_frame section.
140
141 // How can it find the end? Because crtendS.o is linked
142 // in and it has an .eh_frame section with four zero chars.
143 return registerFrameWrapper(EHFrameSectionAddr);
144#endif
145}
146
147Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
148 size_t EHFrameSectionSize) {
149#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
150 return walkLibunwindEHFrameSection(
151 static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,
153#else
154 return deregisterFrameWrapper(EHFrameSectionAddr);
155#endif
156}
157
158} // end namespace orc
159} // end namespace llvm
160
162 return llvm::orc::registerEHFrameSection(EHFrame.Start.toPtr<const void *>(),
163 EHFrame.size());
164}
165
168 EHFrame.Start.toPtr<const void *>(), EHFrame.size());
169}
170
173 return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
175 .release();
176}
177
180 return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
182 .release();
183}
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Size
#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:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
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:406
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
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:124
Represents an address range in the exceutor process.
ExecutorAddrDiff size() const