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(__linux__) && 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#define SYMBOL_IS_FUNC(name)
136#define HIDDEN_SYMBOL(name) .private_extern name
137#if defined(_LIBUNWIND_HIDE_SYMBOLS)
138#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
139#else
140#define EXPORT_SYMBOL(name)
141#endif
142#define WEAK_ALIAS(name, aliasname) \
143 .globl SYMBOL_NAME(aliasname) SEPARATOR \
144 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
145 SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
146
147#define NO_EXEC_STACK_DIRECTIVE
148
149#elif defined(__ELF__)
150
151#if defined(__arm__)
152#define SYMBOL_IS_FUNC(name) .type name,%function
153#else
154#define SYMBOL_IS_FUNC(name) .type name,@function
155#endif
156#define HIDDEN_SYMBOL(name) .hidden name
157#if defined(_LIBUNWIND_HIDE_SYMBOLS)
158#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
159#else
160#define EXPORT_SYMBOL(name)
161#endif
162#define WEAK_SYMBOL(name) .weak name
163
164#if defined(__hexagon__)
165#define WEAK_ALIAS(name, aliasname) \
166 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
167 WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
168 .equiv SYMBOL_NAME(aliasname), SYMBOL_NAME(name)
169#else
170#define WEAK_ALIAS(name, aliasname) \
171 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
172 WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
173 SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
174#endif
175
176#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
177 defined(__linux__)
178#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
179#else
180#define NO_EXEC_STACK_DIRECTIVE
181#endif
182
183#elif defined(_WIN32)
184
185#define SYMBOL_IS_FUNC(name) \
186 .def name SEPARATOR \
187 .scl 2 SEPARATOR \
188 .type 32 SEPARATOR \
189 .endef
190#define EXPORT_SYMBOL2(name) \
191 .section .drectve,"yn" SEPARATOR \
192 .ascii "-export:", #name, "\0" SEPARATOR \
193 .text
194#if defined(_LIBUNWIND_HIDE_SYMBOLS)
195#define EXPORT_SYMBOL(name)
196#else
197#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
198#endif
199#define HIDDEN_SYMBOL(name)
200
201#if defined(__MINGW32__)
202#define WEAK_ALIAS(name, aliasname) \
203 .globl SYMBOL_NAME(aliasname) SEPARATOR \
204 EXPORT_SYMBOL(aliasname) SEPARATOR \
205 SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
206#else
207#define WEAK_ALIAS3(name, aliasname) \
208 .section .drectve,"yn" SEPARATOR \
209 .ascii "-alternatename:", #aliasname, "=", #name, "\0" SEPARATOR \
210 .text
211#define WEAK_ALIAS2(name, aliasname) \
212 WEAK_ALIAS3(name, aliasname)
213#define WEAK_ALIAS(name, aliasname) \
214 EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR \
215 WEAK_ALIAS2(SYMBOL_NAME(name), SYMBOL_NAME(aliasname))
216#endif
217
218#define NO_EXEC_STACK_DIRECTIVE
219
220#elif defined(__sparc__)
221
222#elif defined(_AIX)
223
224#if defined(__powerpc64__)
225#define VBYTE_LEN 8
226#define CSECT_ALIGN 3
227#else
228#define VBYTE_LEN 4
229#define CSECT_ALIGN 2
230#endif
231
232// clang-format off
233#define DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(name, aliasname) \
234 .csect .text[PR], 2 SEPARATOR \
235 .csect .name[PR], 2 SEPARATOR \
236 .globl name[DS] SEPARATOR \
237 .globl .name[PR] SEPARATOR \
238 .align 4 SEPARATOR \
239 .csect name[DS], CSECT_ALIGN SEPARATOR \
240aliasname: \
241 .vbyte VBYTE_LEN, .name[PR] SEPARATOR \
242 .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
243 .vbyte VBYTE_LEN, 0 SEPARATOR \
244 .weak aliasname SEPARATOR \
245 .weak .aliasname SEPARATOR \
246 .csect .name[PR], 2 SEPARATOR \
247.aliasname: \
248
249#define WEAK_ALIAS(name, aliasname)
250#define NO_EXEC_STACK_DIRECTIVE
251
252// clang-format on
253#else
254
255#error Unsupported target
256
257#endif
258
259#if defined(_AIX)
260 // clang-format off
261#define DEFINE_LIBUNWIND_FUNCTION(name) \
262 .globl name[DS] SEPARATOR \
263 .globl .name SEPARATOR \
264 .align 4 SEPARATOR \
265 .csect name[DS], CSECT_ALIGN SEPARATOR \
266 .vbyte VBYTE_LEN, .name SEPARATOR \
267 .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
268 .vbyte VBYTE_LEN, 0 SEPARATOR \
269 .csect .text[PR], 2 SEPARATOR \
270.name:
271 // clang-format on
272#else
273#define DEFINE_LIBUNWIND_FUNCTION(name) \
274 .globl SYMBOL_NAME(name) SEPARATOR \
275 HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
276 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
277 PPC64_OPD1 \
278 SYMBOL_NAME(name): \
279 PPC64_OPD2 \
280 AARCH64_BTI
281#endif
282
283#if defined(__arm__)
284#if !defined(__ARM_ARCH)
285#define __ARM_ARCH 4
286#endif
287
288#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
289#define ARM_HAS_BX
290#endif
291
292#ifdef ARM_HAS_BX
293#define JMP(r) bx r
294#else
295#define JMP(r) mov pc, r
296#endif
297#endif /* __arm__ */
298
299#if defined(__powerpc__)
300#define PPC_LEFT_SHIFT(index) << (index)
301#endif
302
303#endif /* UNWIND_ASSEMBLY_H */
304