Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
96380 views
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
9
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
10
11
#include "llvm/Config/config.h"
12
#include "llvm/ExecutionEngine/JITSymbol.h"
13
#include "llvm/Support/BinaryStreamReader.h"
14
#include "llvm/Support/Compiler.h"
15
#include "llvm/Support/Debug.h"
16
#include "llvm/Support/DynamicLibrary.h"
17
#include "llvm/Support/raw_ostream.h"
18
19
#include "llvm/Support/FormatVariadic.h"
20
21
#define DEBUG_TYPE "orc"
22
23
using namespace llvm;
24
using namespace llvm::orc;
25
using namespace llvm::orc::shared;
26
27
namespace llvm {
28
namespace orc {
29
30
#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
31
!defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
32
33
extern "C" void __register_frame(const void *);
34
extern "C" void __deregister_frame(const void *);
35
36
Error registerFrameWrapper(const void *P) {
37
__register_frame(P);
38
return Error::success();
39
}
40
41
Error deregisterFrameWrapper(const void *P) {
42
__deregister_frame(P);
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.
52
static Error registerFrameWrapper(const void *P) {
53
static void((*RegisterFrame)(const void *)) = 0;
54
55
if (!RegisterFrame)
56
*(void **)&RegisterFrame =
57
llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
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",
66
inconvertibleErrorCode());
67
}
68
69
static Error deregisterFrameWrapper(const void *P) {
70
static void((*DeregisterFrame)(const void *)) = 0;
71
72
if (!DeregisterFrame)
73
*(void **)&DeregisterFrame =
74
llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
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",
84
inconvertibleErrorCode());
85
}
86
#endif
87
88
#if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
89
90
template <typename HandleFDEFn>
91
Error 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
128
Error 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,
136
registerFrameWrapper);
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
147
Error 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,
152
deregisterFrameWrapper);
153
#else
154
return deregisterFrameWrapper(EHFrameSectionAddr);
155
#endif
156
}
157
158
} // end namespace orc
159
} // end namespace llvm
160
161
static Error registerEHFrameWrapper(ExecutorAddrRange EHFrame) {
162
return llvm::orc::registerEHFrameSection(EHFrame.Start.toPtr<const void *>(),
163
EHFrame.size());
164
}
165
166
static Error deregisterEHFrameWrapper(ExecutorAddrRange EHFrame) {
167
return llvm::orc::deregisterEHFrameSection(
168
EHFrame.Start.toPtr<const void *>(), EHFrame.size());
169
}
170
171
extern "C" orc::shared::CWrapperFunctionResult
172
llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size) {
173
return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
174
Data, Size, registerEHFrameWrapper)
175
.release();
176
}
177
178
extern "C" orc::shared::CWrapperFunctionResult
179
llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size) {
180
return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
181
Data, Size, deregisterEHFrameWrapper)
182
.release();
183
}
184
185