1 | //===----------------------------------------------------------------------===// |
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 | // Defines macros used within libunwind project. |
9 | // |
10 | //===----------------------------------------------------------------------===// |
11 | |
12 | |
13 | #ifndef LIBUNWIND_CONFIG_H |
14 | #define LIBUNWIND_CONFIG_H |
15 | |
16 | #include <assert.h> |
17 | #include <stdio.h> |
18 | #include <stdint.h> |
19 | #include <stdlib.h> |
20 | |
21 | #include <__libunwind_config.h> |
22 | |
23 | // Platform specific configuration defines. |
24 | #ifdef __APPLE__ |
25 | #if defined(FOR_DYLD) |
26 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 |
27 | #else |
28 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 |
29 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
30 | #endif |
31 | #elif defined(_WIN32) |
32 | #ifdef __SEH__ |
33 | #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1 |
34 | #else |
35 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
36 | #endif |
37 | #elif defined(_LIBUNWIND_IS_BAREMETAL) |
38 | #if !defined(_LIBUNWIND_ARM_EHABI) |
39 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
40 | #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 |
41 | #endif |
42 | #elif defined(__BIONIC__) && defined(_LIBUNWIND_ARM_EHABI) |
43 | // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After |
44 | // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster. |
45 | #define _LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX 1 |
46 | #elif defined(_AIX) |
47 | // The traceback table at the end of each function is used for unwinding. |
48 | #define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1 |
49 | #elif defined(__HAIKU__) |
50 | #if defined(_LIBUNWIND_USE_HAIKU_BSD_LIB) |
51 | #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 |
52 | #endif |
53 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
54 | #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 |
55 | #else |
56 | // Assume an ELF system with a dl_iterate_phdr function. |
57 | #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 |
58 | #if !defined(_LIBUNWIND_ARM_EHABI) |
59 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
60 | #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 |
61 | #endif |
62 | #endif |
63 | |
64 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) |
65 | // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility. |
66 | #define _LIBUNWIND_EXPORT |
67 | #define _LIBUNWIND_HIDDEN |
68 | #else |
69 | #if !defined(__ELF__) && !defined(__MACH__) && !defined(_AIX) |
70 | #define _LIBUNWIND_EXPORT __declspec(dllexport) |
71 | #define _LIBUNWIND_HIDDEN |
72 | #else |
73 | #define _LIBUNWIND_EXPORT __attribute__((visibility("default"))) |
74 | #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden"))) |
75 | #endif |
76 | #endif |
77 | |
78 | #define STR(a) #a |
79 | #define XSTR(a) STR(a) |
80 | #define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name |
81 | |
82 | #if defined(__APPLE__) |
83 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) |
84 | #define _LIBUNWIND_ALIAS_VISIBILITY(name) __asm__(".private_extern " name); |
85 | #else |
86 | #define _LIBUNWIND_ALIAS_VISIBILITY(name) |
87 | #endif |
88 | #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ |
89 | __asm__(".globl " SYMBOL_NAME(aliasname)); \ |
90 | __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \ |
91 | _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname)) |
92 | #elif defined(__ELF__) || defined(_AIX) || defined(__wasm__) |
93 | #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ |
94 | extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ |
95 | __attribute__((weak, alias(#name))); |
96 | #elif defined(_WIN32) |
97 | #if defined(__MINGW32__) |
98 | #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ |
99 | extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ |
100 | __attribute__((alias(#name))); |
101 | #else |
102 | #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ |
103 | __pragma(comment(linker, "/alternatename:" SYMBOL_NAME(aliasname) "=" \ |
104 | SYMBOL_NAME(name))) \ |
105 | extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname; |
106 | #endif |
107 | #else |
108 | #error Unsupported target |
109 | #endif |
110 | |
111 | // Apple/armv7k defaults to DWARF/Compact unwinding, but its libunwind also |
112 | // needs to include the SJLJ APIs. |
113 | #if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__) |
114 | #define _LIBUNWIND_BUILD_SJLJ_APIS |
115 | #endif |
116 | |
117 | #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \ |
118 | (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \ |
119 | defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \ |
120 | defined(__sparc__) || defined(__s390x__) || defined(__loongarch__) |
121 | #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) |
122 | #define _LIBUNWIND_BUILD_ZERO_COST_APIS |
123 | #endif |
124 | #endif |
125 | |
126 | #ifndef _LIBUNWIND_REMEMBER_HEAP_ALLOC |
127 | #if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \ |
128 | defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \ |
129 | defined(_LIBUNWIND_IS_BAREMETAL) |
130 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) __builtin_alloca(_size) |
131 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) \ |
132 | do { \ |
133 | } while (0) |
134 | #elif defined(_WIN32) |
135 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) _malloca(_size) |
136 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) _freea(_ptr) |
137 | #define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED |
138 | #else |
139 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) malloc(_size) |
140 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) free(_ptr) |
141 | #define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED |
142 | #endif |
143 | #else /* _LIBUNWIND_REMEMBER_HEAP_ALLOC */ |
144 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) malloc(_size) |
145 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) free(_ptr) |
146 | #define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED |
147 | #endif |
148 | |
149 | #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) |
150 | #define _LIBUNWIND_ABORT(msg) \ |
151 | do { \ |
152 | abort(); \ |
153 | } while (0) |
154 | #else |
155 | #define _LIBUNWIND_ABORT(msg) \ |
156 | do { \ |
157 | fprintf(stderr, "libunwind: %s - %s\n", __func__, msg); \ |
158 | fflush(stderr); \ |
159 | abort(); \ |
160 | } while (0) |
161 | #endif |
162 | |
163 | #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) |
164 | #define _LIBUNWIND_LOG0(msg) |
165 | #define _LIBUNWIND_LOG(msg, ...) |
166 | #else |
167 | #define _LIBUNWIND_LOG0(msg) do { \ |
168 | fprintf(stderr, "libunwind: " msg "\n"); \ |
169 | fflush(stderr); \ |
170 | } while (0) |
171 | #define _LIBUNWIND_LOG(msg, ...) do { \ |
172 | fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__); \ |
173 | fflush(stderr); \ |
174 | } while (0) |
175 | #endif |
176 | |
177 | #if defined(NDEBUG) |
178 | #define _LIBUNWIND_LOG_IF_FALSE(x) x |
179 | #else |
180 | #define _LIBUNWIND_LOG_IF_FALSE(x) \ |
181 | do { \ |
182 | bool _ret = x; \ |
183 | if (!_ret) \ |
184 | _LIBUNWIND_LOG("" #x " failed in %s", __FUNCTION__); \ |
185 | } while (0) |
186 | #endif |
187 | |
188 | // Macros that define away in non-Debug builds |
189 | #ifdef NDEBUG |
190 | #define _LIBUNWIND_DEBUG_LOG(msg, ...) |
191 | #define _LIBUNWIND_TRACE_API(msg, ...) |
192 | #define _LIBUNWIND_TRACING_UNWINDING (0) |
193 | #define _LIBUNWIND_TRACING_DWARF (0) |
194 | #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) |
195 | #define _LIBUNWIND_TRACE_DWARF(...) |
196 | #else |
197 | #ifdef __cplusplus |
198 | extern "C" { |
199 | #endif |
200 | extern bool logAPIs(void); |
201 | extern bool logUnwinding(void); |
202 | extern bool logDWARF(void); |
203 | #ifdef __cplusplus |
204 | } |
205 | #endif |
206 | #define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__) |
207 | #define _LIBUNWIND_TRACE_API(msg, ...) \ |
208 | do { \ |
209 | if (logAPIs()) \ |
210 | _LIBUNWIND_LOG(msg, __VA_ARGS__); \ |
211 | } while (0) |
212 | #define _LIBUNWIND_TRACING_UNWINDING logUnwinding() |
213 | #define _LIBUNWIND_TRACING_DWARF logDWARF() |
214 | #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \ |
215 | do { \ |
216 | if (logUnwinding()) \ |
217 | _LIBUNWIND_LOG(msg, __VA_ARGS__); \ |
218 | } while (0) |
219 | #define _LIBUNWIND_TRACE_DWARF(...) \ |
220 | do { \ |
221 | if (logDWARF()) \ |
222 | fprintf(stderr, __VA_ARGS__); \ |
223 | } while (0) |
224 | #endif |
225 | |
226 | #ifdef __cplusplus |
227 | // Used to fit UnwindCursor and Registers_xxx types against unw_context_t / |
228 | // unw_cursor_t sized memory blocks. |
229 | #if defined(_LIBUNWIND_IS_NATIVE_ONLY) |
230 | # define COMP_OP == |
231 | #else |
232 | # define COMP_OP <= |
233 | #endif |
234 | template <typename _Type, typename _Mem> |
235 | struct check_fit { |
236 | template <typename T> |
237 | struct blk_count { |
238 | static const size_t count = |
239 | (sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t); |
240 | }; |
241 | static const bool does_fit = |
242 | (blk_count<_Type>::count COMP_OP blk_count<_Mem>::count); |
243 | }; |
244 | #undef COMP_OP |
245 | #endif // __cplusplus |
246 | |
247 | #endif // LIBUNWIND_CONFIG_H |
248 | |