1/* ===-- assembly.h - libUnwind assembler support macros -------------------===
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 *
9 * This file defines macros for use in libUnwind assembler source.
10 * This file is not part of the interface of this library.
11 *
12 * ===----------------------------------------------------------------------===
13 */
14
15#ifndef UNWIND_ASSEMBLY_H
16#define UNWIND_ASSEMBLY_H
17
18#if defined(__CET__)
19#include <cet.h>
20#define _LIBUNWIND_CET_ENDBR _CET_ENDBR
21#else
22#define _LIBUNWIND_CET_ENDBR
23#endif
24
25#if defined(__powerpc64__)
26#define SEPARATOR ;
27#define PPC64_OFFS_SRR0 0
28#define PPC64_OFFS_CR 272
29#define PPC64_OFFS_XER 280
30#define PPC64_OFFS_LR 288
31#define PPC64_OFFS_CTR 296
32#define PPC64_OFFS_VRSAVE 304
33#define PPC64_OFFS_FP 312
34#define PPC64_OFFS_V 824
35#elif defined(__APPLE__) && defined(__aarch64__)
36#define SEPARATOR %%
37#elif defined(__riscv)
38# define RISCV_ISIZE (__riscv_xlen / 8)
39# define RISCV_FOFFSET (RISCV_ISIZE * 32)
40# if defined(__riscv_flen)
41# define RISCV_FSIZE (__riscv_flen / 8)
42# endif
43
44# if __riscv_xlen == 64
45# define ILOAD ld
46# define ISTORE sd
47# elif __riscv_xlen == 32
48# define ILOAD lw
49# define ISTORE sw
50# else
51# error "Unsupported __riscv_xlen"
52# endif
53
54# if defined(__riscv_flen)
55# if __riscv_flen == 64
56# define FLOAD fld
57# define FSTORE fsd
58# elif __riscv_flen == 32
59# define FLOAD flw
60# define FSTORE fsw
61# else
62# error "Unsupported __riscv_flen"
63# endif
64# endif
65# define SEPARATOR ;
66#else
67#define SEPARATOR ;
68#endif
69
70#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) && \
71 !defined(_AIX)
72#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
73#define PPC64_OPD2 SEPARATOR \
74 .p2align 3 SEPARATOR \
75 .quad .Lfunc_begin0 SEPARATOR \
76 .quad .TOC.@tocbase SEPARATOR \
77 .quad 0 SEPARATOR \
78 .text SEPARATOR \
79.Lfunc_begin0:
80#else
81#define PPC64_OPD1
82#define PPC64_OPD2
83#endif
84
85#if defined(__aarch64__)
86#if defined(__ARM_FEATURE_GCS_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT)
87// Set BTI, PAC, and GCS gnu property bits
88#define GNU_PROPERTY 7
89// We indirectly branch to __libunwind_Registers_arm64_jumpto from
90// __unw_phase2_resume, so we need to use bti jc.
91#define AARCH64_BTI bti jc
92#elif defined(__ARM_FEATURE_GCS_DEFAULT)
93// Set GCS gnu property bit
94#define GNU_PROPERTY 4
95#elif defined(__ARM_FEATURE_BTI_DEFAULT)
96// Set BTI and PAC gnu property bits
97#define GNU_PROPERTY 3
98#define AARCH64_BTI bti c
99#endif
100#ifdef GNU_PROPERTY
101 .pushsection ".note.gnu.property", "a" SEPARATOR \
102 .balign 8 SEPARATOR \
103 .long 4 SEPARATOR \
104 .long 0x10 SEPARATOR \
105 .long 0x5 SEPARATOR \
106 .asciz "GNU" SEPARATOR \
107 .long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \
108 .long 4 SEPARATOR \
109 .long GNU_PROPERTY SEPARATOR \
110 .long 0 SEPARATOR \
111 .popsection SEPARATOR
112#endif
113#endif
114#if !defined(AARCH64_BTI)
115#define AARCH64_BTI
116#endif
117
118#if !defined(__aarch64__)
119#ifdef __ARM_FEATURE_PAC_DEFAULT
120 .eabi_attribute Tag_PAC_extension, 2
121 .eabi_attribute Tag_PACRET_use, 1
122#endif
123#ifdef __ARM_FEATURE_BTI_DEFAULT
124 .eabi_attribute Tag_BTI_extension, 1
125 .eabi_attribute Tag_BTI_use, 1
126#endif
127#endif
128
129#define GLUE2(a, b) a ## b
130#define GLUE(a, b) GLUE2(a, b)
131#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
132
133#if defined(__APPLE__)
134
135#if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
136#define _LIBUNWIND_TRACE_RET_INJECT 1
137#endif
138
139#define SYMBOL_IS_FUNC(name)
140#define HIDDEN_SYMBOL(name) .private_extern name
141#if defined(_LIBUNWIND_HIDE_SYMBOLS)
142#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
143#else
144#define EXPORT_SYMBOL(name)
145#endif
146#define WEAK_ALIAS(name, aliasname) \
147 .globl SYMBOL_NAME(aliasname) SEPARATOR \
148 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
149 SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
150
151#define NO_EXEC_STACK_DIRECTIVE
152
153#elif defined(__ELF__)
154
155#if defined(__arm__)
156#define SYMBOL_IS_FUNC(name) .type name,%function
157#else
158#define SYMBOL_IS_FUNC(name) .type name,@function
159#endif
160#define HIDDEN_SYMBOL(name) .hidden name
161#if defined(_LIBUNWIND_HIDE_SYMBOLS)
162#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
163#else
164#define EXPORT_SYMBOL(name)
165#endif
166#define WEAK_SYMBOL(name) .weak name
167
168#if defined(__hexagon__)
169#define WEAK_ALIAS(name, aliasname) \
170 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
171 WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
172 .equiv SYMBOL_NAME(aliasname), SYMBOL_NAME(name)
173#else
174#define WEAK_ALIAS(name, aliasname) \
175 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
176 WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
177 SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
178#endif
179
180#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
181 defined(__linux__)
182#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
183#else
184#define NO_EXEC_STACK_DIRECTIVE
185#endif
186
187#elif defined(_WIN32)
188
189#define SYMBOL_IS_FUNC(name) \
190 .def name SEPARATOR \
191 .scl 2 SEPARATOR \
192 .type 32 SEPARATOR \
193 .endef
194#define EXPORT_SYMBOL2(name) \
195 .section .drectve,"yn" SEPARATOR \
196 .ascii "-export:", #name, "\0" SEPARATOR \
197 .text
198#if defined(_LIBUNWIND_HIDE_SYMBOLS)
199#define EXPORT_SYMBOL(name)
200#else
201#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
202#endif
203#define HIDDEN_SYMBOL(name)
204
205#if defined(__MINGW32__)
206#define WEAK_ALIAS(name, aliasname) \
207 .globl SYMBOL_NAME(aliasname) SEPARATOR \
208 EXPORT_SYMBOL(aliasname) SEPARATOR \
209 SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
210#else
211#define WEAK_ALIAS3(name, aliasname) \
212 .section .drectve,"yn" SEPARATOR \
213 .ascii "-alternatename:", #aliasname, "=", #name, "\0" SEPARATOR \
214 .text
215#define WEAK_ALIAS2(name, aliasname) \
216 WEAK_ALIAS3(name, aliasname)
217#define WEAK_ALIAS(name, aliasname) \
218 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
219 WEAK_ALIAS2(SYMBOL_NAME(name), SYMBOL_NAME(aliasname))
220#endif
221
222#define NO_EXEC_STACK_DIRECTIVE
223
224#elif defined(__sparc__)
225
226#elif defined(_AIX)
227
228#if defined(__powerpc64__)
229#define VBYTE_LEN 8
230#define CSECT_ALIGN 3
231#else
232#define VBYTE_LEN 4
233#define CSECT_ALIGN 2
234#endif
235
236// clang-format off
237#define DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(name, aliasname) \
238 .csect .text[PR], 2 SEPARATOR \
239 .csect .name[PR], 2 SEPARATOR \
240 .globl name[DS] SEPARATOR \
241 .globl .name[PR] SEPARATOR \
242 .align 4 SEPARATOR \
243 .csect name[DS], CSECT_ALIGN SEPARATOR \
244aliasname: \
245 .vbyte VBYTE_LEN, .name[PR] SEPARATOR \
246 .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
247 .vbyte VBYTE_LEN, 0 SEPARATOR \
248 .weak aliasname SEPARATOR \
249 .weak .aliasname SEPARATOR \
250 .csect .name[PR], 2 SEPARATOR \
251.aliasname: \
252
253#define WEAK_ALIAS(name, aliasname)
254#define NO_EXEC_STACK_DIRECTIVE
255
256// clang-format on
257#else
258
259#error Unsupported target
260
261#endif
262
263#if defined(_AIX)
264 // clang-format off
265#define DEFINE_LIBUNWIND_FUNCTION(name) \
266 .globl name[DS] SEPARATOR \
267 .globl .name SEPARATOR \
268 .align 4 SEPARATOR \
269 .csect name[DS], CSECT_ALIGN SEPARATOR \
270 .vbyte VBYTE_LEN, .name SEPARATOR \
271 .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
272 .vbyte VBYTE_LEN, 0 SEPARATOR \
273 .csect .text[PR], 2 SEPARATOR \
274.name:
275 // clang-format on
276#else
277#define DEFINE_LIBUNWIND_FUNCTION(name) \
278 .globl SYMBOL_NAME(name) SEPARATOR \
279 HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
280 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
281 PPC64_OPD1 \
282 SYMBOL_NAME(name): \
283 PPC64_OPD2 \
284 AARCH64_BTI
285#endif
286
287#if defined(__arm__)
288#if !defined(__ARM_ARCH)
289#define __ARM_ARCH 4
290#endif
291
292#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
293#define ARM_HAS_BX
294#endif
295
296#ifdef ARM_HAS_BX
297#define JMP(r) bx r
298#else
299#define JMP(r) mov pc, r
300#endif
301#endif /* __arm__ */
302
303#if defined(__powerpc__)
304#define PPC_LEFT_SHIFT(index) << (index)
305#endif
306
307#endif /* UNWIND_ASSEMBLY_H */
308