• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2001-2004 Hewlett-Packard Co
3         Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4    Copyright (C) 2013 Linaro Limited
5 
6 This file is part of libunwind.
7 
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15 
16 The above copyright notice and this permission notice shall be
17 included in all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
26 
27 #ifndef LIBUNWIND_H
28 #define LIBUNWIND_H
29 
30 #if defined(__cplusplus) || defined(c_plusplus)
31 extern "C" {
32 #endif
33 
34 #include <inttypes.h>
35 #include <stddef.h>
36 #include <ucontext.h>
37 #include <stdalign.h>
38 
39 #ifndef UNW_EMPTY_STRUCT
40 #  ifdef __GNUC__
41 #    define UNW_EMPTY_STRUCT
42 #  else
43 #    define UNW_EMPTY_STRUCT uint8_t unused;
44 #  endif
45 #endif
46 
47 #define UNW_TARGET      aarch64
48 #define UNW_TARGET_AARCH64      1
49 
50 #define _U_TDEP_QP_TRUE 0       /* see libunwind-dynamic.h  */
51 
52 /* This needs to be big enough to accommodate "struct cursor", while
53    leaving some slack for future expansion.  Changing this value will
54    require recompiling all users of this library.  Stack allocation is
55    relatively cheap and unwind-state copying is relatively rare, so we
56    want to err on making it rather too big than too small.
57 
58    Calculation is regs used (64 + 34) * 2 + 40 (bytes of rest of
59    cursor) + padding
60 */
61 
62 #define UNW_TDEP_CURSOR_LEN     250
63 
64 typedef uint64_t unw_word_t;
65 typedef int64_t unw_sword_t;
66 
67 typedef long double unw_tdep_fpreg_t;
68 
69 typedef struct
70   {
71     /* no aarch64-specific auxiliary proc-info */
72     UNW_EMPTY_STRUCT
73   }
74 unw_tdep_proc_info_t;
75 
76 typedef enum
77   {
78     /* 64-bit general registers.  */
79     UNW_AARCH64_X0,
80     UNW_AARCH64_X1,
81     UNW_AARCH64_X2,
82     UNW_AARCH64_X3,
83     UNW_AARCH64_X4,
84     UNW_AARCH64_X5,
85     UNW_AARCH64_X6,
86     UNW_AARCH64_X7,
87     UNW_AARCH64_X8,
88 
89     /* Temporary registers.  */
90     UNW_AARCH64_X9,
91     UNW_AARCH64_X10,
92     UNW_AARCH64_X11,
93     UNW_AARCH64_X12,
94     UNW_AARCH64_X13,
95     UNW_AARCH64_X14,
96     UNW_AARCH64_X15,
97 
98     /* Intra-procedure-call temporary registers.  */
99     UNW_AARCH64_X16,
100     UNW_AARCH64_X17,
101 
102     /* Callee-saved registers.  */
103     UNW_AARCH64_X18,
104     UNW_AARCH64_X19,
105     UNW_AARCH64_X20,
106     UNW_AARCH64_X21,
107     UNW_AARCH64_X22,
108     UNW_AARCH64_X23,
109     UNW_AARCH64_X24,
110     UNW_AARCH64_X25,
111     UNW_AARCH64_X26,
112     UNW_AARCH64_X27,
113     UNW_AARCH64_X28,
114 
115     /* 64-bit frame pointer.  */
116     UNW_AARCH64_X29,
117 
118     /* 64-bit link register.  */
119     UNW_AARCH64_X30,
120 
121     /* 64-bit stack pointer.  */
122     UNW_AARCH64_SP =  31,
123     UNW_AARCH64_PC,
124     UNW_AARCH64_PSTATE,
125 
126     /* 128-bit FP/Advanced SIMD registers.  */
127     UNW_AARCH64_V0 = 64,
128     UNW_AARCH64_V1,
129     UNW_AARCH64_V2,
130     UNW_AARCH64_V3,
131     UNW_AARCH64_V4,
132     UNW_AARCH64_V5,
133     UNW_AARCH64_V6,
134     UNW_AARCH64_V7,
135     UNW_AARCH64_V8,
136     UNW_AARCH64_V9,
137     UNW_AARCH64_V10,
138     UNW_AARCH64_V11,
139     UNW_AARCH64_V12,
140     UNW_AARCH64_V13,
141     UNW_AARCH64_V14,
142     UNW_AARCH64_V15,
143     UNW_AARCH64_V16,
144     UNW_AARCH64_V17,
145     UNW_AARCH64_V18,
146     UNW_AARCH64_V19,
147     UNW_AARCH64_V20,
148     UNW_AARCH64_V21,
149     UNW_AARCH64_V22,
150     UNW_AARCH64_V23,
151     UNW_AARCH64_V24,
152     UNW_AARCH64_V25,
153     UNW_AARCH64_V26,
154     UNW_AARCH64_V27,
155     UNW_AARCH64_V28,
156     UNW_AARCH64_V29,
157     UNW_AARCH64_V30,
158     UNW_AARCH64_V31,
159 
160     UNW_AARCH64_FPSR,
161     UNW_AARCH64_FPCR,
162 
163     /* For AArch64, the CFA is the value of SP (x31) at the call site of the
164        previous frame.  */
165     UNW_AARCH64_CFA = UNW_AARCH64_SP,
166 
167     UNW_TDEP_LAST_REG = UNW_AARCH64_FPCR,
168 
169     UNW_TDEP_IP = UNW_AARCH64_X30,
170     UNW_TDEP_SP = UNW_AARCH64_SP,
171     UNW_TDEP_EH = UNW_AARCH64_X0,
172 
173   }
174 aarch64_regnum_t;
175 
176 /* Use R0 through R3 to pass exception handling information.  */
177 #define UNW_TDEP_NUM_EH_REGS    4
178 
179 typedef struct unw_tdep_save_loc
180   {
181     /* Additional target-dependent info on a save location.  */
182     UNW_EMPTY_STRUCT
183   }
184 unw_tdep_save_loc_t;
185 
186 #ifdef __linux__
187 /* On AArch64, we can directly use ucontext_t as the unwind context,
188  * however, the __reserved struct is quite large: tune it down to only
189  * the necessary used fields.  */
190 
191 struct unw_sigcontext
192   {
193 	uint64_t fault_address;
194 	uint64_t regs[31];
195 	uint64_t sp;
196 	uint64_t pc;
197 	uint64_t pstate;
198 	alignas(16) uint8_t __reserved[(66 * 8)];
199 };
200 
201 typedef struct
202   {
203 	unsigned long uc_flags;
204 	struct ucontext *uc_link;
205 	stack_t uc_stack;
206 #ifndef __ANDROID__
207 	sigset_t uc_sigmask;
208 #else
209 	union {
210 		sigset_t uc_sigmask;
211 		sigset64_t uc_sigmask64;
212 	};
213 	char __padding[128 - sizeof(sigset_t)];
214 #endif
215 	struct unw_sigcontext uc_mcontext;
216   } unw_tdep_context_t;
217 
218 typedef struct
219   {
220 	uint32_t _ctx_magic;
221 	uint32_t _ctx_size;
222 	uint32_t fpsr;
223 	uint32_t fpcr;
224 	uint64_t vregs[64];
225   } unw_fpsimd_context_t;
226 #else
227 /* On AArch64, we can directly use ucontext_t as the unwind context.  */
228 typedef ucontext_t unw_tdep_context_t;
229 #endif
230 
231 
232 #include "libunwind-common.h"
233 #include "libunwind-dynamic.h"
234 
235 #define unw_tdep_getcontext(uc) ({					\
236   unw_tdep_context_t *unw_ctx = (uc);					\
237   register uint64_t unw_base __asm__ ("x0") = (uint64_t) unw_ctx->uc_mcontext.regs; \
238   __asm__ __volatile__ (					        \
239      "stp x0, x1, [%[base], #0]\n" \
240      "stp x2, x3, [%[base], #16]\n" \
241      "stp x4, x5, [%[base], #32]\n" \
242      "stp x6, x7, [%[base], #48]\n" \
243      "stp x8, x9, [%[base], #64]\n" \
244      "stp x10, x11, [%[base], #80]\n" \
245      "stp x12, x13, [%[base], #96]\n" \
246      "stp x14, x13, [%[base], #112]\n" \
247      "stp x16, x17, [%[base], #128]\n" \
248      "stp x18, x19, [%[base], #144]\n" \
249      "stp x20, x21, [%[base], #160]\n" \
250      "stp x22, x23, [%[base], #176]\n" \
251      "stp x24, x25, [%[base], #192]\n" \
252      "stp x26, x27, [%[base], #208]\n" \
253      "stp x28, x29, [%[base], #224]\n" \
254      "mov x1, sp\n" \
255      "stp x30, x1, [%[base], #240]\n" \
256      "adr x1, ret%=\n" \
257      "str x1, [%[base], #256]\n" \
258      "mov %[base], #0\n" \
259      "ret%=:\n" \
260      : [base] "+r" (unw_base) : : "x1", "memory"); \
261   (int)unw_base; })
262 #define unw_tdep_is_fpreg		UNW_ARCH_OBJ(is_fpreg)
263 
264 extern int unw_tdep_is_fpreg (int);
265 
266 #if defined(__cplusplus) || defined(c_plusplus)
267 }
268 #endif
269 
270 #endif /* LIBUNWIND_H */
271