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__) && defined(__ARM_FEATURE_BTI_DEFAULT)
86  .pushsection ".note.gnu.property", "a" SEPARATOR                             \
87  .balign 8 SEPARATOR                                                          \
88  .long 4 SEPARATOR                                                            \
89  .long 0x10 SEPARATOR                                                         \
90  .long 0x5 SEPARATOR                                                          \
91  .asciz "GNU" SEPARATOR                                                       \
92  .long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */          \
93  .long 4 SEPARATOR                                                            \
94  .long 3 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_BTI AND */               \
95                    /* GNU_PROPERTY_AARCH64_FEATURE_1_PAC */                   \
96  .long 0 SEPARATOR                                                            \
97  .popsection SEPARATOR
98#define AARCH64_BTI  bti c
99#else
100#define AARCH64_BTI
101#endif
102
103#if !defined(__aarch64__)
104#ifdef __ARM_FEATURE_PAC_DEFAULT
105  .eabi_attribute Tag_PAC_extension, 2
106  .eabi_attribute Tag_PACRET_use, 1
107#endif
108#ifdef __ARM_FEATURE_BTI_DEFAULT
109  .eabi_attribute Tag_BTI_extension, 1
110  .eabi_attribute Tag_BTI_use, 1
111#endif
112#endif
113
114#define GLUE2(a, b) a ## b
115#define GLUE(a, b) GLUE2(a, b)
116#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
117
118#if defined(__APPLE__)
119
120#define SYMBOL_IS_FUNC(name)
121#define HIDDEN_SYMBOL(name) .private_extern name
122#if defined(_LIBUNWIND_HIDE_SYMBOLS)
123#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
124#else
125#define EXPORT_SYMBOL(name)
126#endif
127#define WEAK_ALIAS(name, aliasname)                                            \
128  .globl SYMBOL_NAME(aliasname) SEPARATOR                                      \
129  EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR                              \
130  SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
131
132#define NO_EXEC_STACK_DIRECTIVE
133
134#elif defined(__ELF__)
135
136#if defined(__arm__)
137#define SYMBOL_IS_FUNC(name) .type name,%function
138#else
139#define SYMBOL_IS_FUNC(name) .type name,@function
140#endif
141#define HIDDEN_SYMBOL(name) .hidden name
142#if defined(_LIBUNWIND_HIDE_SYMBOLS)
143#define EXPORT_SYMBOL(name) HIDDEN_SYMBOL(name)
144#else
145#define EXPORT_SYMBOL(name)
146#endif
147#define WEAK_SYMBOL(name) .weak name
148
149#if defined(__hexagon__)
150#define WEAK_ALIAS(name, aliasname)                                            \
151  EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR                              \
152  WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR                                \
153  .equiv SYMBOL_NAME(aliasname), SYMBOL_NAME(name)
154#else
155#define WEAK_ALIAS(name, aliasname)                                            \
156  EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR                              \
157  WEAK_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR                                \
158  SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
159#endif
160
161#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
162    defined(__linux__)
163#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
164#else
165#define NO_EXEC_STACK_DIRECTIVE
166#endif
167
168#elif defined(_WIN32)
169
170#define SYMBOL_IS_FUNC(name)                                                   \
171  .def name SEPARATOR                                                          \
172    .scl 2 SEPARATOR                                                           \
173    .type 32 SEPARATOR                                                         \
174  .endef
175#define EXPORT_SYMBOL2(name)                                                   \
176  .section .drectve,"yn" SEPARATOR                                             \
177  .ascii "-export:", #name, "\0" SEPARATOR                                     \
178  .text
179#if defined(_LIBUNWIND_HIDE_SYMBOLS)
180#define EXPORT_SYMBOL(name)
181#else
182#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
183#endif
184#define HIDDEN_SYMBOL(name)
185
186#if defined(__MINGW32__)
187#define WEAK_ALIAS(name, aliasname)                                            \
188  .globl SYMBOL_NAME(aliasname) SEPARATOR                                      \
189  EXPORT_SYMBOL(aliasname) SEPARATOR                                           \
190  SYMBOL_NAME(aliasname) = SYMBOL_NAME(name)
191#else
192#define WEAK_ALIAS3(name, aliasname)                                           \
193  .section .drectve,"yn" SEPARATOR                                             \
194  .ascii "-alternatename:", #aliasname, "=", #name, "\0" SEPARATOR             \
195  .text
196#define WEAK_ALIAS2(name, aliasname)                                           \
197  WEAK_ALIAS3(name, aliasname)
198#define WEAK_ALIAS(name, aliasname)                                            \
199  EXPORT_SYMBOL(SYMBOL_NAME(aliasname)) SEPARATOR                              \
200  WEAK_ALIAS2(SYMBOL_NAME(name), SYMBOL_NAME(aliasname))
201#endif
202
203#define NO_EXEC_STACK_DIRECTIVE
204
205#elif defined(__sparc__)
206
207#elif defined(_AIX)
208
209#if defined(__powerpc64__)
210#define VBYTE_LEN 8
211#define CSECT_ALIGN 3
212#else
213#define VBYTE_LEN 4
214#define CSECT_ALIGN 2
215#endif
216
217// clang-format off
218#define DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(name, aliasname)              \
219  .csect .text[PR], 2 SEPARATOR                                                \
220  .csect .name[PR], 2 SEPARATOR                                                \
221  .globl name[DS] SEPARATOR                                                    \
222  .globl .name[PR] SEPARATOR                                                   \
223  .align 4 SEPARATOR                                                           \
224  .csect name[DS], CSECT_ALIGN SEPARATOR                                       \
225aliasname:                                                                     \
226  .vbyte VBYTE_LEN, .name[PR] SEPARATOR                                        \
227  .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR                                         \
228  .vbyte VBYTE_LEN, 0 SEPARATOR                                                \
229  .weak  aliasname SEPARATOR                                                   \
230  .weak  .aliasname SEPARATOR                                                  \
231  .csect .name[PR], 2 SEPARATOR                                                \
232.aliasname:                                                                    \
233
234#define WEAK_ALIAS(name, aliasname)
235#define NO_EXEC_STACK_DIRECTIVE
236
237// clang-format on
238#else
239
240#error Unsupported target
241
242#endif
243
244#if defined(_AIX)
245  // clang-format off
246#define DEFINE_LIBUNWIND_FUNCTION(name)                                        \
247  .globl name[DS] SEPARATOR                                                    \
248  .globl .name SEPARATOR                                                       \
249  .align 4 SEPARATOR                                                           \
250  .csect name[DS], CSECT_ALIGN SEPARATOR                                       \
251  .vbyte VBYTE_LEN, .name SEPARATOR                                            \
252  .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR                                         \
253  .vbyte VBYTE_LEN, 0 SEPARATOR                                                \
254  .csect .text[PR], 2 SEPARATOR                                                \
255.name:
256  // clang-format on
257#else
258#define DEFINE_LIBUNWIND_FUNCTION(name)                                        \
259  .globl SYMBOL_NAME(name) SEPARATOR                                           \
260  HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                                   \
261  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
262  PPC64_OPD1                                                                   \
263  SYMBOL_NAME(name):                                                           \
264  PPC64_OPD2                                                                   \
265  AARCH64_BTI
266#endif
267
268#if defined(__arm__)
269#if !defined(__ARM_ARCH)
270#define __ARM_ARCH 4
271#endif
272
273#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
274#define ARM_HAS_BX
275#endif
276
277#ifdef ARM_HAS_BX
278#define JMP(r) bx r
279#else
280#define JMP(r) mov pc, r
281#endif
282#endif /* __arm__ */
283
284#if defined(__powerpc__)
285#define PPC_LEFT_SHIFT(index) << (index)
286#endif
287
288#endif /* UNWIND_ASSEMBLY_H */
289