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 5This file is part of libunwind. 6 7Permission is hereby granted, free of charge, to any person obtaining 8a copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sublicense, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice shall be 16included in all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 25 26#include "unwind_i.h" 27 28/* forward declaration: */ 29static int create_state_record_for (struct cursor *c, 30 struct ia64_state_record *sr, 31 unw_word_t ip); 32 33typedef unsigned long unw_word; 34 35#define alloc_reg_state() (mempool_alloc (&unw.reg_state_pool)) 36#define free_reg_state(rs) (mempool_free (&unw.reg_state_pool, rs)) 37#define alloc_labeled_state() (mempool_alloc (&unw.labeled_state_pool)) 38#define free_labeled_state(s) (mempool_free (&unw.labeled_state_pool, s)) 39 40/* Routines to manipulate the state stack. */ 41 42static inline void 43push (struct ia64_state_record *sr) 44{ 45 struct ia64_reg_state *rs; 46 47 rs = alloc_reg_state (); 48 if (!rs) 49 { 50 print_error ("libunwind: cannot stack reg state!\n"); 51 return; 52 } 53 memcpy (rs, &sr->curr, sizeof (*rs)); 54 sr->curr.next = rs; 55} 56 57static void 58pop (struct ia64_state_record *sr) 59{ 60 struct ia64_reg_state *rs = sr->curr.next; 61 62 if (!rs) 63 { 64 print_error ("libunwind: stack underflow!\n"); 65 return; 66 } 67 memcpy (&sr->curr, rs, sizeof (*rs)); 68 free_reg_state (rs); 69} 70 71/* Make a copy of the state stack. Non-recursive to avoid stack overflows. */ 72static struct ia64_reg_state * 73dup_state_stack (struct ia64_reg_state *rs) 74{ 75 struct ia64_reg_state *copy, *prev = NULL, *first = NULL; 76 77 while (rs) 78 { 79 copy = alloc_reg_state (); 80 if (!copy) 81 { 82 print_error ("unwind.dup_state_stack: out of memory\n"); 83 return NULL; 84 } 85 memcpy (copy, rs, sizeof (*copy)); 86 if (first) 87 prev->next = copy; 88 else 89 first = copy; 90 rs = rs->next; 91 prev = copy; 92 } 93 return first; 94} 95 96/* Free all stacked register states (but not RS itself). */ 97static void 98free_state_stack (struct ia64_reg_state *rs) 99{ 100 struct ia64_reg_state *p, *next; 101 102 for (p = rs->next; p != NULL; p = next) 103 { 104 next = p->next; 105 free_reg_state (p); 106 } 107 rs->next = NULL; 108} 109 110/* Unwind decoder routines */ 111 112static enum ia64_pregnum CONST_ATTR 113decode_abreg (unsigned char abreg, int memory) 114{ 115 switch (abreg) 116 { 117 case 0x04 ... 0x07: 118 return IA64_REG_R4 + (abreg - 0x04); 119 case 0x22 ... 0x25: 120 return IA64_REG_F2 + (abreg - 0x22); 121 case 0x30 ... 0x3f: 122 return IA64_REG_F16 + (abreg - 0x30); 123 case 0x41 ... 0x45: 124 return IA64_REG_B1 + (abreg - 0x41); 125 case 0x60: 126 return IA64_REG_PR; 127 case 0x61: 128 return IA64_REG_PSP; 129 case 0x62: 130 return memory ? IA64_REG_PRI_UNAT_MEM : IA64_REG_PRI_UNAT_GR; 131 case 0x63: 132 return IA64_REG_IP; 133 case 0x64: 134 return IA64_REG_BSP; 135 case 0x65: 136 return IA64_REG_BSPSTORE; 137 case 0x66: 138 return IA64_REG_RNAT; 139 case 0x67: 140 return IA64_REG_UNAT; 141 case 0x68: 142 return IA64_REG_FPSR; 143 case 0x69: 144 return IA64_REG_PFS; 145 case 0x6a: 146 return IA64_REG_LC; 147 default: 148 break; 149 } 150 Dprintf ("libunwind: bad abreg=0x%x\n", abreg); 151 return IA64_REG_LC; 152} 153 154static void 155set_reg (struct ia64_reg_info *reg, enum ia64_where where, int when, 156 unsigned long val) 157{ 158 reg->val = val; 159 reg->where = where; 160 if (reg->when == IA64_WHEN_NEVER) 161 reg->when = when; 162} 163 164static void 165alloc_spill_area (unsigned long *offp, unsigned long regsize, 166 struct ia64_reg_info *lo, struct ia64_reg_info *hi) 167{ 168 struct ia64_reg_info *reg; 169 170 for (reg = hi; reg >= lo; --reg) 171 { 172 if (reg->where == IA64_WHERE_SPILL_HOME) 173 { 174 reg->where = IA64_WHERE_PSPREL; 175 *offp -= regsize; 176 reg->val = *offp; 177 } 178 } 179} 180 181static inline void 182spill_next_when (struct ia64_reg_info **regp, struct ia64_reg_info *lim, 183 unw_word t) 184{ 185 struct ia64_reg_info *reg; 186 187 for (reg = *regp; reg <= lim; ++reg) 188 { 189 if (reg->where == IA64_WHERE_SPILL_HOME) 190 { 191 reg->when = t; 192 *regp = reg + 1; 193 return; 194 } 195 } 196 Dprintf ("libunwind: excess spill!\n"); 197} 198 199static inline void 200finish_prologue (struct ia64_state_record *sr) 201{ 202 struct ia64_reg_info *reg; 203 unsigned long off; 204 int i; 205 206 /* First, resolve implicit register save locations (see Section 207 "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */ 208 for (i = 0; i < (int) ARRAY_SIZE (unw.save_order); ++i) 209 { 210 reg = sr->curr.reg + unw.save_order[i]; 211 if (reg->where == IA64_WHERE_GR_SAVE) 212 { 213 reg->where = IA64_WHERE_GR; 214 reg->val = sr->gr_save_loc++; 215 } 216 } 217 218 /* Next, compute when the fp, general, and branch registers get 219 saved. This must come before alloc_spill_area() because we need 220 to know which registers are spilled to their home locations. */ 221 222 if (sr->imask) 223 { 224 unsigned char kind, mask = 0, *cp = sr->imask; 225 unsigned long t; 226 static const unsigned char limit[3] = 227 { 228 IA64_REG_F31, IA64_REG_R7, IA64_REG_B5 229 }; 230 struct ia64_reg_info *(regs[3]); 231 232 regs[0] = sr->curr.reg + IA64_REG_F2; 233 regs[1] = sr->curr.reg + IA64_REG_R4; 234 regs[2] = sr->curr.reg + IA64_REG_B1; 235 236 for (t = 0; (int) t < sr->region_len; ++t) 237 { 238 if ((t & 3) == 0) 239 mask = *cp++; 240 kind = (mask >> 2 * (3 - (t & 3))) & 3; 241 if (kind > 0) 242 spill_next_when (®s[kind - 1], sr->curr.reg + limit[kind - 1], 243 sr->region_start + t); 244 } 245 } 246 247 /* Next, lay out the memory stack spill area. */ 248 249 if (sr->any_spills) 250 { 251 off = sr->spill_offset; 252 alloc_spill_area (&off, 16, sr->curr.reg + IA64_REG_F2, 253 sr->curr.reg + IA64_REG_F31); 254 alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_B1, 255 sr->curr.reg + IA64_REG_B5); 256 alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_R4, 257 sr->curr.reg + IA64_REG_R7); 258 } 259} 260 261/* Region header descriptors. */ 262 263static void 264desc_prologue (int body, unw_word rlen, unsigned char mask, 265 unsigned char grsave, struct ia64_state_record *sr) 266{ 267 int i, region_start; 268 269 if (!(sr->in_body || sr->first_region)) 270 finish_prologue (sr); 271 sr->first_region = 0; 272 273 /* check if we're done: */ 274 if (sr->when_target < sr->region_start + sr->region_len) 275 { 276 sr->done = 1; 277 return; 278 } 279 280 region_start = sr->region_start + sr->region_len; 281 282 for (i = 0; i < sr->epilogue_count; ++i) 283 pop (sr); 284 sr->epilogue_count = 0; 285 sr->when_sp_restored = IA64_WHEN_NEVER; 286 287 sr->region_start = region_start; 288 sr->region_len = rlen; 289 sr->in_body = body; 290 291 if (!body) 292 { 293 push (sr); 294 295 if (mask) 296 for (i = 0; i < 4; ++i) 297 { 298 if (mask & 0x8) 299 set_reg (sr->curr.reg + unw.save_order[i], IA64_WHERE_GR, 300 sr->region_start + sr->region_len - 1, grsave++); 301 mask <<= 1; 302 } 303 sr->gr_save_loc = grsave; 304 sr->any_spills = 0; 305 sr->imask = 0; 306 sr->spill_offset = 0x10; /* default to psp+16 */ 307 } 308} 309 310/* Prologue descriptors. */ 311 312static inline void 313desc_abi (unsigned char abi, unsigned char context, 314 struct ia64_state_record *sr) 315{ 316 sr->abi_marker = (abi << 8) | context; 317} 318 319static inline void 320desc_br_gr (unsigned char brmask, unsigned char gr, 321 struct ia64_state_record *sr) 322{ 323 int i; 324 325 for (i = 0; i < 5; ++i) 326 { 327 if (brmask & 1) 328 set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_GR, 329 sr->region_start + sr->region_len - 1, gr++); 330 brmask >>= 1; 331 } 332} 333 334static inline void 335desc_br_mem (unsigned char brmask, struct ia64_state_record *sr) 336{ 337 int i; 338 339 for (i = 0; i < 5; ++i) 340 { 341 if (brmask & 1) 342 { 343 set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_SPILL_HOME, 344 sr->region_start + sr->region_len - 1, 0); 345 sr->any_spills = 1; 346 } 347 brmask >>= 1; 348 } 349} 350 351static inline void 352desc_frgr_mem (unsigned char grmask, unw_word frmask, 353 struct ia64_state_record *sr) 354{ 355 int i; 356 357 for (i = 0; i < 4; ++i) 358 { 359 if ((grmask & 1) != 0) 360 { 361 set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME, 362 sr->region_start + sr->region_len - 1, 0); 363 sr->any_spills = 1; 364 } 365 grmask >>= 1; 366 } 367 for (i = 0; i < 20; ++i) 368 { 369 if ((frmask & 1) != 0) 370 { 371 int base = (i < 4) ? IA64_REG_F2 : IA64_REG_F16 - 4; 372 set_reg (sr->curr.reg + base + i, IA64_WHERE_SPILL_HOME, 373 sr->region_start + sr->region_len - 1, 0); 374 sr->any_spills = 1; 375 } 376 frmask >>= 1; 377 } 378} 379 380static inline void 381desc_fr_mem (unsigned char frmask, struct ia64_state_record *sr) 382{ 383 int i; 384 385 for (i = 0; i < 4; ++i) 386 { 387 if ((frmask & 1) != 0) 388 { 389 set_reg (sr->curr.reg + IA64_REG_F2 + i, IA64_WHERE_SPILL_HOME, 390 sr->region_start + sr->region_len - 1, 0); 391 sr->any_spills = 1; 392 } 393 frmask >>= 1; 394 } 395} 396 397static inline void 398desc_gr_gr (unsigned char grmask, unsigned char gr, 399 struct ia64_state_record *sr) 400{ 401 int i; 402 403 for (i = 0; i < 4; ++i) 404 { 405 if ((grmask & 1) != 0) 406 set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_GR, 407 sr->region_start + sr->region_len - 1, gr++); 408 grmask >>= 1; 409 } 410} 411 412static inline void 413desc_gr_mem (unsigned char grmask, struct ia64_state_record *sr) 414{ 415 int i; 416 417 for (i = 0; i < 4; ++i) 418 { 419 if ((grmask & 1) != 0) 420 { 421 set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME, 422 sr->region_start + sr->region_len - 1, 0); 423 sr->any_spills = 1; 424 } 425 grmask >>= 1; 426 } 427} 428 429static inline void 430desc_mem_stack_f (unw_word t, unw_word size, struct ia64_state_record *sr) 431{ 432 set_reg (sr->curr.reg + IA64_REG_PSP, IA64_WHERE_NONE, 433 sr->region_start + MIN ((int) t, sr->region_len - 1), 16 * size); 434} 435 436static inline void 437desc_mem_stack_v (unw_word t, struct ia64_state_record *sr) 438{ 439 sr->curr.reg[IA64_REG_PSP].when = 440 sr->region_start + MIN ((int) t, sr->region_len - 1); 441} 442 443static inline void 444desc_reg_gr (unsigned char reg, unsigned char dst, 445 struct ia64_state_record *sr) 446{ 447 set_reg (sr->curr.reg + reg, IA64_WHERE_GR, 448 sr->region_start + sr->region_len - 1, dst); 449} 450 451static inline void 452desc_reg_psprel (unsigned char reg, unw_word pspoff, 453 struct ia64_state_record *sr) 454{ 455 set_reg (sr->curr.reg + reg, IA64_WHERE_PSPREL, 456 sr->region_start + sr->region_len - 1, 0x10 - 4 * pspoff); 457} 458 459static inline void 460desc_reg_sprel (unsigned char reg, unw_word spoff, 461 struct ia64_state_record *sr) 462{ 463 set_reg (sr->curr.reg + reg, IA64_WHERE_SPREL, 464 sr->region_start + sr->region_len - 1, 4 * spoff); 465} 466 467static inline void 468desc_rp_br (unsigned char dst, struct ia64_state_record *sr) 469{ 470 sr->return_link_reg = dst; 471} 472 473static inline void 474desc_reg_when (unsigned char regnum, unw_word t, struct ia64_state_record *sr) 475{ 476 struct ia64_reg_info *reg = sr->curr.reg + regnum; 477 478 if (reg->where == IA64_WHERE_NONE) 479 reg->where = IA64_WHERE_GR_SAVE; 480 reg->when = sr->region_start + MIN ((int) t, sr->region_len - 1); 481} 482 483static inline void 484desc_spill_base (unw_word pspoff, struct ia64_state_record *sr) 485{ 486 sr->spill_offset = 0x10 - 4 * pspoff; 487} 488 489static inline unsigned char * 490desc_spill_mask (unsigned char *imaskp, struct ia64_state_record *sr) 491{ 492 sr->imask = imaskp; 493 return imaskp + (2 * sr->region_len + 7) / 8; 494} 495 496/* Body descriptors. */ 497 498static inline void 499desc_epilogue (unw_word t, unw_word ecount, struct ia64_state_record *sr) 500{ 501 sr->when_sp_restored = sr->region_start + sr->region_len - 1 - t; 502 sr->epilogue_count = ecount + 1; 503} 504 505static inline void 506desc_copy_state (unw_word label, struct ia64_state_record *sr) 507{ 508 struct ia64_labeled_state *ls; 509 510 for (ls = sr->labeled_states; ls; ls = ls->next) 511 { 512 if (ls->label == label) 513 { 514 free_state_stack (&sr->curr); 515 memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr)); 516 sr->curr.next = dup_state_stack (ls->saved_state.next); 517 return; 518 } 519 } 520 print_error ("libunwind: failed to find labeled state\n"); 521} 522 523static inline void 524desc_label_state (unw_word label, struct ia64_state_record *sr) 525{ 526 struct ia64_labeled_state *ls; 527 528 ls = alloc_labeled_state (); 529 if (!ls) 530 { 531 print_error ("unwind.desc_label_state(): out of memory\n"); 532 return; 533 } 534 ls->label = label; 535 memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state)); 536 ls->saved_state.next = dup_state_stack (sr->curr.next); 537 538 /* insert into list of labeled states: */ 539 ls->next = sr->labeled_states; 540 sr->labeled_states = ls; 541} 542 543/* General descriptors. */ 544 545static inline int 546desc_is_active (unsigned char qp, unw_word t, struct ia64_state_record *sr) 547{ 548 if (sr->when_target <= sr->region_start + MIN ((int) t, sr->region_len - 1)) 549 return 0; 550 if (qp > 0) 551 { 552 if ((sr->pr_val & ((unw_word_t) 1 << qp)) == 0) 553 return 0; 554 sr->pr_mask |= ((unw_word_t) 1 << qp); 555 } 556 return 1; 557} 558 559static inline void 560desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, 561 struct ia64_state_record *sr) 562{ 563 struct ia64_reg_info *r; 564 565 if (!desc_is_active (qp, t, sr)) 566 return; 567 568 r = sr->curr.reg + decode_abreg (abreg, 0); 569 r->where = IA64_WHERE_NONE; 570 r->when = IA64_WHEN_NEVER; 571 r->val = 0; 572} 573 574static inline void 575desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, 576 unsigned char x, unsigned char ytreg, 577 struct ia64_state_record *sr) 578{ 579 enum ia64_where where = IA64_WHERE_GR; 580 struct ia64_reg_info *r; 581 582 if (!desc_is_active (qp, t, sr)) 583 return; 584 585 if (x) 586 where = IA64_WHERE_BR; 587 else if (ytreg & 0x80) 588 where = IA64_WHERE_FR; 589 590 r = sr->curr.reg + decode_abreg (abreg, 0); 591 r->where = where; 592 r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); 593 r->val = (ytreg & 0x7f); 594} 595 596static inline void 597desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, 598 unw_word pspoff, struct ia64_state_record *sr) 599{ 600 struct ia64_reg_info *r; 601 602 if (!desc_is_active (qp, t, sr)) 603 return; 604 605 r = sr->curr.reg + decode_abreg (abreg, 1); 606 r->where = IA64_WHERE_PSPREL; 607 r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); 608 r->val = 0x10 - 4 * pspoff; 609} 610 611static inline void 612desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, 613 unw_word spoff, struct ia64_state_record *sr) 614{ 615 struct ia64_reg_info *r; 616 617 if (!desc_is_active (qp, t, sr)) 618 return; 619 620 r = sr->curr.reg + decode_abreg (abreg, 1); 621 r->where = IA64_WHERE_SPREL; 622 r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); 623 r->val = 4 * spoff; 624} 625 626#define UNW_DEC_BAD_CODE(code) \ 627 print_error ("libunwind: unknown code encountered\n") 628 629/* Register names. */ 630#define UNW_REG_BSP IA64_REG_BSP 631#define UNW_REG_BSPSTORE IA64_REG_BSPSTORE 632#define UNW_REG_FPSR IA64_REG_FPSR 633#define UNW_REG_LC IA64_REG_LC 634#define UNW_REG_PFS IA64_REG_PFS 635#define UNW_REG_PR IA64_REG_PR 636#define UNW_REG_RNAT IA64_REG_RNAT 637#define UNW_REG_PSP IA64_REG_PSP 638#define UNW_REG_RP IA64_REG_IP 639#define UNW_REG_UNAT IA64_REG_UNAT 640 641/* Region headers. */ 642#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg) 643#define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg) 644 645/* Prologue descriptors. */ 646#define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg) 647#define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg) 648#define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg) 649#define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg) 650#define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg) 651#define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg) 652#define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg) 653#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg) 654#define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg) 655#define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg) 656#define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg) 657#define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg) 658#define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg) 659#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) \ 660 desc_reg_when(IA64_REG_PRI_UNAT_GR,t,arg) 661#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) \ 662 desc_reg_when(IA64_REG_PRI_UNAT_MEM,t,arg) 663#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) \ 664 desc_reg_gr(IA64_REG_PRI_UNAT_GR,r,arg) 665#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) \ 666 desc_reg_psprel(IA64_REG_PRI_UNAT_MEM,o,arg) 667#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) \ 668 desc_reg_sprel(IA64_REG_PRI_UNAT_MEM,o,arg) 669#define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg) 670#define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg) 671#define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg)) 672 673/* Body descriptors. */ 674#define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg) 675#define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg) 676#define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg) 677 678/* General unwind descriptors. */ 679#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg) 680#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg) 681#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) \ 682 desc_spill_psprel_p(p,t,a,o,arg) 683#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) \ 684 desc_spill_psprel_p(0,t,a,o,arg) 685#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg) 686#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg) 687#define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg) 688#define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg) 689 690#include "unwind_decoder.h" 691 692#ifdef _U_dyn_op 693 694/* parse dynamic unwind info */ 695 696static struct ia64_reg_info * 697lookup_preg (int regnum, int memory, struct ia64_state_record *sr) 698{ 699 int preg; 700 701 switch (regnum) 702 { 703 case UNW_IA64_AR_BSP: preg = IA64_REG_BSP; break; 704 case UNW_IA64_AR_BSPSTORE: preg = IA64_REG_BSPSTORE; break; 705 case UNW_IA64_AR_FPSR: preg = IA64_REG_FPSR; break; 706 case UNW_IA64_AR_LC: preg = IA64_REG_LC; break; 707 case UNW_IA64_AR_PFS: preg = IA64_REG_PFS; break; 708 case UNW_IA64_AR_RNAT: preg = IA64_REG_RNAT; break; 709 case UNW_IA64_AR_UNAT: preg = IA64_REG_UNAT; break; 710 case UNW_IA64_BR + 0: preg = IA64_REG_IP; break; 711 case UNW_IA64_PR: preg = IA64_REG_PR; break; 712 case UNW_IA64_SP: preg = IA64_REG_PSP; break; 713 714 case UNW_IA64_NAT: 715 if (memory) 716 preg = IA64_REG_PRI_UNAT_MEM; 717 else 718 preg = IA64_REG_PRI_UNAT_GR; 719 break; 720 721 case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: 722 preg = IA64_REG_R4 + (regnum - (UNW_IA64_GR + 4)); 723 break; 724 725 case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5: 726 preg = IA64_REG_B1 + (regnum - UNW_IA64_BR); 727 break; 728 729 case UNW_IA64_FR + 2 ... UNW_IA64_FR + 5: 730 preg = IA64_REG_F2 + (regnum - (UNW_IA64_FR + 2)); 731 break; 732 733 case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31: 734 preg = IA64_REG_F16 + (regnum - (UNW_IA64_FR + 16)); 735 break; 736 737 default: 738 Dprintf ("%s: invalid register number %d\n", __FUNCTION__, regnum); 739 return NULL; 740 } 741 return sr->curr.reg + preg; 742} 743 744/* An alias directive inside a region of length RLEN is interpreted to 745 mean that the region behaves exactly like the first RLEN 746 instructions at the aliased IP. RLEN=0 implies that the current 747 state matches exactly that of before the instruction at the aliased 748 IP is executed. */ 749 750static int 751desc_alias (unw_dyn_op_t *op, struct cursor *c, struct ia64_state_record *sr) 752{ 753 struct ia64_state_record orig_sr = *sr; 754 int i, ret, when, rlen = sr->region_len; 755 unw_word_t new_ip; 756 757 when = MIN (sr->when_target, rlen); 758 new_ip = op->val + ((when / 3) * 16 + (when % 3)); 759 760 if ((ret = ia64_fetch_proc_info (c, new_ip, 1)) < 0) 761 return ret; 762 763 if ((ret = create_state_record_for (c, sr, new_ip)) < 0) 764 return ret; 765 766 sr->first_region = orig_sr.first_region; 767 sr->done = 0; 768 sr->any_spills |= orig_sr.any_spills; 769 sr->in_body = orig_sr.in_body; 770 sr->region_start = orig_sr.region_start; 771 sr->region_len = orig_sr.region_len; 772 if (sr->when_sp_restored != IA64_WHEN_NEVER) 773 sr->when_sp_restored = op->when + MIN (orig_sr.when_sp_restored, rlen); 774 sr->epilogue_count = orig_sr.epilogue_count; 775 sr->when_target = orig_sr.when_target; 776 777 for (i = 0; i < IA64_NUM_PREGS; ++i) 778 if (sr->curr.reg[i].when != IA64_WHEN_NEVER) 779 sr->curr.reg[i].when = op->when + MIN (sr->curr.reg[i].when, rlen); 780 781 ia64_free_state_record (sr); 782 sr->labeled_states = orig_sr.labeled_states; 783 sr->curr.next = orig_sr.curr.next; 784 return 0; 785} 786 787static inline int 788parse_dynamic (struct cursor *c, struct ia64_state_record *sr) 789{ 790 unw_dyn_info_t *di = c->pi.unwind_info; 791 unw_dyn_proc_info_t *proc = &di->u.pi; 792 unw_dyn_region_info_t *r; 793 struct ia64_reg_info *ri; 794 enum ia64_where where; 795 int32_t when, len; 796 unw_dyn_op_t *op; 797 unw_word_t val; 798 int memory, ret; 799 int8_t qp; 800 801 for (r = proc->regions; r; r = r->next) 802 { 803 len = r->insn_count; 804 if (len < 0) 805 { 806 if (r->next) 807 { 808 Debug (1, "negative region length allowed in last region only!"); 809 return -UNW_EINVAL; 810 } 811 len = -len; 812 /* hack old region info to set the start where we need it: */ 813 sr->region_start = (di->end_ip - di->start_ip) / 0x10 * 3 - len; 814 sr->region_len = 0; 815 } 816 /* all regions are treated as prologue regions: */ 817 desc_prologue (0, len, 0, 0, sr); 818 819 if (sr->done) 820 return 0; 821 822 for (op = r->op; op < r->op + r->op_count; ++op) 823 { 824 when = op->when; 825 val = op->val; 826 qp = op->qp; 827 828 if (!desc_is_active (qp, when, sr)) 829 continue; 830 831 when = sr->region_start + MIN ((int) when, sr->region_len - 1); 832 833 switch (op->tag) 834 { 835 case UNW_DYN_SAVE_REG: 836 memory = 0; 837 if ((unsigned) (val - UNW_IA64_GR) < 128) 838 where = IA64_WHERE_GR; 839 else if ((unsigned) (val - UNW_IA64_FR) < 128) 840 where = IA64_WHERE_FR; 841 else if ((unsigned) (val - UNW_IA64_BR) < 8) 842 where = IA64_WHERE_BR; 843 else 844 { 845 Dprintf ("%s: can't save to register number %d\n", 846 __FUNCTION__, (int) op->reg); 847 return -UNW_EBADREG; 848 } 849 /* fall through */ 850 update_reg_info: 851 ri = lookup_preg (op->reg, memory, sr); 852 if (!ri) 853 return -UNW_EBADREG; 854 ri->where = where; 855 ri->when = when; 856 ri->val = val; 857 break; 858 859 case UNW_DYN_SPILL_FP_REL: 860 memory = 1; 861 where = IA64_WHERE_PSPREL; 862 val = 0x10 - val; 863 goto update_reg_info; 864 865 case UNW_DYN_SPILL_SP_REL: 866 memory = 1; 867 where = IA64_WHERE_SPREL; 868 goto update_reg_info; 869 870 case UNW_DYN_ADD: 871 if (op->reg == UNW_IA64_SP) 872 { 873 if (val & 0xf) 874 { 875 Dprintf ("%s: frame-size %ld not an integer " 876 "multiple of 16\n", 877 __FUNCTION__, (long) op->val); 878 return -UNW_EINVAL; 879 } 880 desc_mem_stack_f (when, -((int64_t) val / 16), sr); 881 } 882 else 883 { 884 Dprintf ("%s: can only ADD to stack-pointer\n", 885 __FUNCTION__); 886 return -UNW_EBADREG; 887 } 888 break; 889 890 case UNW_DYN_POP_FRAMES: 891 sr->when_sp_restored = when; 892 sr->epilogue_count = op->val; 893 break; 894 895 case UNW_DYN_LABEL_STATE: 896 desc_label_state (op->val, sr); 897 break; 898 899 case UNW_DYN_COPY_STATE: 900 desc_copy_state (op->val, sr); 901 break; 902 903 case UNW_DYN_ALIAS: 904 if ((ret = desc_alias (op, c, sr)) < 0) 905 return ret; 906 907 case UNW_DYN_STOP: 908 goto end_of_ops; 909 } 910 } 911 end_of_ops: 912 ; 913 } 914 return 0; 915} 916#else 917# define parse_dynamic(c,sr) (-UNW_EINVAL) 918#endif /* _U_dyn_op */ 919 920 921HIDDEN int 922ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, int need_unwind_info) 923{ 924 int ret, dynamic = 1; 925 926 if (c->pi_valid && !need_unwind_info) 927 return 0; 928 929 /* check dynamic info first --- it overrides everything else */ 930 ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info, 931 c->as_arg); 932 if (ret == -UNW_ENOINFO) 933 { 934 dynamic = 0; 935 ret = ia64_find_proc_info (c, ip, need_unwind_info); 936 } 937 938 c->pi_valid = 1; 939 c->pi_is_dynamic = dynamic; 940 return ret; 941} 942 943static inline void 944put_unwind_info (struct cursor *c, unw_proc_info_t *pi) 945{ 946 if (!c->pi_valid) 947 return; 948 949 if (c->pi_is_dynamic) 950 unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); 951 else 952 ia64_put_unwind_info (c, pi); 953} 954 955static int 956create_state_record_for (struct cursor *c, struct ia64_state_record *sr, 957 unw_word_t ip) 958{ 959 unw_word_t predicates = c->pr; 960 struct ia64_reg_info *r; 961 uint8_t *dp, *desc_end; 962 int ret; 963 964 assert (c->pi_valid); 965 966 /* build state record */ 967 memset (sr, 0, sizeof (*sr)); 968 for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) 969 r->when = IA64_WHEN_NEVER; 970 sr->pr_val = predicates; 971 sr->first_region = 1; 972 973 if (!c->pi.unwind_info) 974 { 975 /* No info, return default unwinder (leaf proc, no mem stack, no 976 saved regs), rp in b0, pfs in ar.pfs. */ 977 Debug (1, "no unwind info for ip=0x%lx (gp=%lx)\n", 978 (long) ip, (long) c->pi.gp); 979 sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR; 980 sr->curr.reg[IA64_REG_IP].when = -1; 981 sr->curr.reg[IA64_REG_IP].val = 0; 982 goto out; 983 } 984 985 sr->when_target = (3 * ((ip & ~(unw_word_t) 0xf) - c->pi.start_ip) / 16 986 + (ip & 0xf)); 987 988 switch (c->pi.format) 989 { 990 case UNW_INFO_FORMAT_TABLE: 991 case UNW_INFO_FORMAT_REMOTE_TABLE: 992 dp = c->pi.unwind_info; 993 desc_end = dp + c->pi.unwind_info_size; 994 while (!sr->done && dp < desc_end) 995 dp = unw_decode (dp, sr->in_body, sr); 996 ret = 0; 997 break; 998 999 case UNW_INFO_FORMAT_DYNAMIC: 1000 ret = parse_dynamic (c, sr); 1001 break; 1002 1003 default: 1004 ret = -UNW_EINVAL; 1005 } 1006 1007 put_unwind_info (c, &c->pi); 1008 1009 if (ret < 0) 1010 return ret; 1011 1012 if (sr->when_target > sr->when_sp_restored) 1013 { 1014 /* sp has been restored and all values on the memory stack below 1015 psp also have been restored. */ 1016 sr->curr.reg[IA64_REG_PSP].val = 0; 1017 sr->curr.reg[IA64_REG_PSP].where = IA64_WHERE_NONE; 1018 sr->curr.reg[IA64_REG_PSP].when = IA64_WHEN_NEVER; 1019 for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) 1020 if ((r->where == IA64_WHERE_PSPREL && r->val <= 0x10) 1021 || r->where == IA64_WHERE_SPREL) 1022 { 1023 r->val = 0; 1024 r->where = IA64_WHERE_NONE; 1025 r->when = IA64_WHEN_NEVER; 1026 } 1027 } 1028 1029 /* If RP did't get saved, generate entry for the return link 1030 register. */ 1031 if (sr->curr.reg[IA64_REG_IP].when >= sr->when_target) 1032 { 1033 sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR; 1034 sr->curr.reg[IA64_REG_IP].when = -1; 1035 sr->curr.reg[IA64_REG_IP].val = sr->return_link_reg; 1036 } 1037 1038 if (sr->when_target > sr->curr.reg[IA64_REG_BSP].when 1039 && sr->when_target > sr->curr.reg[IA64_REG_BSPSTORE].when 1040 && sr->when_target > sr->curr.reg[IA64_REG_RNAT].when) 1041 { 1042 Debug (8, "func 0x%lx may switch the register-backing-store\n", 1043 c->pi.start_ip); 1044 c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH; 1045 } 1046 out: 1047#if UNW_DEBUG 1048 if (unwi_debug_level > 2) 1049 { 1050 Dprintf ("%s: state record for func 0x%lx, t=%u (flags=0x%lx):\n", 1051 __FUNCTION__, 1052 (long) c->pi.start_ip, sr->when_target, (long) c->pi.flags); 1053 for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) 1054 { 1055 if (r->where != IA64_WHERE_NONE || r->when != IA64_WHEN_NEVER) 1056 { 1057 Dprintf (" %s <- ", unw.preg_name[r - sr->curr.reg]); 1058 switch (r->where) 1059 { 1060 case IA64_WHERE_GR: 1061 Dprintf ("r%lu", (long) r->val); 1062 break; 1063 case IA64_WHERE_FR: 1064 Dprintf ("f%lu", (long) r->val); 1065 break; 1066 case IA64_WHERE_BR: 1067 Dprintf ("b%lu", (long) r->val); 1068 break; 1069 case IA64_WHERE_SPREL: 1070 Dprintf ("[sp+0x%lx]", (long) r->val); 1071 break; 1072 case IA64_WHERE_PSPREL: 1073 Dprintf ("[psp+0x%lx]", (long) r->val); 1074 break; 1075 case IA64_WHERE_NONE: 1076 Dprintf ("%s+0x%lx", 1077 unw.preg_name[r - sr->curr.reg], (long) r->val); 1078 break; 1079 default: 1080 Dprintf ("BADWHERE(%d)", r->where); 1081 break; 1082 } 1083 Dprintf ("\t\t%d\n", r->when); 1084 } 1085 } 1086 } 1087#endif 1088 return 0; 1089} 1090 1091/* The proc-info must be valid for IP before this routine can be 1092 called. */ 1093HIDDEN int 1094ia64_create_state_record (struct cursor *c, struct ia64_state_record *sr) 1095{ 1096 return create_state_record_for (c, sr, c->ip); 1097} 1098 1099HIDDEN int 1100ia64_free_state_record (struct ia64_state_record *sr) 1101{ 1102 struct ia64_labeled_state *ls, *next; 1103 1104 /* free labeled register states & stack: */ 1105 1106 for (ls = sr->labeled_states; ls; ls = next) 1107 { 1108 next = ls->next; 1109 free_state_stack (&ls->saved_state); 1110 free_labeled_state (ls); 1111 } 1112 free_state_stack (&sr->curr); 1113 1114 return 0; 1115} 1116 1117HIDDEN int 1118ia64_make_proc_info (struct cursor *c) 1119{ 1120 int ret, caching = c->as->caching_policy != UNW_CACHE_NONE; 1121 1122 if (!caching || ia64_get_cached_proc_info (c) < 0) 1123 { 1124 /* Lookup it up the slow way... */ 1125 if ((ret = ia64_fetch_proc_info (c, c->ip, 0)) < 0) 1126 return ret; 1127 if (caching) 1128 ia64_cache_proc_info (c); 1129 } 1130 return 0; 1131} 1132