1 //===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
11 #include "llvm/Config/config.h"
12 #include "llvm/Support/Compiler.h"
13 #include "llvm/Support/DynamicLibrary.h"
14 #include "llvm/Support/raw_ostream.h"
16 #define DEBUG_TYPE "orc"
19 using namespace llvm::orc
;
20 using namespace llvm::orc::shared
;
25 #if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
26 !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
28 extern "C" void __register_frame(const void *);
29 extern "C" void __deregister_frame(const void *);
31 Error
registerFrameWrapper(const void *P
) {
33 return Error::success();
36 Error
deregisterFrameWrapper(const void *P
) {
37 __deregister_frame(P
);
38 return Error::success();
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.
47 static Error
registerFrameWrapper(const void *P
) {
48 static void((*RegisterFrame
)(const void *)) = 0;
51 *(void **)&RegisterFrame
=
52 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
56 return Error::success();
59 return make_error
<StringError
>("could not register eh-frame: "
60 "__register_frame function not found",
61 inconvertibleErrorCode());
64 static Error
deregisterFrameWrapper(const void *P
) {
65 static void((*DeregisterFrame
)(const void *)) = 0;
68 *(void **)&DeregisterFrame
=
69 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
70 "__deregister_frame");
72 if (DeregisterFrame
) {
74 return Error::success();
77 return make_error
<StringError
>("could not deregister eh-frame: "
78 "__deregister_frame function not found",
79 inconvertibleErrorCode());
83 #if defined(HAVE_UNW_ADD_DYNAMIC_FDE) || defined(__APPLE__)
85 template <typename HandleFDEFn
>
86 Error
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
);
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;
98 uint32_t Offset
= *reinterpret_cast<const uint32_t *>(OffsetField
);
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
));
110 if (auto Err
= HandleFDE(CurCFIRecord
))
113 CurCFIRecord
+= Size
;
115 Size
= *reinterpret_cast<const uint32_t *>(CurCFIRecord
);
118 return Error::success();
121 #endif // HAVE_UNW_ADD_DYNAMIC_FDE || __APPLE__
123 Error
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
,
131 registerFrameWrapper
);
133 // With libgcc, __register_frame takes a single argument:
134 // a pointer to the start of the .eh_frame section.
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
);
142 Error
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
,
147 deregisterFrameWrapper
);
149 return deregisterFrameWrapper(EHFrameSectionAddr
);
153 } // end namespace orc
154 } // end namespace llvm
156 static Error
registerEHFrameWrapper(ExecutorAddrRange EHFrame
) {
157 return llvm::orc::registerEHFrameSection(EHFrame
.Start
.toPtr
<const void *>(),
161 static Error
deregisterEHFrameWrapper(ExecutorAddrRange EHFrame
) {
162 return llvm::orc::deregisterEHFrameSection(
163 EHFrame
.Start
.toPtr
<const void *>(), EHFrame
.size());
166 extern "C" orc::shared::CWrapperFunctionResult
167 llvm_orc_registerEHFrameSectionWrapper(const char *Data
, uint64_t Size
) {
168 return WrapperFunction
<SPSError(SPSExecutorAddrRange
)>::handle(
169 Data
, Size
, registerEHFrameWrapper
)
173 extern "C" orc::shared::CWrapperFunctionResult
174 llvm_orc_deregisterEHFrameSectionWrapper(const char *Data
, uint64_t Size
) {
175 return WrapperFunction
<SPSError(SPSExecutorAddrRange
)>::handle(
176 Data
, Size
, deregisterEHFrameWrapper
)