1 /* libunwind - a platform-independent unwind library 2 Copyright (C) 2001-2005 Hewlett-Packard Co 3 Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com> 4 5 This file is part of libunwind. 6 7 Permission is hereby granted, free of charge, to any person obtaining 8 a copy of this software and associated documentation files (the 9 "Software"), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, sublicense, and/or sell copies of the Software, and to 12 permit persons to whom the Software is furnished to do so, subject to 13 the following conditions: 14 15 The above copyright notice and this permission notice shall be 16 included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 25 26 #ifndef unwind_i_h 27 #define unwind_i_h 28 29 #include <string.h> 30 #include <inttypes.h> 31 32 #include <libunwind-ia64.h> 33 34 #include "rse.h" 35 36 #include "libunwind_i.h" 37 38 #define IA64_UNW_VER(x) ((x) >> 48) 39 #define IA64_UNW_FLAG_MASK ((unw_word_t) 0x0000ffff00000000ULL) 40 #define IA64_UNW_FLAG_OSMASK ((unw_word_t) 0x0000f00000000000ULL) 41 #define IA64_UNW_FLAG_EHANDLER(x) ((x) & (unw_word_t) 0x0000000100000000ULL) 42 #define IA64_UNW_FLAG_UHANDLER(x) ((x) & (unw_word_t) 0x0000000200000000ULL) 43 #define IA64_UNW_LENGTH(x) ((x) & (unw_word_t) 0x00000000ffffffffULL) 44 45 #ifdef MIN 46 # undef MIN 47 #endif 48 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 49 50 #if !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY) 51 52 static ALWAYS_INLINE void * 53 inlined_uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr) 54 { 55 unw_word_t reg_addr; 56 void *addr; 57 58 switch (reg) 59 { 60 case UNW_IA64_GR + 0: addr = &unw.read_only.r0; break; 61 case UNW_IA64_NAT + 0: addr = &unw.read_only.r0; break; 62 case UNW_IA64_FR + 0: addr = &unw.read_only.f0; break; 63 case UNW_IA64_FR + 1: 64 if (__BYTE_ORDER == __BIG_ENDIAN) 65 addr = &unw.read_only.f1_be; 66 else 67 addr = &unw.read_only.f1_le; 68 break; 69 case UNW_IA64_IP: addr = &uc->uc_mcontext.sc_br[0]; break; 70 case UNW_IA64_CFM: addr = &uc->uc_mcontext.sc_ar_pfs; break; 71 case UNW_IA64_AR_RNAT: addr = &uc->uc_mcontext.sc_ar_rnat; break; 72 case UNW_IA64_AR_UNAT: addr = &uc->uc_mcontext.sc_ar_unat; break; 73 case UNW_IA64_AR_LC: addr = &uc->uc_mcontext.sc_ar_lc; break; 74 case UNW_IA64_AR_FPSR: addr = &uc->uc_mcontext.sc_ar_fpsr; break; 75 case UNW_IA64_PR: addr = &uc->uc_mcontext.sc_pr; break; 76 case UNW_IA64_AR_BSPSTORE: addr = &uc->uc_mcontext.sc_ar_bsp; break; 77 78 case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: 79 case UNW_IA64_GR + 12: 80 addr = &uc->uc_mcontext.sc_gr[reg - UNW_IA64_GR]; 81 break; 82 83 case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7: 84 case UNW_IA64_NAT + 12: 85 addr = &uc->uc_mcontext.sc_nat; 86 reg_addr = (unw_word_t) &uc->uc_mcontext.sc_gr[reg - UNW_IA64_NAT]; 87 *nat_bitnr = reg - UNW_IA64_NAT; 88 break; 89 90 case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5: 91 addr = &uc->uc_mcontext.sc_br[reg - UNW_IA64_BR]; 92 break; 93 94 case UNW_IA64_FR+ 2 ... UNW_IA64_FR+ 5: 95 case UNW_IA64_FR+16 ... UNW_IA64_FR+31: 96 addr = &uc->uc_mcontext.sc_fr[reg - UNW_IA64_FR]; 97 break; 98 99 default: 100 addr = NULL; 101 } 102 return addr; 103 } 104 105 static inline void * 106 uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr) 107 { 108 if (__builtin_constant_p (reg)) 109 return inlined_uc_addr (uc, reg, nat_bitnr); 110 else 111 return tdep_uc_addr (uc, reg, nat_bitnr); 112 } 113 114 /* Return TRUE if ADDR points inside unw.read_only_reg. */ 115 116 static inline long 117 ia64_read_only_reg (void *addr) 118 { 119 return ((unsigned long) ((char *) addr - (char *) &unw.read_only) 120 < sizeof (unw.read_only)); 121 } 122 123 #endif /* !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY) */ 124 125 /* Bits 0 and 1 of a location are used to encode its type: 126 bit 0: set if location uses floating-point format. 127 bit 1: set if location is a NaT bit on memory stack. */ 128 129 #define IA64_LOC_TYPE_FP (1 << 0) 130 #define IA64_LOC_TYPE_MEMSTK_NAT (1 << 1) 131 132 #ifdef UNW_LOCAL_ONLY 133 #define IA64_LOC_REG(r,t) (((r) << 2) | (t)) 134 #define IA64_LOC_ADDR(a,t) (((a) & ~0x3) | (t)) 135 #define IA64_LOC_UC_ADDR(a,t) IA64_LOC_ADDR(a, t) 136 #define IA64_NULL_LOC (0) 137 138 #define IA64_GET_REG(l) ((l) >> 2) 139 #define IA64_GET_ADDR(l) ((l) & ~0x3) 140 #define IA64_IS_NULL_LOC(l) ((l) == 0) 141 #define IA64_IS_FP_LOC(l) (((l) & IA64_LOC_TYPE_FP) != 0) 142 #define IA64_IS_MEMSTK_NAT(l) (((l) & IA64_LOC_TYPE_MEMSTK_NAT) != 0) 143 #define IA64_IS_REG_LOC(l) 0 144 #define IA64_IS_UC_LOC(l) 0 145 146 #define IA64_REG_LOC(c,r) ((unw_word_t) uc_addr((c)->as_arg, r, NULL)) 147 #define IA64_REG_NAT_LOC(c,r,n) ((unw_word_t) uc_addr((c)->as_arg, r, n)) 148 #define IA64_FPREG_LOC(c,r) \ 149 ((unw_word_t) uc_addr((c)->as_arg, (r), NULL) | IA64_LOC_TYPE_FP) 150 151 # define ia64_find_proc_info(c,ip,n) \ 152 tdep_find_proc_info(unw_local_addr_space, (ip), &(c)->pi, (n), \ 153 (c)->as_arg) 154 # define ia64_put_unwind_info(c, pi) do { ; } while (0) 155 156 /* Note: the register accessors (ia64_{get,set}{,fp}()) must check for 157 NULL locations because uc_addr() returns NULL for unsaved 158 registers. */ 159 160 static inline int 161 ia64_getfp (struct cursor *c, unw_word_t loc, unw_fpreg_t *val) 162 { 163 if (IA64_IS_NULL_LOC (loc)) 164 { 165 Debug (16, "access to unsaved register\n"); 166 return -UNW_EBADREG; 167 } 168 *val = *(unw_fpreg_t *) IA64_GET_ADDR (loc); 169 return 0; 170 } 171 172 static inline int 173 ia64_putfp (struct cursor *c, unw_word_t loc, unw_fpreg_t val) 174 { 175 unw_fpreg_t *addr = (unw_fpreg_t *) IA64_GET_ADDR (loc); 176 177 if (IA64_IS_NULL_LOC (loc)) 178 { 179 Debug (16, "access to unsaved register\n"); 180 return -UNW_EBADREG; 181 } 182 else if (ia64_read_only_reg (addr)) 183 { 184 Debug (16, "attempt to read-only register\n"); 185 return -UNW_EREADONLYREG; 186 } 187 *addr = val; 188 return 0; 189 } 190 191 static inline int 192 ia64_get (struct cursor *c, unw_word_t loc, unw_word_t *val) 193 { 194 if (IA64_IS_NULL_LOC (loc)) 195 { 196 Debug (16, "access to unsaved register\n"); 197 return -UNW_EBADREG; 198 } 199 *val = *(unw_word_t *) IA64_GET_ADDR (loc); 200 return 0; 201 } 202 203 static inline int 204 ia64_put (struct cursor *c, unw_word_t loc, unw_word_t val) 205 { 206 unw_word_t *addr = (unw_word_t *) IA64_GET_ADDR (loc); 207 208 if (IA64_IS_NULL_LOC (loc)) 209 { 210 Debug (16, "access to unsaved register\n"); 211 return -UNW_EBADREG; 212 } 213 else if (ia64_read_only_reg (addr)) 214 { 215 Debug (16, "attempt to read-only register\n"); 216 return -UNW_EREADONLYREG; 217 } 218 *addr = val; 219 return 0; 220 } 221 222 #else /* !UNW_LOCAL_ONLY */ 223 224 /* Bits 0 and 1 of the second word (w1) of a location are used 225 to further distinguish what location we're dealing with: 226 227 bit 0: set if the location is a register 228 bit 1: set of the location is accessed via uc_access(3) */ 229 #define IA64_LOC_TYPE_REG (1 << 0) 230 #define IA64_LOC_TYPE_UC (1 << 1) 231 232 #define IA64_LOC_REG(r,t) ((ia64_loc_t) { ((r) << 2) | (t), \ 233 IA64_LOC_TYPE_REG }) 234 #define IA64_LOC_ADDR(a,t) ((ia64_loc_t) { ((a) & ~0x3) | (t), 0 }) 235 #define IA64_LOC_UC_ADDR(a,t) ((ia64_loc_t) { ((a) & ~0x3) | (t), \ 236 IA64_LOC_TYPE_UC }) 237 #define IA64_LOC_UC_REG(r,a) ((ia64_loc_t) { ((r) << 2), \ 238 ((a) | IA64_LOC_TYPE_REG \ 239 | IA64_LOC_TYPE_UC) }) 240 #define IA64_NULL_LOC ((ia64_loc_t) { 0, 0 }) 241 242 #define IA64_GET_REG(l) ((l).w0 >> 2) 243 #define IA64_GET_ADDR(l) ((l).w0 & ~0x3) 244 #define IA64_GET_AUX_ADDR(l) ((l).w1 & ~0x3) 245 #define IA64_IS_NULL_LOC(l) (((l).w0 | (l).w1) == 0) 246 #define IA64_IS_FP_LOC(l) (((l).w0 & IA64_LOC_TYPE_FP) != 0) 247 #define IA64_IS_MEMSTK_NAT(l) (((l).w0 & IA64_LOC_TYPE_MEMSTK_NAT) != 0) 248 #define IA64_IS_REG_LOC(l) (((l).w1 & IA64_LOC_TYPE_REG) != 0) 249 #define IA64_IS_UC_LOC(l) (((l).w1 & IA64_LOC_TYPE_UC) != 0) 250 251 #define IA64_REG_LOC(c,r) IA64_LOC_REG ((r), 0) 252 #define IA64_REG_NAT_LOC(c,r,n) IA64_LOC_REG ((r), 0) 253 #define IA64_FPREG_LOC(c,r) IA64_LOC_REG ((r), IA64_LOC_TYPE_FP) 254 255 # define ia64_find_proc_info(c,ip,n) \ 256 (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ 257 (c)->as_arg) 258 # define ia64_put_unwind_info(c,pi) \ 259 (*(c)->as->acc.put_unwind_info)((c)->as, (pi), (c)->as_arg) 260 261 #define ia64_uc_access_reg UNW_OBJ(uc_access_reg) 262 #define ia64_uc_access_fpreg UNW_OBJ(uc_access_fpreg) 263 264 extern int ia64_uc_access_reg (struct cursor *c, ia64_loc_t loc, 265 unw_word_t *valp, int write); 266 extern int ia64_uc_access_fpreg (struct cursor *c, ia64_loc_t loc, 267 unw_fpreg_t *valp, int write); 268 269 static inline int 270 ia64_getfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t *val) 271 { 272 unw_word_t addr; 273 int ret; 274 275 if (IA64_IS_NULL_LOC (loc)) 276 { 277 Debug (16, "access to unsaved register\n"); 278 return -UNW_EBADREG; 279 } 280 281 if (IA64_IS_UC_LOC (loc)) 282 return ia64_uc_access_fpreg (c, loc, val, 0); 283 284 if (IA64_IS_REG_LOC (loc)) 285 return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc), 286 val, 0, c->as_arg); 287 288 addr = IA64_GET_ADDR (loc); 289 ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val->raw.bits[0], 0, 290 c->as_arg); 291 if (ret < 0) 292 return ret; 293 294 return (*c->as->acc.access_mem) (c->as, addr + 8, &val->raw.bits[1], 0, 295 c->as_arg); 296 } 297 298 static inline int 299 ia64_putfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t val) 300 { 301 unw_word_t addr; 302 int ret; 303 304 if (IA64_IS_NULL_LOC (loc)) 305 { 306 Debug (16, "access to unsaved register\n"); 307 return -UNW_EBADREG; 308 } 309 310 if (IA64_IS_UC_LOC (loc)) 311 return ia64_uc_access_fpreg (c, loc, &val, 1); 312 313 if (IA64_IS_REG_LOC (loc)) 314 return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc), &val, 1, 315 c->as_arg); 316 317 addr = IA64_GET_ADDR (loc); 318 ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val.raw.bits[0], 1, 319 c->as_arg); 320 if (ret < 0) 321 return ret; 322 323 return (*c->as->acc.access_mem) (c->as, addr + 8, &val.raw.bits[1], 1, 324 c->as_arg); 325 } 326 327 /* Get the 64 data bits from location LOC. If bit 0 is cleared, LOC 328 is a memory address, otherwise it is a register number. If the 329 register is a floating-point register, the 64 bits are read from 330 the significand bits. */ 331 332 static inline int 333 ia64_get (struct cursor *c, ia64_loc_t loc, unw_word_t *val) 334 { 335 if (IA64_IS_NULL_LOC (loc)) 336 { 337 Debug (16, "access to unsaved register\n"); 338 return -UNW_EBADREG; 339 } 340 341 if (IA64_IS_FP_LOC (loc)) 342 { 343 unw_fpreg_t tmp; 344 int ret; 345 346 ret = ia64_getfp (c, loc, &tmp); 347 if (ret < 0) 348 return ret; 349 350 if (c->as->big_endian) 351 *val = tmp.raw.bits[1]; 352 else 353 *val = tmp.raw.bits[0]; 354 return 0; 355 } 356 357 if (IA64_IS_UC_LOC (loc)) 358 return ia64_uc_access_reg (c, loc, val, 0); 359 360 if (IA64_IS_REG_LOC (loc)) 361 return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), val, 0, 362 c->as_arg); 363 else 364 return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), val, 0, 365 c->as_arg); 366 } 367 368 static inline int 369 ia64_put (struct cursor *c, ia64_loc_t loc, unw_word_t val) 370 { 371 if (IA64_IS_NULL_LOC (loc)) 372 { 373 Debug (16, "access to unsaved register\n"); 374 return -UNW_EBADREG; 375 } 376 377 if (IA64_IS_FP_LOC (loc)) 378 { 379 unw_fpreg_t tmp; 380 381 memset (&tmp, 0, sizeof (tmp)); 382 if (c->as->big_endian) 383 tmp.raw.bits[1] = val; 384 else 385 tmp.raw.bits[0] = val; 386 return ia64_putfp (c, loc, tmp); 387 } 388 389 if (IA64_IS_UC_LOC (loc)) 390 return ia64_uc_access_reg (c, loc, &val, 1); 391 392 if (IA64_IS_REG_LOC (loc)) 393 return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), &val, 1, 394 c->as_arg); 395 else 396 return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), &val, 1, 397 c->as_arg); 398 } 399 400 #endif /* !UNW_LOCAL_ONLY */ 401 402 struct ia64_unwind_block 403 { 404 unw_word_t header; 405 unw_word_t desc[0]; /* unwind descriptors */ 406 407 /* Personality routine and language-specific data follow behind 408 descriptors. */ 409 }; 410 411 enum ia64_where 412 { 413 IA64_WHERE_NONE, /* register isn't saved at all */ 414 IA64_WHERE_GR, /* register is saved in a general register */ 415 IA64_WHERE_FR, /* register is saved in a floating-point register */ 416 IA64_WHERE_BR, /* register is saved in a branch register */ 417 IA64_WHERE_SPREL, /* register is saved on memstack (sp-relative) */ 418 IA64_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */ 419 420 /* At the end of each prologue these locations get resolved to 421 IA64_WHERE_PSPREL and IA64_WHERE_GR, respectively: */ 422 423 IA64_WHERE_SPILL_HOME, /* register is saved in its spill home */ 424 IA64_WHERE_GR_SAVE /* register is saved in next general register */ 425 }; 426 427 #define IA64_WHEN_NEVER 0x7fffffff 428 429 struct ia64_reg_info 430 { 431 unw_word_t val; /* save location: register number or offset */ 432 enum ia64_where where; /* where the register gets saved */ 433 int when; /* when the register gets saved */ 434 }; 435 436 struct ia64_labeled_state; /* opaque structure */ 437 438 struct ia64_reg_state 439 { 440 struct ia64_reg_state *next; /* next (outer) element on state stack */ 441 struct ia64_reg_info reg[IA64_NUM_PREGS]; /* register save locations */ 442 }; 443 444 struct ia64_state_record 445 { 446 unsigned int first_region : 1; /* is this the first region? */ 447 unsigned int done : 1; /* are we done scanning descriptors? */ 448 unsigned int any_spills : 1; /* got any register spills? */ 449 unsigned int in_body : 1; /* are we inside prologue or body? */ 450 uint8_t *imask; /* imask of spill_mask record or NULL */ 451 uint16_t abi_marker; 452 453 unw_word_t pr_val; /* predicate values */ 454 unw_word_t pr_mask; /* predicate mask */ 455 456 long spill_offset; /* psp-relative offset for spill base */ 457 int region_start; 458 int region_len; 459 int when_sp_restored; 460 int epilogue_count; 461 int when_target; 462 463 uint8_t gr_save_loc; /* next save register */ 464 uint8_t return_link_reg; /* branch register used as return pointer */ 465 466 struct ia64_labeled_state *labeled_states; 467 struct ia64_reg_state curr; 468 }; 469 470 struct ia64_labeled_state 471 { 472 struct ia64_labeled_state *next; /* next label (or NULL) */ 473 unsigned long label; /* label for this state */ 474 struct ia64_reg_state saved_state; 475 }; 476 477 /* Convenience macros: */ 478 #define ia64_make_proc_info UNW_OBJ(make_proc_info) 479 #define ia64_fetch_proc_info UNW_OBJ(fetch_proc_info) 480 #define ia64_create_state_record UNW_OBJ(create_state_record) 481 #define ia64_free_state_record UNW_OBJ(free_state_record) 482 #define ia64_find_save_locs UNW_OBJ(find_save_locs) 483 #define ia64_validate_cache UNW_OBJ(ia64_validate_cache) 484 #define ia64_local_validate_cache UNW_OBJ(ia64_local_validate_cache) 485 #define ia64_per_thread_cache UNW_OBJ(per_thread_cache) 486 #define ia64_scratch_loc UNW_OBJ(scratch_loc) 487 #define ia64_local_resume UNW_OBJ(local_resume) 488 #define ia64_local_addr_space_init UNW_OBJ(local_addr_space_init) 489 #define ia64_strloc UNW_OBJ(strloc) 490 #define ia64_install_cursor UNW_OBJ(install_cursor) 491 #define rbs_switch UNW_OBJ(rbs_switch) 492 #define rbs_find_stacked UNW_OBJ(rbs_find_stacked) 493 494 extern int ia64_make_proc_info (struct cursor *c); 495 extern int ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, 496 int need_unwind_info); 497 /* The proc-info must be valid for IP before this routine can be 498 called: */ 499 extern int ia64_create_state_record (struct cursor *c, 500 struct ia64_state_record *sr); 501 extern int ia64_free_state_record (struct ia64_state_record *sr); 502 extern int ia64_find_save_locs (struct cursor *c); 503 extern void ia64_validate_cache (unw_addr_space_t as, void *arg); 504 extern int ia64_local_validate_cache (unw_addr_space_t as, void *arg); 505 extern void ia64_local_addr_space_init (void); 506 extern ia64_loc_t ia64_scratch_loc (struct cursor *c, unw_regnum_t reg, 507 uint8_t *nat_bitnr); 508 509 extern NORETURN void ia64_install_cursor (struct cursor *c, 510 unw_word_t pri_unat, 511 unw_word_t *extra, 512 unw_word_t bspstore, 513 unw_word_t dirty_size, 514 unw_word_t *dirty_partition, 515 unw_word_t dirty_rnat); 516 extern int ia64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, 517 void *arg); 518 extern int rbs_switch (struct cursor *c, 519 unw_word_t saved_bsp, unw_word_t saved_bspstore, 520 ia64_loc_t saved_rnat_loc); 521 extern int rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip, 522 ia64_loc_t *locp, ia64_loc_t *rnat_locp); 523 524 #ifndef UNW_REMOTE_ONLY 525 # define NEED_RBS_COVER_AND_FLUSH 526 # define rbs_cover_and_flush UNW_OBJ(rbs_cover_and_flush) 527 extern int rbs_cover_and_flush (struct cursor *c, unw_word_t nregs, 528 unw_word_t *dirty_partition, 529 unw_word_t *dirty_rnat, 530 unw_word_t *bspstore); 531 #endif 532 533 /* Warning: ia64_strloc() is for debugging only and it is NOT re-entrant! */ 534 extern const char *ia64_strloc (ia64_loc_t loc); 535 536 /* Return true if the register-backing store is inside a ucontext_t 537 that needs to be accessed via uc_access(3). */ 538 539 static inline int 540 rbs_on_uc (struct rbs_area *rbs) 541 { 542 return IA64_IS_UC_LOC (rbs->rnat_loc) && !IA64_IS_REG_LOC (rbs->rnat_loc); 543 } 544 545 /* Return true if BSP points to a word that's stored on register 546 backing-store RBS. */ 547 static inline int 548 rbs_contains (struct rbs_area *rbs, unw_word_t bsp) 549 { 550 int result; 551 552 /* Caveat: this takes advantage of unsigned arithmetic. The full 553 test is (bsp >= rbs->end - rbs->size) && (bsp < rbs->end). We 554 take advantage of the fact that -n == ~n + 1. */ 555 result = bsp - rbs->end > ~rbs->size; 556 Debug (16, "0x%lx in [0x%lx-0x%lx) => %d\n", 557 (long) bsp, (long) (rbs->end - rbs->size), (long) rbs->end, result); 558 return result; 559 } 560 561 static inline ia64_loc_t 562 rbs_get_rnat_loc (struct rbs_area *rbs, unw_word_t bsp) 563 { 564 unw_word_t rnat_addr = rse_rnat_addr (bsp); 565 ia64_loc_t rnat_loc; 566 567 if (rbs_contains (rbs, rnat_addr)) 568 { 569 if (rbs_on_uc (rbs)) 570 rnat_loc = IA64_LOC_UC_ADDR (rnat_addr, 0); 571 else 572 rnat_loc = IA64_LOC_ADDR (rnat_addr, 0); 573 } 574 else 575 rnat_loc = rbs->rnat_loc; 576 return rnat_loc; 577 } 578 579 static inline ia64_loc_t 580 rbs_loc (struct rbs_area *rbs, unw_word_t bsp) 581 { 582 if (rbs_on_uc (rbs)) 583 return IA64_LOC_UC_ADDR (bsp, 0); 584 else 585 return IA64_LOC_ADDR (bsp, 0); 586 } 587 588 static inline int 589 ia64_get_stacked (struct cursor *c, unw_word_t reg, 590 ia64_loc_t *locp, ia64_loc_t *rnat_locp) 591 { 592 struct rbs_area *rbs = c->rbs_area + c->rbs_curr; 593 unw_word_t addr, regs_to_skip = reg - 32; 594 int ret = 0; 595 596 assert (reg >= 32 && reg < 128); 597 598 addr = rse_skip_regs (c->bsp, regs_to_skip); 599 if (locp) 600 *locp = rbs_loc (rbs, addr); 601 if (rnat_locp) 602 *rnat_locp = rbs_get_rnat_loc (rbs, addr); 603 604 if (!rbs_contains (rbs, addr)) 605 ret = rbs_find_stacked (c, regs_to_skip, locp, rnat_locp); 606 return ret; 607 } 608 609 /* The UNaT slot # calculation is identical to the one for RNaT slots, 610 but for readability/clarity, we don't want to use 611 ia64_rnat_slot_num() directly. */ 612 #define ia64_unat_slot_num(addr) rse_slot_num(addr) 613 614 /* The following are helper macros which makes it easier for libunwind 615 to be used in the kernel. They allow the kernel to optimize away 616 any unused code without littering everything with #ifdefs. */ 617 #define ia64_is_big_endian(c) ((c)->as->big_endian) 618 #define ia64_get_abi(c) ((c)->as->abi) 619 #define ia64_set_abi(c, v) ((c)->as->abi = (v)) 620 #define ia64_get_abi_marker(c) ((c)->last_abi_marker) 621 622 /* XXX should be in glibc: */ 623 #ifndef IA64_SC_FLAG_ONSTACK 624 # define IA64_SC_FLAG_ONSTACK_BIT 0 /* running on signal stack? */ 625 # define IA64_SC_FLAG_IN_SYSCALL_BIT 1 /* did signal interrupt a syscall? */ 626 # define IA64_SC_FLAG_FPH_VALID_BIT 2 /* is state in f[32]-f[127] valid? */ 627 628 # define IA64_SC_FLAG_ONSTACK (1 << IA64_SC_FLAG_ONSTACK_BIT) 629 # define IA64_SC_FLAG_IN_SYSCALL (1 << IA64_SC_FLAG_IN_SYSCALL_BIT) 630 # define IA64_SC_FLAG_FPH_VALID (1 << IA64_SC_FLAG_FPH_VALID_BIT) 631 #endif 632 633 #endif /* unwind_i_h */ 634