• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2008 CodeSourcery
3 
4 This file is part of libunwind.
5 
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13 
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
24 
25 #ifndef LIBUNWIND_H
26 #define LIBUNWIND_H
27 
28 #if defined(__cplusplus) || defined(c_plusplus)
29 extern "C" {
30 #endif
31 
32 #include <inttypes.h>
33 #include <stddef.h>
34 
35 #ifndef UNW_EMPTY_STRUCT
36 #  ifdef __GNUC__
37 #    define UNW_EMPTY_STRUCT
38 #  else
39 #    define UNW_EMPTY_STRUCT uint8_t unused;
40 #  endif
41 #endif
42 
43 #define UNW_TARGET      arm
44 #define UNW_TARGET_ARM  1
45 
46 #define _U_TDEP_QP_TRUE 0       /* see libunwind-dynamic.h  */
47 
48 /* This needs to be big enough to accommodate "struct cursor", while
49    leaving some slack for future expansion.  Changing this value will
50    require recompiling all users of this library.  Stack allocation is
51    relatively cheap and unwind-state copying is relatively rare, so we
52    want to err on making it rather too big than too small.  */
53 
54 /* FIXME for ARM. Too big?  What do other things use for similar tasks?  */
55 #define UNW_TDEP_CURSOR_LEN     4096
56 
57 typedef uint32_t unw_word_t;
58 typedef int32_t unw_sword_t;
59 
60 typedef long double unw_tdep_fpreg_t;
61 
62 typedef enum
63   {
64     UNW_ARM_R0,
65     UNW_ARM_R1,
66     UNW_ARM_R2,
67     UNW_ARM_R3,
68     UNW_ARM_R4,
69     UNW_ARM_R5,
70     UNW_ARM_R6,
71     UNW_ARM_R7,
72     UNW_ARM_R8,
73     UNW_ARM_R9,
74     UNW_ARM_R10,
75     UNW_ARM_R11,
76     UNW_ARM_R12,
77     UNW_ARM_R13,
78     UNW_ARM_R14,
79     UNW_ARM_R15,
80 
81     /* VFPv2 s0-s31 (obsolescent numberings).  */
82     UNW_ARM_S0 = 64,
83     UNW_ARM_S1,
84     UNW_ARM_S2,
85     UNW_ARM_S3,
86     UNW_ARM_S4,
87     UNW_ARM_S5,
88     UNW_ARM_S6,
89     UNW_ARM_S7,
90     UNW_ARM_S8,
91     UNW_ARM_S9,
92     UNW_ARM_S10,
93     UNW_ARM_S11,
94     UNW_ARM_S12,
95     UNW_ARM_S13,
96     UNW_ARM_S14,
97     UNW_ARM_S15,
98     UNW_ARM_S16,
99     UNW_ARM_S17,
100     UNW_ARM_S18,
101     UNW_ARM_S19,
102     UNW_ARM_S20,
103     UNW_ARM_S21,
104     UNW_ARM_S22,
105     UNW_ARM_S23,
106     UNW_ARM_S24,
107     UNW_ARM_S25,
108     UNW_ARM_S26,
109     UNW_ARM_S27,
110     UNW_ARM_S28,
111     UNW_ARM_S29,
112     UNW_ARM_S30,
113     UNW_ARM_S31,
114 
115     /* FPA register numberings.  */
116     UNW_ARM_F0 = 96,
117     UNW_ARM_F1,
118     UNW_ARM_F2,
119     UNW_ARM_F3,
120     UNW_ARM_F4,
121     UNW_ARM_F5,
122     UNW_ARM_F6,
123     UNW_ARM_F7,
124 
125     /* iWMMXt GR register numberings.  */
126     UNW_ARM_wCGR0 = 104,
127     UNW_ARM_wCGR1,
128     UNW_ARM_wCGR2,
129     UNW_ARM_wCGR3,
130     UNW_ARM_wCGR4,
131     UNW_ARM_wCGR5,
132     UNW_ARM_wCGR6,
133     UNW_ARM_wCGR7,
134 
135     /* iWMMXt register numberings.  */
136     UNW_ARM_wR0 = 112,
137     UNW_ARM_wR1,
138     UNW_ARM_wR2,
139     UNW_ARM_wR3,
140     UNW_ARM_wR4,
141     UNW_ARM_wR5,
142     UNW_ARM_wR6,
143     UNW_ARM_wR7,
144     UNW_ARM_wR8,
145     UNW_ARM_wR9,
146     UNW_ARM_wR10,
147     UNW_ARM_wR11,
148     UNW_ARM_wR12,
149     UNW_ARM_wR13,
150     UNW_ARM_wR14,
151     UNW_ARM_wR15,
152 
153     /* Two-byte encodings from here on.  */
154 
155     /* SPSR.  */
156     UNW_ARM_SPSR = 128,
157     UNW_ARM_SPSR_FIQ,
158     UNW_ARM_SPSR_IRQ,
159     UNW_ARM_SPSR_ABT,
160     UNW_ARM_SPSR_UND,
161     UNW_ARM_SPSR_SVC,
162 
163     /* User mode registers.  */
164     UNW_ARM_R8_USR = 144,
165     UNW_ARM_R9_USR,
166     UNW_ARM_R10_USR,
167     UNW_ARM_R11_USR,
168     UNW_ARM_R12_USR,
169     UNW_ARM_R13_USR,
170     UNW_ARM_R14_USR,
171 
172     /* FIQ registers.  */
173     UNW_ARM_R8_FIQ = 151,
174     UNW_ARM_R9_FIQ,
175     UNW_ARM_R10_FIQ,
176     UNW_ARM_R11_FIQ,
177     UNW_ARM_R12_FIQ,
178     UNW_ARM_R13_FIQ,
179     UNW_ARM_R14_FIQ,
180 
181     /* IRQ registers.  */
182     UNW_ARM_R13_IRQ = 158,
183     UNW_ARM_R14_IRQ,
184 
185     /* ABT registers.  */
186     UNW_ARM_R13_ABT = 160,
187     UNW_ARM_R14_ABT,
188 
189     /* UND registers.  */
190     UNW_ARM_R13_UND = 162,
191     UNW_ARM_R14_UND,
192 
193     /* SVC registers.  */
194     UNW_ARM_R13_SVC = 164,
195     UNW_ARM_R14_SVC,
196 
197     /* iWMMXt control registers.  */
198     UNW_ARM_wC0 = 192,
199     UNW_ARM_wC1,
200     UNW_ARM_wC2,
201     UNW_ARM_wC3,
202     UNW_ARM_wC4,
203     UNW_ARM_wC5,
204     UNW_ARM_wC6,
205     UNW_ARM_wC7,
206 
207     /* VFPv3/Neon 64-bit registers.  */
208     UNW_ARM_D0 = 256,
209     UNW_ARM_D1,
210     UNW_ARM_D2,
211     UNW_ARM_D3,
212     UNW_ARM_D4,
213     UNW_ARM_D5,
214     UNW_ARM_D6,
215     UNW_ARM_D7,
216     UNW_ARM_D8,
217     UNW_ARM_D9,
218     UNW_ARM_D10,
219     UNW_ARM_D11,
220     UNW_ARM_D12,
221     UNW_ARM_D13,
222     UNW_ARM_D14,
223     UNW_ARM_D15,
224     UNW_ARM_D16,
225     UNW_ARM_D17,
226     UNW_ARM_D18,
227     UNW_ARM_D19,
228     UNW_ARM_D20,
229     UNW_ARM_D21,
230     UNW_ARM_D22,
231     UNW_ARM_D23,
232     UNW_ARM_D24,
233     UNW_ARM_D25,
234     UNW_ARM_D26,
235     UNW_ARM_D27,
236     UNW_ARM_D28,
237     UNW_ARM_D29,
238     UNW_ARM_D30,
239     UNW_ARM_D31,
240 
241     /* For ARM, the CFA is the value of SP (r13) at the call site in the
242        previous frame.  */
243     UNW_ARM_CFA,
244 
245     UNW_TDEP_LAST_REG = UNW_ARM_D31,
246 
247     UNW_TDEP_IP = UNW_ARM_R15,
248     UNW_TDEP_SP = UNW_ARM_R13,
249     UNW_TDEP_EH = UNW_ARM_R0   /* FIXME.  */
250   }
251 arm_regnum_t;
252 
253 #define UNW_TDEP_NUM_EH_REGS    2       /* FIXME for ARM.  */
254 
255 typedef struct unw_tdep_save_loc
256   {
257     /* Additional target-dependent info on a save location.  */
258     uint8_t placeholder;
259   }
260 unw_tdep_save_loc_t;
261 
262 /* On ARM, we define our own unw_tdep_context instead of using ucontext_t.
263    This allows us to support systems that don't support getcontext and
264    therefore do not define ucontext_t.  */
265 typedef struct unw_tdep_context
266   {
267     unsigned long regs[16];
268   }
269 unw_tdep_context_t;
270 
271 /* FIXME: this is a stub version which only saves GP registers.  Not ideal, but
272    may be sufficient for all libunwind use cases.
273    In thumb mode, we return directly back to thumb mode on return (with bx), to
274    avoid altering any registers after unw_resume. */
275 #ifndef __thumb__
276 #define unw_tdep_getcontext(uc) ({					\
277   unw_tdep_context_t *unw_ctx = (uc);					\
278   register unsigned long *r0 __asm__ ("r0");				\
279   unsigned long *unw_base = unw_ctx->regs;				\
280   __asm__ __volatile__ (						\
281     "mov r0, #0\n"							\
282     "stmia %[base], {r0-r15}\n"						\
283     "nop\n" /* align return address to value stored by stmia */		\
284     : [r0] "=r" (r0) : [base] "r" (unw_base) : "memory");		\
285   (int)r0; })
286 #else /* __thumb__ */
287 #define unw_tdep_getcontext(uc) ({					\
288   unw_tdep_context_t *unw_ctx = (uc);					\
289   register unsigned long *r0 __asm__ ("r0");				\
290   unsigned long *unw_base = unw_ctx->regs;				\
291   __asm__ __volatile__ (						\
292     ".align 2\n"							\
293     "bx pc\n"								\
294     "nop\n"								\
295     ".code 32\n"							\
296     "mov r0, #0\n"							\
297     "stmia %[base], {r0-r14}\n"						\
298     "adr r0, ret%=+1\n"							\
299     "str r0, [%[base], #60]\n"						\
300     "orr r0, pc, #1\n"							\
301     "bx r0\n"								\
302     ".code 16\n"							\
303     "mov r0, #0\n"							\
304     "ret%=:\n"								\
305     : [r0] "=r" (r0) : [base] "r" (unw_base) : "memory", "cc");		\
306   (int)r0; })
307 #endif
308 
309 #include "libunwind-dynamic.h"
310 
311 typedef struct
312   {
313     /* no arm-specific auxiliary proc-info */
314     uint8_t placeholder;
315   }
316 unw_tdep_proc_info_t;
317 
318 #include "libunwind-common.h"
319 
320 #define unw_tdep_is_fpreg               UNW_ARCH_OBJ(is_fpreg)
321 extern int unw_tdep_is_fpreg (int);
322 
323 #if defined(__cplusplus) || defined(c_plusplus)
324 }
325 #endif
326 
327 #endif /* LIBUNWIND_H */
328