1 //===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
11
12 #include "llvm/Config/config.h"
13 #include "llvm/ExecutionEngine/JITSymbol.h"
14 #include "llvm/Support/BinaryStreamReader.h"
15 #include "llvm/Support/Compiler.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/DynamicLibrary.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 #include "llvm/Support/FormatVariadic.h"
21
22 #define DEBUG_TYPE "orc"
23
24 using namespace llvm;
25 using namespace llvm::orc;
26 using namespace llvm::orc::shared;
27
28 namespace llvm {
29 namespace orc {
30
31 #if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
32 !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
33
34 extern "C" void __register_frame(const void *);
35 extern "C" void __deregister_frame(const void *);
36
registerFrameWrapper(const void * P)37 Error registerFrameWrapper(const void *P) {
38 __register_frame(P);
39 return Error::success();
40 }
41
deregisterFrameWrapper(const void * P)42 Error deregisterFrameWrapper(const void *P) {
43 __deregister_frame(P);
44 return Error::success();
45 }
46
47 #else
48
49 // The building compiler does not have __(de)register_frame but
50 // it may be found at runtime in a dynamically-loaded library.
51 // For example, this happens when building LLVM with Visual C++
52 // but using the MingW runtime.
53 static Error registerFrameWrapper(const void *P) {
54 static void((*RegisterFrame)(const void *)) = 0;
55
56 if (!RegisterFrame)
57 *(void **)&RegisterFrame =
58 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
59
60 if (RegisterFrame) {
61 RegisterFrame(P);
62 return Error::success();
63 }
64
65 return make_error<StringError>("could not register eh-frame: "
66 "__register_frame function not found",
67 inconvertibleErrorCode());
68 }
69
70 static Error deregisterFrameWrapper(const void *P) {
71 static void((*DeregisterFrame)(const void *)) = 0;
72
73 if (!DeregisterFrame)
74 *(void **)&DeregisterFrame =
75 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
76 "__deregister_frame");
77
78 if (DeregisterFrame) {
79 DeregisterFrame(P);
80 return Error::success();
81 }
82
83 return make_error<StringError>("could not deregister eh-frame: "
84 "__deregister_frame function not found",
85 inconvertibleErrorCode());
86 }
87 #endif
88
89 #ifdef __APPLE__
90
91 template <typename HandleFDEFn>
walkAppleEHFrameSection(const char * const SectionStart,size_t SectionSize,HandleFDEFn HandleFDE)92 Error walkAppleEHFrameSection(const char *const SectionStart,
93 size_t SectionSize, HandleFDEFn HandleFDE) {
94 const char *CurCFIRecord = SectionStart;
95 const char *End = SectionStart + SectionSize;
96 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
97
98 while (CurCFIRecord != End && Size != 0) {
99 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
100 if (Size == 0xffffffff)
101 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
102 else
103 Size += 4;
104 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
105
106 LLVM_DEBUG({
107 dbgs() << "Registering eh-frame section:\n";
108 dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
109 << (void *)CurCFIRecord << ": [";
110 for (unsigned I = 0; I < Size; ++I)
111 dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
112 dbgs() << " ]\n";
113 });
114
115 if (Offset != 0)
116 if (auto Err = HandleFDE(CurCFIRecord))
117 return Err;
118
119 CurCFIRecord += Size;
120
121 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
122 }
123
124 return Error::success();
125 }
126
127 #endif // __APPLE__
128
registerEHFrameSection(const void * EHFrameSectionAddr,size_t EHFrameSectionSize)129 Error registerEHFrameSection(const void *EHFrameSectionAddr,
130 size_t EHFrameSectionSize) {
131 #ifdef __APPLE__
132 // On Darwin __register_frame has to be called for each FDE entry.
133 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
134 EHFrameSectionSize, registerFrameWrapper);
135 #else
136 // On Linux __register_frame takes a single argument:
137 // a pointer to the start of the .eh_frame section.
138
139 // How can it find the end? Because crtendS.o is linked
140 // in and it has an .eh_frame section with four zero chars.
141 return registerFrameWrapper(EHFrameSectionAddr);
142 #endif
143 }
144
deregisterEHFrameSection(const void * EHFrameSectionAddr,size_t EHFrameSectionSize)145 Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
146 size_t EHFrameSectionSize) {
147 #ifdef __APPLE__
148 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
149 EHFrameSectionSize, deregisterFrameWrapper);
150 #else
151 return deregisterFrameWrapper(EHFrameSectionAddr);
152 #endif
153 }
154
155 } // end namespace orc
156 } // end namespace llvm
157
registerEHFrameWrapper(JITTargetAddress Addr,uint64_t Size)158 static Error registerEHFrameWrapper(JITTargetAddress Addr, uint64_t Size) {
159 return llvm::orc::registerEHFrameSection(
160 jitTargetAddressToPointer<const void *>(Addr), Size);
161 }
162
deregisterEHFrameWrapper(JITTargetAddress Addr,uint64_t Size)163 static Error deregisterEHFrameWrapper(JITTargetAddress Addr, uint64_t Size) {
164 return llvm::orc::deregisterEHFrameSection(
165 jitTargetAddressToPointer<const void *>(Addr), Size);
166 }
167
168 extern "C" orc::shared::detail::CWrapperFunctionResult
llvm_orc_registerEHFrameSectionWrapper(const char * Data,uint64_t Size)169 llvm_orc_registerEHFrameSectionWrapper(const char *Data, uint64_t Size) {
170 return WrapperFunction<SPSError(SPSExecutorAddress, uint64_t)>::handle(
171 Data, Size, registerEHFrameWrapper)
172 .release();
173 }
174
175 extern "C" orc::shared::detail::CWrapperFunctionResult
llvm_orc_deregisterEHFrameSectionWrapper(const char * Data,uint64_t Size)176 llvm_orc_deregisterEHFrameSectionWrapper(const char *Data, uint64_t Size) {
177 return WrapperFunction<SPSError(SPSExecutorAddress, uint64_t)>::handle(
178 Data, Size, deregisterEHFrameWrapper)
179 .release();
180 }
181