1 //===----------------------------- config.h -------------------------------===//
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 // Define static_assert() unless already defined by compiler.
22 #ifndef __has_feature
23 #define __has_feature(__x) 0
24 #endif
25 #if !(__has_feature(cxx_static_assert)) && !defined(static_assert)
26 #define static_assert(__b, __m) \
27 extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ] \
28 __attribute__( ( unused ) );
29 #endif
30
31 // Platform specific configuration defines.
32 #ifdef __APPLE__
33 #if defined(FOR_DYLD)
34 #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
35 #else
36 #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
37 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
38 #endif
39 #elif defined(_WIN32)
40 #ifdef __SEH__
41 #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
42 #else
43 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
44 #endif
45 #else
46 #if defined(__ARM_DWARF_EH__) || !defined(__arm__)
47 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
48 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
49 #endif
50 #endif
51
52 #if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
53 #define _LIBUNWIND_EXPORT
54 #define _LIBUNWIND_HIDDEN
55 #else
56 #if !defined(__ELF__) && !defined(__MACH__)
57 #define _LIBUNWIND_EXPORT __declspec(dllexport)
58 #define _LIBUNWIND_HIDDEN
59 #else
60 #define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
61 #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
62 #endif
63 #endif
64
65 #define STR(a) #a
66 #define XSTR(a) STR(a)
67 #define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name
68
69 #if defined(__APPLE__)
70 #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
71 __asm__(".globl " SYMBOL_NAME(aliasname)); \
72 __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \
73 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
74 __attribute__((weak_import));
75 #elif defined(__ELF__)
76 #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
77 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
78 __attribute__((weak, alias(#name)));
79 #elif defined(_WIN32)
80 #if defined(__MINGW32__)
81 #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
82 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
83 __attribute__((alias(#name)));
84 #else
85 #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
86 __pragma(comment(linker, "/alternatename:" SYMBOL_NAME(aliasname) "=" \
87 SYMBOL_NAME(name))) \
88 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname;
89 #endif
90 #else
91 #error Unsupported target
92 #endif
93
94 #if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__)
95 #define _LIBUNWIND_BUILD_SJLJ_APIS
96 #endif
97
98 #if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__)
99 #define _LIBUNWIND_SUPPORT_FRAME_APIS
100 #endif
101
102 #if defined(__i386__) || defined(__x86_64__) || \
103 defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \
104 (!defined(__APPLE__) && defined(__arm__)) || \
105 defined(__aarch64__) || \
106 defined(__mips__) || \
107 defined(__riscv) || \
108 defined(__hexagon__)
109 #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
110 #define _LIBUNWIND_BUILD_ZERO_COST_APIS
111 #endif
112 #endif
113
114 #if defined(__powerpc64__) && defined(_ARCH_PWR8)
115 #define PPC64_HAS_VMX
116 #endif
117
118 #ifdef __CHERI_PURE_CAPABILITY__
119 #define _LIBUNWIND_FMT_PTR "%-#p"
120 #else
121 #define _LIBUNWIND_FMT_PTR "%p"
122 #endif
123
124 #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
125 #define _LIBUNWIND_ABORT(msg) \
126 do { \
127 abort(); \
128 } while (0)
129 #define _LIBUNWIND_ABORT_FMT(fmt, msg, ...) _LIBUNWIND_ABORT(msg)
130 #else
131 #define _LIBUNWIND_ABORT(msg) \
132 do { \
133 fprintf(stderr, "libunwind: %s - %s\n", __func__, msg); \
134 fflush(stderr); \
135 __builtin_trap(); abort(); \
136 } while (0)
137 #define _LIBUNWIND_ABORT_FMT(fmt, ...) \
138 do { \
139 fprintf(stderr, "libunwind: %s %s:%d - " fmt "\n", __func__, __FILE__, \
140 __LINE__, __VA_ARGS__); \
141 fflush(stderr); \
142 __builtin_trap(); abort(); \
143 } while (0)
144 #endif
145
146 #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
147 #define _LIBUNWIND_LOG0(msg)
148 #define _LIBUNWIND_LOG(msg, ...)
149 #else
150 #define _LIBUNWIND_LOG0(msg) \
151 fprintf(stderr, "libunwind: " msg "\n")
152 #define _LIBUNWIND_LOG(msg, ...) \
153 fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
154 #endif
155
156 #if defined(NDEBUG)
157 #define _LIBUNWIND_LOG_IF_FALSE(x) x
158 #else
159 #define _LIBUNWIND_LOG_IF_FALSE(x) \
160 do { \
161 bool _ret = x; \
162 if (!_ret) \
163 _LIBUNWIND_LOG("" #x " failed in %s", __FUNCTION__); \
164 } while (0)
165 #endif
166
167 #ifdef __CHERI_PURE_CAPABILITY__
assert_pointer_in_bounds(uintptr_t value)168 static inline uintptr_t assert_pointer_in_bounds(uintptr_t value) {
169 if (!__builtin_cheri_tag_get((void*)value)) {
170 _LIBUNWIND_ABORT_FMT("Untagged value " _LIBUNWIND_FMT_PTR
171 " used for dwarf section", (void*)value);
172 } else if (__builtin_cheri_offset_get((void*)value) >=
173 __builtin_cheri_length_get((void*)value)) {
174 _LIBUNWIND_ABORT_FMT("Out-of-bounds value " _LIBUNWIND_FMT_PTR
175 " used for dwarf section", (void*)value);
176 }
177 return value;
178 }
179 #else
assert_pointer_in_bounds(uintptr_t value)180 static inline uintptr_t assert_pointer_in_bounds(uintptr_t value) {
181 return value;
182 }
183 #endif
184
185 #if !__has_extension(cheri_casts)
186 #define __cheri_addr /* nothing */
187 #endif
188
189 // Macros that define away in non-Debug builds
190 #ifdef NDEBUG
191 #define _LIBUNWIND_DEBUG_LOG(msg, ...)
192 #define _LIBUNWIND_TRACE_API(msg, ...)
193 #define _LIBUNWIND_TRACING_UNWINDING (0)
194 #define _LIBUNWIND_TRACING_DWARF (0)
195 #define _LIBUNWIND_TRACE_UNWINDING(msg, ...)
196 #define _LIBUNWIND_TRACE_DWARF(...)
197 #define CHERI_DBG(...) (void)0
198 #else
199 #ifdef __cplusplus
200 extern "C" {
201 #endif
202 extern bool logAPIs();
203 extern bool logUnwinding();
204 extern bool logDWARF();
205 #ifdef __CHERI_PURE_CAPABILITY__
206 extern bool logCHERI();
207 #endif
208 #ifdef __cplusplus
209 }
210 #endif
211 #define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__)
212 #define _LIBUNWIND_TRACE_API(msg, ...) \
213 do { \
214 if (logAPIs()) \
215 _LIBUNWIND_LOG(msg, __VA_ARGS__); \
216 } while (0)
217 #define _LIBUNWIND_TRACING_UNWINDING logUnwinding()
218 #define _LIBUNWIND_TRACING_DWARF logDWARF()
219 #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \
220 do { \
221 if (logUnwinding()) \
222 _LIBUNWIND_LOG(msg, __VA_ARGS__); \
223 } while (0)
224 #define _LIBUNWIND_TRACE_DWARF(...) \
225 do { \
226 if (logDWARF()) \
227 fprintf(stderr, __VA_ARGS__); \
228 } while (0)
229 #ifndef __CHERI_PURE_CAPABILITY__
230 #define CHERI_DBG(...) (void)0
231 #else
232 #define CHERI_DBG(...) \
233 do { \
234 if (logCHERI()) \
235 fprintf(stderr, __VA_ARGS__); \
236 } while (0)
237 #endif
238 #endif
239
240 #ifdef __cplusplus
241 // Used to fit UnwindCursor and Registers_xxx types against unw_context_t /
242 // unw_cursor_t sized memory blocks.
243 #if defined(_LIBUNWIND_IS_NATIVE_ONLY)
244 # define COMP_OP ==
245 #else
246 # define COMP_OP <=
247 #endif
248 template <typename _Type, typename _Mem>
249 struct check_fit {
250 template <typename T>
251 struct blk_count {
252 static const size_t count =
253 (sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
254 };
255 static const bool does_fit =
256 (blk_count<_Type>::count COMP_OP blk_count<_Mem>::count);
257 };
258 #undef COMP_OP
259 #endif // __cplusplus
260
pcc_address(uintptr_t a)261 static inline uintptr_t pcc_address(uintptr_t a)
262 {
263 #ifdef __CHERI_PURE_CAPABILITY__
264 if (__builtin_cheri_tag_get((void*)a))
265 return a;
266 void *pcc = __builtin_cheri_program_counter_get();
267 pcc = __builtin_cheri_offset_set(pcc, (long)__builtin_cheri_address_get((void*)a));
268 return (uintptr_t)pcc;
269 #else
270 return a;
271 #endif
272 }
273
274 #endif // LIBUNWIND_CONFIG_H
275