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