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