[Darwin][Driver][clang] apple-none-macho orders the resource directory after internal...
[llvm-project.git] / llvm / lib / ExecutionEngine / Orc / TargetProcess / RegisterEHFrames.cpp
blobf11a73bb5c7ac187c692ea55ee21e704ac53f1bc
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 //===----------------------------------------------------------------------===//
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"
18 using namespace llvm;
19 using namespace llvm::orc;
20 using namespace llvm::orc::shared;
22 namespace llvm {
23 namespace orc {
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) {
32 __register_frame(P);
33 return Error::success();
36 Error deregisterFrameWrapper(const void *P) {
37 __deregister_frame(P);
38 return Error::success();
41 #else
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;
50 if (!RegisterFrame)
51 *(void **)&RegisterFrame =
52 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
54 if (RegisterFrame) {
55 RegisterFrame(P);
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;
67 if (!DeregisterFrame)
68 *(void **)&DeregisterFrame =
69 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
70 "__deregister_frame");
72 if (DeregisterFrame) {
73 DeregisterFrame(P);
74 return Error::success();
77 return make_error<StringError>("could not deregister eh-frame: "
78 "__deregister_frame function not found",
79 inconvertibleErrorCode());
81 #endif
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;
96 else
97 Size += 4;
98 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
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";
109 if (Offset != 0)
110 if (auto Err = HandleFDE(CurCFIRecord))
111 return Err;
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);
132 #else
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);
139 #endif
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);
148 #else
149 return deregisterFrameWrapper(EHFrameSectionAddr);
150 #endif
153 } // end namespace orc
154 } // end namespace llvm
156 static Error registerEHFrameWrapper(ExecutorAddrRange EHFrame) {
157 return llvm::orc::registerEHFrameSection(EHFrame.Start.toPtr<const void *>(),
158 EHFrame.size());
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)
170 .release();
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)
177 .release();