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/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"
19 #include "llvm/Support/FormatVariadic.h"
21 #define DEBUG_TYPE "orc"
24 using namespace llvm::orc
;
25 using namespace llvm::orc::shared
;
30 #if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
31 !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
33 extern "C" void __register_frame(const void *);
34 extern "C" void __deregister_frame(const void *);
36 Error
registerFrameWrapper(const void *P
) {
38 return Error::success();
41 Error
deregisterFrameWrapper(const void *P
) {
42 __deregister_frame(P
);
43 return Error::success();
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;
56 *(void **)&RegisterFrame
=
57 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
61 return Error::success();
64 return make_error
<StringError
>("could not register eh-frame: "
65 "__register_frame function not found",
66 inconvertibleErrorCode());
69 static Error
deregisterFrameWrapper(const void *P
) {
70 static void((*DeregisterFrame
)(const void *)) = 0;
73 *(void **)&DeregisterFrame
=
74 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
75 "__deregister_frame");
77 if (DeregisterFrame
) {
79 return Error::success();
82 return make_error
<StringError
>("could not deregister eh-frame: "
83 "__deregister_frame function not found",
84 inconvertibleErrorCode());
88 #ifdef HAVE_UNW_ADD_DYNAMIC_FDE
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
);
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;
103 uint32_t Offset
= *reinterpret_cast<const uint32_t *>(OffsetField
);
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
));
115 if (auto Err
= HandleFDE(CurCFIRecord
))
118 CurCFIRecord
+= Size
;
120 Size
= *reinterpret_cast<const uint32_t *>(CurCFIRecord
);
123 return Error::success();
126 #endif // HAVE_UNW_ADD_DYNAMIC_FDE
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 #ifdef HAVE_UNW_ADD_DYNAMIC_FDE
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
);
138 // With libgcc, __register_frame takes a single argument:
139 // a pointer to the start of the .eh_frame section.
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
);
147 Error
deregisterEHFrameSection(const void *EHFrameSectionAddr
,
148 size_t EHFrameSectionSize
) {
149 #ifdef HAVE_UNW_ADD_DYNAMIC_FDE
150 return walkLibunwindEHFrameSection(
151 static_cast<const char *>(EHFrameSectionAddr
), EHFrameSectionSize
,
152 deregisterFrameWrapper
);
154 return deregisterFrameWrapper(EHFrameSectionAddr
);
158 } // end namespace orc
159 } // end namespace llvm
161 static Error
registerEHFrameWrapper(JITTargetAddress Addr
, uint64_t Size
) {
162 return llvm::orc::registerEHFrameSection(
163 jitTargetAddressToPointer
<const void *>(Addr
), Size
);
166 static Error
deregisterEHFrameWrapper(JITTargetAddress Addr
, uint64_t Size
) {
167 return llvm::orc::deregisterEHFrameSection(
168 jitTargetAddressToPointer
<const void *>(Addr
), Size
);
171 extern "C" orc::shared::detail::CWrapperFunctionResult
172 llvm_orc_registerEHFrameSectionWrapper(const char *Data
, uint64_t Size
) {
173 return WrapperFunction
<SPSError(SPSExecutorAddress
, uint64_t)>::handle(
174 Data
, Size
, registerEHFrameWrapper
)
178 extern "C" orc::shared::detail::CWrapperFunctionResult
179 llvm_orc_deregisterEHFrameSectionWrapper(const char *Data
, uint64_t Size
) {
180 return WrapperFunction
<SPSError(SPSExecutorAddress
, uint64_t)>::handle(
181 Data
, Size
, deregisterEHFrameWrapper
)