1 /* $NetBSD: stackframe.c,v 1.9 2016/07/31 19:33:18 dholland Exp $ */ 2 3 /* Contributed to the NetBSD foundation by Cherry G. Mathew <cherry@mahiti.org> 4 * This file contains routines to use decoded unwind descriptor entries 5 * to build a stack configuration. The unwinder consults the stack 6 * configuration to fetch registers used to unwind the frame. 7 * References: 8 * [1] section. 11.4.2.6., Itanium Software Conventions and 9 * Runtime Architecture Guide. 10 */ 11 12 #include <sys/cdefs.h> 13 #include <sys/param.h> 14 #include <sys/systm.h> 15 16 17 #include <ia64/unwind/decode.h> 18 #include <ia64/unwind/stackframe.h> 19 20 //#define UNWIND_DIAGNOSTIC 21 22 /* 23 * Global variables: 24 * array of struct recordchain 25 * size of record chain array. 26 */ 27 struct recordchain strc[MAXSTATERECS]; 28 int rec_cnt = 0; 29 30 /* 31 * Build a recordchain of a region, given the pointer to unwind table 32 * entry, and the number of entries to decode. 33 */ 34 void 35 buildrecordchain(uint64_t unwind_infop, struct recordchain *xxx) 36 { 37 uint64_t unwindstart, unwindend; 38 uint64_t unwindlen; 39 uint64_t region_len = 0; 40 bool region_type = false; /* Prologue */ 41 42 struct unwind_hdr_t { 43 uint64_t uwh; 44 } *uwhp = (void *) unwind_infop; 45 46 char *nextrecp, *recptr = (char *) unwind_infop + sizeof(uint64_t); 47 48 unwindstart = (uint64_t) recptr; 49 50 if (UNW_VER(uwhp->uwh) != 1) { 51 printf("Wrong unwind version! \n"); 52 return; 53 } 54 55 unwindlen = UNW_LENGTH(uwhp->uwh) * sizeof(uint64_t); 56 unwindend = unwindstart + unwindlen; 57 58 #ifdef UNWIND_DIAGNOSTIC 59 printf("recptr = %p \n", recptr); 60 printf("unwindlen = %lx \n", unwindlen); 61 printf("unwindend = %lx \n", unwindend); 62 #endif 63 64 /* XXX: Ignore zero length records. */ 65 66 67 for (rec_cnt = 0; 68 rec_cnt < MAXSTATERECS && (uint64_t)recptr < unwindend; 69 rec_cnt++) { 70 nextrecp = unwind_decode_R1(recptr, &strc[rec_cnt].udesc); 71 if (nextrecp) { 72 region_len = strc[rec_cnt].udesc.R1.rlen; 73 region_type = strc[rec_cnt].udesc.R1.r; 74 strc[rec_cnt].type = R1; 75 recptr = nextrecp; 76 continue; 77 } 78 79 nextrecp = unwind_decode_R2(recptr, &strc[rec_cnt].udesc); 80 if (nextrecp) { 81 region_len = strc[rec_cnt].udesc.R2.rlen; 82 /* R2 regions are prologue regions */ 83 region_type = false; 84 strc[rec_cnt].type = R2; 85 recptr = nextrecp; 86 continue; 87 } 88 89 nextrecp = unwind_decode_R3(recptr, &strc[rec_cnt].udesc); 90 if (nextrecp) { 91 region_len = strc[rec_cnt].udesc.R3.rlen; 92 region_type = strc[rec_cnt].udesc.R3.r; 93 strc[rec_cnt].type = R3; 94 recptr = nextrecp; 95 continue; 96 } 97 98 if (region_type == false) { 99 /* Prologue Region */ 100 nextrecp = unwind_decode_P1(recptr, 101 &strc[rec_cnt].udesc); 102 if (nextrecp) { 103 strc[rec_cnt].type = P1; 104 recptr = nextrecp; 105 continue; 106 } 107 108 nextrecp = unwind_decode_P2(recptr, 109 &strc[rec_cnt].udesc); 110 if (nextrecp) { 111 strc[rec_cnt].type = P2; 112 recptr = nextrecp; 113 continue; 114 } 115 116 nextrecp = unwind_decode_P3(recptr, 117 &strc[rec_cnt].udesc); 118 if (nextrecp) { 119 strc[rec_cnt].type = P3; 120 recptr = nextrecp; 121 continue; 122 } 123 124 nextrecp = unwind_decode_P4(recptr, 125 &strc[rec_cnt].udesc, 126 region_len); 127 if (nextrecp) { 128 strc[rec_cnt].type = P4; 129 recptr = nextrecp; 130 break; 131 } 132 133 nextrecp = unwind_decode_P5(recptr, 134 &strc[rec_cnt].udesc); 135 if (nextrecp) { 136 strc[rec_cnt].type = P5; 137 recptr = nextrecp; 138 continue; 139 } 140 141 nextrecp = unwind_decode_P6(recptr, 142 &strc[rec_cnt].udesc); 143 if (nextrecp) { 144 strc[rec_cnt].type = P6; 145 recptr = nextrecp; 146 continue; 147 } 148 149 nextrecp = unwind_decode_P7(recptr, 150 &strc[rec_cnt].udesc); 151 if (nextrecp) { 152 strc[rec_cnt].type = P7; 153 recptr = nextrecp; 154 continue; 155 } 156 157 nextrecp = unwind_decode_P8(recptr, 158 &strc[rec_cnt].udesc); 159 if (nextrecp) { 160 strc[rec_cnt].type = P8; 161 recptr = nextrecp; 162 continue; 163 } 164 165 nextrecp = unwind_decode_P9(recptr, 166 &strc[rec_cnt].udesc); 167 if (nextrecp) { 168 strc[rec_cnt].type = P9; 169 recptr = nextrecp; 170 continue; 171 } 172 173 nextrecp = unwind_decode_P10(recptr, 174 &strc[rec_cnt].udesc); 175 if (nextrecp) { 176 strc[rec_cnt].type = P10; 177 recptr = nextrecp; 178 continue; 179 } 180 181 printf("Skipping prologue desc slot :: %d \n", rec_cnt); 182 } else { 183 184 nextrecp = unwind_decode_B1(recptr, 185 &strc[rec_cnt].udesc); 186 if (nextrecp) { 187 strc[rec_cnt].type = B1; 188 recptr = nextrecp; 189 continue; 190 } 191 192 nextrecp = unwind_decode_B2(recptr, 193 &strc[rec_cnt].udesc); 194 if (nextrecp) { 195 strc[rec_cnt].type = B2; 196 recptr = nextrecp; 197 continue; 198 } 199 200 nextrecp = unwind_decode_B3(recptr, 201 &strc[rec_cnt].udesc); 202 if (nextrecp) { 203 strc[rec_cnt].type = B3; 204 recptr = nextrecp; 205 continue; 206 } 207 208 nextrecp = unwind_decode_B4(recptr, 209 &strc[rec_cnt].udesc); 210 if (nextrecp) { 211 strc[rec_cnt].type = B4; 212 recptr = nextrecp; 213 continue; 214 } 215 216 nextrecp = unwind_decode_X1(recptr, 217 &strc[rec_cnt].udesc); 218 if (nextrecp) { 219 strc[rec_cnt].type = X1; 220 recptr = nextrecp; 221 continue; 222 } 223 224 nextrecp = unwind_decode_X2(recptr, 225 &strc[rec_cnt].udesc); 226 if (nextrecp) { 227 strc[rec_cnt].type = X2; 228 recptr = nextrecp; 229 continue; 230 } 231 232 233 nextrecp = unwind_decode_X3(recptr, 234 &strc[rec_cnt].udesc); 235 if (nextrecp) { 236 strc[rec_cnt].type = X3; 237 recptr = nextrecp; 238 continue; 239 } 240 241 nextrecp = unwind_decode_X4(recptr, 242 &strc[rec_cnt].udesc); 243 if (nextrecp) { 244 strc[rec_cnt].type = X4; 245 recptr = nextrecp; 246 continue; 247 } 248 249 printf("Skipping body desc slot :: %d \n", rec_cnt); 250 } 251 } 252 253 #ifdef UNWIND_DIAGNOSTIC 254 int i; 255 for(i = 0;i < rec_cnt;i++) { 256 dump_recordchain(&strc[i]); 257 } 258 259 #endif /* UNWIND_DIAGNOSTIC */ 260 } 261 262 263 264 265 /* 266 * Debug support: dump a record chain entry 267 */ 268 void 269 dump_recordchain(struct recordchain *rchain) 270 { 271 272 switch(rchain->type) { 273 case R1: 274 printf("\t R1:"); 275 if(rchain->udesc.R1.r) 276 printf("body ("); 277 else 278 printf("prologue ("); 279 printf("rlen = %ld) \n", rchain->udesc.R1.rlen); 280 break; 281 282 case R2: 283 printf("\t R2:"); 284 printf("prologue_gr ("); 285 printf("mask = %x, ", rchain->udesc.R2.mask); 286 printf("grsave = %d, ", rchain->udesc.R2.grsave); 287 printf("rlen = %ld )\n", rchain->udesc.R2.rlen); 288 break; 289 290 case R3: 291 printf("\t R3:"); 292 if(rchain->udesc.R3.r) 293 printf("body ("); 294 else 295 printf("prologue ("); 296 printf("rlen = %ld )\n", rchain->udesc.R3.rlen); 297 break; 298 299 case P1: 300 printf("\t\tP1:"); 301 printf("br_mem (brmask = %x) \n", rchain->udesc.P1.brmask); 302 break; 303 304 case P2: 305 printf("\t\tP2:"); 306 printf("br_gr(brmask = %x, ", rchain->udesc.P2.brmask); 307 printf("gr = %d ) \n", rchain->udesc.P2.gr); 308 break; 309 310 case P3: 311 printf("\t\tP3:"); 312 switch(rchain->udesc.P3.r) { 313 case 0: 314 printf("psp_gr"); 315 break; 316 case 1: 317 printf("rp_gr"); 318 break; 319 case 2: 320 printf("pfs_gr"); 321 break; 322 case 3: 323 printf("preds_gr"); 324 break; 325 case 4: 326 printf("unat_gr"); 327 break; 328 case 5: 329 printf("lc_gr"); 330 break; 331 case 6: 332 printf("rp_br"); 333 break; 334 case 7: 335 printf("rnat_gr"); 336 break; 337 case 8: 338 printf("bsp_gr"); 339 break; 340 case 9: 341 printf("bspstore_gr"); 342 break; 343 case 10: 344 printf("fpsr_gr"); 345 break; 346 case 11: 347 printf("priunat_gr"); 348 break; 349 default: 350 printf("unknown desc: %d", rchain->udesc.P3.r); 351 352 } 353 printf("(gr/br = %d) \n", rchain->udesc.P3.grbr); 354 355 break; 356 357 case P4: 358 printf("P4: (unimplemented): \n"); 359 break; 360 361 case P5: 362 printf("\t\tP5:"); 363 printf("frgr_mem(grmask = %x, frmask = %x )\n", 364 rchain->udesc.P5.grmask, rchain->udesc.P5.frmask); 365 break; 366 367 case P6: 368 printf("\t\tP6: "); 369 if(rchain->udesc.P6.r) 370 printf("gr_mem( "); 371 else 372 printf("fr_mem( "); 373 printf("rmask = %x) \n", rchain->udesc.P6.rmask); 374 break; 375 376 case P7: 377 printf("\t\tP7:"); 378 switch(rchain->udesc.P7.r) { 379 case 0: 380 printf("memstack_f( "); 381 printf("t = %ld, ", rchain->udesc.P7.t); 382 printf("size = %ld) \n", rchain->udesc.P7.size); 383 break; 384 case 1: 385 printf("memstack_v( "); 386 printf("t = %ld) \n", rchain->udesc.P7.t); 387 break; 388 case 2: 389 printf("spillbase( "); 390 printf("pspoff = %ld) \n", rchain->udesc.P7.t); 391 break; 392 case 3: 393 printf("psp_sprel( "); 394 printf("spoff = %ld) \n", rchain->udesc.P7.t); 395 break; 396 case 4: 397 printf("rp_when( "); 398 printf("t = %ld) \n", rchain->udesc.P7.t); 399 break; 400 case 5: 401 printf("rp_psprel( "); 402 printf("pspoff = %ld) \n", rchain->udesc.P7.t); 403 break; 404 case 6: 405 printf("pfs_when( "); 406 printf("t = %ld) \n", rchain->udesc.P7.t); 407 break; 408 case 7: 409 printf("pfs_psprel( "); 410 printf("pspoff = %ld) \n", rchain->udesc.P7.t); 411 break; 412 case 8: 413 printf("preds_when( "); 414 printf("t = %ld) \n", rchain->udesc.P7.t); 415 break; 416 case 9: 417 printf("preds_psprel( "); 418 printf("pspoff = %ld) \n", rchain->udesc.P7.t); 419 break; 420 case 10: 421 printf("lc_when( "); 422 printf("t = %ld) \n", rchain->udesc.P7.t); 423 break; 424 case 11: 425 printf("lc_psprel( "); 426 printf("pspoff = %ld) \n", rchain->udesc.P7.t); 427 break; 428 case 12: 429 printf("unat_when( "); 430 printf("t = %ld) \n", rchain->udesc.P7.t); 431 break; 432 case 13: 433 printf("unat_psprel( "); 434 printf("pspoff = %ld) \n", rchain->udesc.P7.t); 435 break; 436 case 14: 437 printf("fpsr_when( "); 438 printf("t = %ld) \n", rchain->udesc.P7.t); 439 break; 440 case 15: 441 printf("fpsr_psprel( "); 442 printf("pspoff = %ld) \n", rchain->udesc.P7.t); 443 break; 444 default: 445 printf("unknown \n"); 446 } 447 448 break; 449 450 case P8: 451 printf("\t\tP8:"); 452 switch(rchain->udesc.P8.r) { 453 case 1: 454 printf("rp_sprel( "); 455 printf("spoff = %ld) \n", rchain->udesc.P8.t); 456 break; 457 case 2: 458 printf("pfs_sprel( "); 459 printf("spoff = %ld) \n", rchain->udesc.P8.t); 460 break; 461 case 3: 462 printf("preds_sprel( "); 463 printf("spoff = %ld) \n", rchain->udesc.P8.t); 464 break; 465 case 4: 466 printf("lc_sprel( "); 467 printf("spoff = %ld) \n", rchain->udesc.P8.t); 468 break; 469 case 5: 470 printf("unat_sprel( "); 471 printf("spoff = %ld) \n", rchain->udesc.P8.t); 472 break; 473 case 6: 474 printf("fpsr_sprel( "); 475 printf("spoff = %ld) \n", rchain->udesc.P8.t); 476 break; 477 case 7: 478 printf("bsp_when( "); 479 printf("t = %ld) \n", rchain->udesc.P8.t); 480 break; 481 case 8: 482 printf("bsp_psprel( "); 483 printf("pspoff = %ld) \n", rchain->udesc.P8.t); 484 break; 485 case 9: 486 printf("bsp_sprel( "); 487 printf("spoff = %ld) \n", rchain->udesc.P8.t); 488 break; 489 case 10: 490 printf("bspstore_when( "); 491 printf("t = %ld) \n", rchain->udesc.P8.t); 492 break; 493 case 11: 494 printf("bspstore_psprel( "); 495 printf("pspoff = %ld) \n", rchain->udesc.P8.t); 496 break; 497 case 12: 498 printf("bspstore_sprel( "); 499 printf("spoff = %ld) \n", rchain->udesc.P8.t); 500 break; 501 case 13: 502 printf("rnat_when( "); 503 printf("t = %ld) \n", rchain->udesc.P8.t); 504 break; 505 case 14: 506 printf("rnat_psprel( "); 507 printf("pspoff = %ld) \n", rchain->udesc.P8.t); 508 break; 509 case 15: 510 printf("rnat_sprel( "); 511 printf("spoff = %ld) \n", rchain->udesc.P8.t); 512 break; 513 case 16: 514 printf("priunat_when_gr( "); 515 printf("t = %ld) \n", rchain->udesc.P8.t); 516 break; 517 case 17: 518 printf("priunat_psprel( "); 519 printf("pspoff = %ld) \n", rchain->udesc.P8.t); 520 break; 521 case 18: 522 printf("priunat_sprel( "); 523 printf("spoff = %ld) \n", rchain->udesc.P8.t); 524 break; 525 case 19: 526 printf("priunat_when_mem( "); 527 printf("t = %ld) \n", rchain->udesc.P8.t); 528 break; 529 530 default: 531 printf("unknown \n"); 532 } 533 534 break; 535 536 case P9: 537 printf("\t\tP9:"); 538 printf("(grmask = %x, gr = %d) \n", 539 rchain->udesc.P9.grmask, rchain->udesc.P9.gr); 540 break; 541 542 case P10: 543 printf("\t\tP10:"); 544 printf("(abi: "); 545 switch(rchain->udesc.P10.abi) { 546 case 0: 547 printf("Unix SVR4) \n"); 548 break; 549 case 1: 550 printf("HP-UX) \n"); 551 break; 552 default: 553 printf("Other) \n"); 554 } 555 break; 556 557 case B1: 558 printf("\t\tB1:"); 559 if(rchain->udesc.B1.r) 560 printf("copy_state( "); 561 else 562 printf("label_state( "); 563 printf("label = %d) \n", rchain->udesc.B1.label); 564 565 break; 566 567 case B2: 568 printf("\t\tB2:"); 569 printf("(ecount = %d, t = %ld)\n", 570 rchain->udesc.B2.ecount, rchain->udesc.B2.t); 571 572 break; 573 574 case B3: 575 printf("\t\tB3:"); 576 printf("(t = %ld, ecount = %ld) \n", 577 rchain->udesc.B3.t, rchain->udesc.B3.ecount); 578 579 break; 580 581 case B4: 582 printf("\t\tB4:"); 583 if(rchain->udesc.B4.r) 584 printf("copy_state( "); 585 else 586 printf("label_state( "); 587 588 printf("label = %ld) \n", rchain->udesc.B4.label); 589 590 break; 591 592 593 case X1: 594 printf("\tX1:\n "); 595 break; 596 597 case X2: 598 printf("\tX2:\n"); 599 break; 600 601 case X3: 602 printf("\tX3:\n"); 603 break; 604 605 case X4: 606 printf("\tX4:\n"); 607 break; 608 default: 609 printf("\tunknow: \n"); 610 } 611 612 } 613 614 /* 615 * State record stuff..... based on section 11. and Appendix A. of the 616 * "Itanium Software Conventions and Runtime Architecture Guide" 617 */ 618 619 620 /* 621 * Global variables: 622 * 1. Two arrays of staterecords: recordstack[], recordstackcopy[] 623 * XXX: Since we don't use malloc, we have two arbitrary sized arrays 624 * providing guaranteed memory from the BSS. See the TODO file 625 * for more details. 626 * 2. Two head variables to hold the member index: unwind_rsp,unwind_rscp 627 */ 628 629 struct staterecord recordstack[MAXSTATERECS]; 630 struct staterecord recordstackcopy[MAXSTATERECS]; 631 struct staterecord current_state; 632 struct staterecord *unwind_rsp, *unwind_rscp; 633 634 635 /* Base of spill area in memory stack frame as a psp relative offset */ 636 uint64_t spill_base = 0; 637 638 /* 639 * Initialises a staterecord from a given template, 640 * with default values as described by the Runtime Spec. 641 */ 642 void 643 initrecord(struct staterecord *target) 644 { 645 target->bsp.where = UNSAVED; 646 target->bsp.when = 0; 647 target->bsp.offset = INVALID; 648 target->psp.where = UNSAVED; 649 target->psp.when = 0; 650 target->psp.offset = INVALID; 651 target->rp.where = UNSAVED; 652 target->rp.when = 0; 653 target->rp.offset = INVALID; 654 target->pfs.where = UNSAVED; 655 target->pfs.when = 0; 656 target->pfs.offset = INVALID; 657 } 658 659 660 /* 661 * Modifies a staterecord structure by parsing 662 * a single record chain structure. 663 * regionoffset is the offset within a (prologue) region 664 * where the stack unwinding began. 665 */ 666 void 667 modifyrecord(struct staterecord *srec, struct recordchain *rchain, 668 uint64_t regionoffset) 669 { 670 /* 671 * Default start save GR for prologue_save GRs. 672 */ 673 uint64_t grno = 32; 674 675 676 switch (rchain->type) { 677 678 case R2: 679 /* 680 * R2, prologue_gr is the only region encoding 681 * with register save info. 682 */ 683 684 grno = rchain->udesc.R2.grsave; 685 686 if (rchain->udesc.R2.mask & R2MASKRP) { 687 srec->rp.when = 0; 688 srec->rp.where = GRREL; 689 srec->rp.offset = grno++; 690 } 691 692 if (rchain->udesc.R2.mask & R2MASKPFS) { 693 srec->pfs.when = 0; 694 srec->pfs.where = GRREL; 695 srec->pfs.offset = grno++; 696 } 697 698 if (rchain->udesc.R2.mask & R2MASKPSP) { 699 srec->psp.when = 0; 700 srec->psp.where = GRREL; 701 srec->psp.offset = grno++; 702 } 703 break; 704 705 case P3: 706 switch (rchain->udesc.P3.r) { 707 case 0: /* psp_gr */ 708 if (srec->psp.when < regionoffset) { 709 srec->psp.where = GRREL; 710 srec->psp.offset = rchain->udesc.P3.grbr; 711 } 712 break; 713 714 case 1: /* rp_gr */ 715 if (srec->rp.when < regionoffset) { 716 srec->rp.where = GRREL; 717 srec->rp.offset = rchain->udesc.P3.grbr; 718 } 719 break; 720 721 case 2: /* pfs_gr */ 722 if (srec->pfs.when < regionoffset) { 723 srec->pfs.where = GRREL; 724 srec->pfs.offset = rchain->udesc.P3.grbr; 725 } 726 break; 727 728 } 729 break; 730 731 732 /* 733 * XXX: P4 spill_mask and P7: spill_base are for GRs, FRs, and BRs. 734 * We're not particularly worried about those right now. 735 */ 736 737 case P7: 738 switch (rchain->udesc.P7.r) { 739 740 case 0: /* mem_stack_f */ 741 if (srec->psp.offset != INVALID) { 742 printf("!!!saw mem_stack_f more than once. \n"); 743 } 744 srec->psp.when = rchain->udesc.P7.t; 745 if (srec->psp.when < regionoffset) { 746 srec->psp.where = IMMED; 747 /* spsz.offset is "overloaded" */ 748 srec->psp.offset = rchain->udesc.P7.size; 749 } 750 break; 751 752 case 1: /* mem_stack_v */ 753 srec->psp.when = rchain->udesc.P7.t; 754 break; 755 756 case 2: /* spill_base */ 757 spill_base = rchain->udesc.P7.t; 758 break; 759 760 case 3: /* psp_sprel */ 761 if (srec->psp.when < regionoffset) { 762 srec->psp.where = SPREL; 763 srec->psp.offset = rchain->udesc.P7.t; 764 } 765 break; 766 767 case 4: /* rp_when */ 768 srec->rp.when = rchain->udesc.P7.t; 769 /* 770 * XXX: Need to set to prologue_gr(grno) for 771 * the orphan case ie; _gr/_psprel/_sprel 772 * not set and therefore default to begin 773 * from the gr specified in prologue_gr. 774 */ 775 break; 776 777 case 5: /* rp_psprel */ 778 if (srec->rp.when < regionoffset) { 779 srec->rp.where = PSPREL; 780 srec->rp.offset = rchain->udesc.P7.t; 781 } 782 break; 783 784 case 6: /* pfs_when */ 785 srec->pfs.when = rchain->udesc.P7.t; 786 /* 787 * XXX: Need to set to prologue_gr(grno) for 788 * the orphan case ie; _gr/_psprel/_sprel 789 * not set and therefore default to begin 790 * from the gr specified in prologue_gr. 791 */ 792 break; 793 794 case 7: /* pfs_psprel */ 795 if (srec->pfs.when < regionoffset) { 796 srec->pfs.where = PSPREL; 797 srec->pfs.offset = rchain->udesc.P7.t; 798 } 799 break; 800 801 } 802 break; 803 804 case P8: 805 switch (rchain->udesc.P8.r) { 806 case 1: /* rp_sprel */ 807 if (srec->rp.when < regionoffset) { 808 srec->rp.where = SPREL; 809 srec->rp.offset = rchain->udesc.P8.t; 810 } 811 break; 812 case 2: /* pfs_sprel */ 813 if (srec->pfs.when < regionoffset) { 814 srec->pfs.where = SPREL; 815 srec->pfs.offset = rchain->udesc.P8.t; 816 817 } 818 break; 819 } 820 break; 821 822 case B1: 823 824 rchain->udesc.B1.r ? switchrecordstack(0) : 825 clonerecordstack(0); 826 break; 827 828 case B2: 829 if (regionoffset < rchain->udesc.B2.t) { 830 poprecord(¤t_state, rchain->udesc.B2.ecount); 831 } 832 break; 833 case B3: 834 if (regionoffset < rchain->udesc.B3.t) { 835 poprecord(¤t_state, rchain->udesc.B3.ecount); 836 } 837 break; 838 case B4: 839 rchain->udesc.B4.r ? switchrecordstack(0) : 840 clonerecordstack(0); 841 break; 842 843 case X1: 844 case X2: 845 case X3: 846 /* XXX: Todo */ 847 break; 848 849 850 case R1: 851 case R3: 852 case P1: 853 case P2: 854 case P4: 855 case P5: 856 case P6: 857 case P9: 858 case P10: 859 default: 860 /* Ignore. */ 861 printf("XXX: Ignored. \n"); 862 } 863 864 865 } 866 867 void 868 dump_staterecord(struct staterecord *srec) 869 { 870 printf("rp.where: "); 871 switch(srec->rp.where) { 872 case UNSAVED: 873 printf("UNSAVED "); 874 break; 875 case BRREL: 876 printf("BRREL "); 877 break; 878 case GRREL: 879 printf("GRREL "); 880 break; 881 case SPREL: 882 printf("SPREL "); 883 break; 884 case PSPREL: 885 printf("PSPSREL "); 886 break; 887 default: 888 printf("unknown "); 889 } 890 891 printf(", rp.when = %lu, ", srec->rp.when); 892 printf("rp.offset = %lu \n", srec->rp.offset); 893 894 895 printf("pfs.where: "); 896 switch(srec->pfs.where) { 897 case UNSAVED: 898 printf("UNSAVED "); 899 break; 900 case BRREL: 901 printf("BRREL "); 902 break; 903 case GRREL: 904 printf("GRREL "); 905 break; 906 case SPREL: 907 printf("SPREL "); 908 break; 909 case PSPREL: 910 printf("PSPSREL "); 911 break; 912 default: 913 printf("unknown "); 914 } 915 916 printf(", pfs.when = %lu, ", srec->pfs.when); 917 printf("pfs.offset = %lu \n", srec->pfs.offset); 918 } 919 920 921 /* 922 * Push a state record on the record stack. 923 */ 924 void 925 pushrecord(struct staterecord *srec) 926 { 927 if(unwind_rsp >= recordstack + MAXSTATERECS) { 928 printf("Push exceeded array size!!! \n"); 929 return; 930 } 931 932 memcpy(unwind_rsp, srec, sizeof(struct staterecord)); 933 unwind_rsp++; 934 935 } 936 937 /* 938 * Pop n state records off the record stack. 939 */ 940 void 941 poprecord(struct staterecord *srec, int n) 942 { 943 if(unwind_rsp == recordstack) { 944 printf("Popped beyond end of Stack!!! \n"); 945 return; 946 } 947 unwind_rsp -= n; 948 memcpy(srec, unwind_rsp, sizeof(struct staterecord)); 949 #ifdef DEBUG 950 memset(unwind_rsp, 0, sizeof(struct staterecord) * n); 951 #endif 952 953 } 954 955 /* 956 * Clone the whole record stack upto this one. 957 */ 958 void 959 clonerecordstack(u_int label) 960 { 961 memcpy(recordstackcopy, recordstack, 962 (unwind_rsp - recordstack) * sizeof(struct staterecord)); 963 unwind_rscp = unwind_rsp; 964 } 965 966 /* 967 * Discard the current stack, and adopt a clone. 968 */ 969 void 970 switchrecordstack(u_int label) 971 { 972 memcpy((void *) recordstack, (void *) recordstackcopy, 973 (unwind_rscp - recordstackcopy) * sizeof(struct staterecord)); 974 unwind_rsp = unwind_rscp; 975 976 } 977 978 /* 979 * In the context of a procedure: 980 * Parses through a record chain, building, pushing and/or popping staterecords, 981 * or cloning/destroying stacks of staterecords as required. 982 * Parameters are: 983 * rchain: pointer to recordchain array. 984 * procoffset: offset of point of interest, in slots, within procedure 985 * starting from slot 0 986 * This routine obeys [1] 987 */ 988 struct staterecord * 989 buildrecordstack(struct recordchain *rchain, uint64_t procoffset) 990 { 991 /* Current region length, defaults to zero if not specified */ 992 uint64_t rlen = 0; 993 /* Accumulated region length */ 994 uint64_t roffset = 0; 995 /* Offset within current region */ 996 uint64_t rdepth = 0; 997 998 bool rtype; 999 int i; 1000 1001 /* Start with bottom of staterecord stack. */ 1002 unwind_rsp = recordstack; 1003 1004 initrecord(¤t_state); 1005 1006 for (i = 0;i < rec_cnt;i++) { 1007 1008 switch (rchain[i].type) { 1009 case R1: 1010 rlen = rchain[i].udesc.R1.rlen; 1011 if (procoffset < roffset) { 1012 /* 1013 * Overshot Region containing 1014 * procoffset. Bail out. 1015 */ 1016 goto out; 1017 } 1018 rdepth = procoffset - roffset; 1019 roffset += rlen; 1020 rtype = rchain[i].udesc.R1.r; 1021 if (!rtype) { 1022 pushrecord(¤t_state); 1023 } 1024 break; 1025 1026 case R3: 1027 rlen = rchain[i].udesc.R3.rlen; 1028 if (procoffset < roffset) { 1029 /* 1030 * Overshot Region containing 1031 * procoffset. Bail out. 1032 */ 1033 goto out; 1034 } 1035 rdepth = procoffset - roffset; 1036 roffset += rlen; 1037 rtype = rchain[i].udesc.R3.r; 1038 if (!rtype) { 1039 pushrecord(¤t_state); 1040 } 1041 break; 1042 1043 case R2: 1044 rlen = rchain[i].udesc.R2.rlen; 1045 if (procoffset < roffset) { 1046 /* 1047 * Overshot Region containing 1048 * procoffset. Bail out. 1049 */ 1050 goto out; 1051 } 1052 rdepth = procoffset - roffset; 1053 roffset += rlen; 1054 rtype = false; /* prologue region */ 1055 pushrecord(¤t_state); 1056 1057 /* R2 has save info. Continue down. */ 1058 /* FALLTHROUGH */ 1059 case P1: 1060 case P2: 1061 case P3: 1062 case P4: 1063 case P5: 1064 case P6: 1065 case P7: 1066 case P8: 1067 case P9: 1068 case P10: 1069 modifyrecord(¤t_state, &rchain[i], rdepth); 1070 break; 1071 1072 case B1: 1073 case B2: 1074 case B3: 1075 case B4: 1076 modifyrecord(¤t_state, &rchain[i], 1077 rlen - 1 - rdepth); 1078 break; 1079 1080 case X1: 1081 case X2: 1082 case X3: 1083 case X4: 1084 default: 1085 printf("Error: Unknown descriptor type!!! \n"); 1086 1087 } 1088 1089 #if UNWIND_DIAGNOSTIC 1090 dump_staterecord(¤t_state); 1091 #endif 1092 1093 1094 } 1095 1096 out: 1097 1098 return ¤t_state; 1099 } 1100 1101 void 1102 updateregs(struct unwind_frame *uwf, struct staterecord *srec, 1103 uint64_t procoffset) 1104 { 1105 /* XXX: Update uwf for regs other than rp and pfs*/ 1106 uint64_t roffset = 0; 1107 1108 /* Uses shadow arrays to update uwf from srec in a loop. */ 1109 /* Count of number of regstate elements in struct staterecord */ 1110 int statecount = sizeof(struct staterecord)/sizeof(struct regstate); 1111 /* Pointer to current regstate. */ 1112 struct regstate *stptr = (void *) srec; 1113 /* Pointer to current unwind_frame element */ 1114 uint64_t *gr = (void *) uwf; 1115 1116 int i; 1117 1118 #ifdef UNWIND_DIAGNOSTIC 1119 printf("updateregs(): \n"); 1120 printf("procoffset (slots) = %lu \n", procoffset); 1121 #endif 1122 1123 for(i = 0; i < statecount; i++) { 1124 switch (stptr[i].where) { 1125 case IMMED: /* currently only mem_stack_f */ 1126 if (stptr[i].when >= procoffset) break; 1127 uwf->psp -= (stptr[i].offset << 4); 1128 break; 1129 1130 case GRREL: 1131 if (stptr[i].when >= procoffset) break; 1132 1133 roffset = stptr[i].offset; 1134 if (roffset == 0) { 1135 gr[i] = 0; 1136 break; 1137 } 1138 1139 1140 if (roffset < 32) { 1141 printf("GR%ld: static register save ??? \n", 1142 roffset); 1143 break; 1144 } 1145 1146 /* Fetch from bsp + offset - 32 + Adjust for RNAT. */ 1147 roffset -= 32; 1148 gr[i] = ia64_getrse_gr(uwf->bsp, roffset); 1149 break; 1150 1151 case SPREL: 1152 if (stptr[i].when >= procoffset) break; 1153 1154 /* Check if frame has been setup. */ 1155 if (srec->psp.offset == INVALID) { 1156 printf("sprel used without setting up " 1157 "stackframe!!! \n"); 1158 break; 1159 } 1160 1161 roffset = stptr[i].offset; 1162 1163 /* Fetch from sp + offset */ 1164 memcpy(&gr[i], (char *) uwf->sp + roffset * 4, 1165 sizeof(uint64_t)); 1166 break; 1167 1168 1169 case PSPREL: 1170 if (stptr[i].when >= procoffset) break; 1171 1172 /* Check if frame has been setup. */ 1173 if (srec->psp.offset == INVALID) { 1174 printf("psprel used without setting up " 1175 "stackframe!!! \n"); 1176 break; 1177 } 1178 1179 roffset = stptr[i].offset; 1180 1181 /* Fetch from sp + offset */ 1182 memcpy(&gr[i], (char *) uwf->psp + 16 - (roffset * 4), 1183 sizeof(uint64_t)); 1184 break; 1185 1186 case UNSAVED: 1187 case BRREL: 1188 default: 1189 #ifdef UNWIND_DIAGNOSTIC 1190 printf ("updateregs: reg[%d] is UNSAVED \n", i); 1191 #endif 1192 break; 1193 /* XXX: Not implemented yet. */ 1194 } 1195 1196 } 1197 1198 } 1199 1200 1201 /* 1202 * Locates unwind table entry, given unwind table entry info. 1203 * Expects the variables ia64_unwindtab, and ia64_unwindtablen 1204 * to be set appropriately. 1205 */ 1206 struct uwtable_ent * 1207 get_unwind_table_entry(uint64_t iprel) 1208 { 1209 1210 extern uint64_t ia64_unwindtab, ia64_unwindtablen; 1211 1212 struct uwtable_ent *uwt; 1213 int tabent; 1214 1215 1216 for(uwt = (struct uwtable_ent *) ia64_unwindtab, tabent = 0; 1217 /* The Runtime spec tells me the table entries are sorted. */ 1218 uwt->end <= iprel && tabent < ia64_unwindtablen; 1219 uwt++, tabent += sizeof(struct uwtable_ent)); 1220 1221 1222 if (!(uwt->start <= iprel && iprel < uwt->end)) { 1223 #ifdef UNWIND_DIAGNOSTIC 1224 printf("Entry not found \n"); 1225 printf("iprel = %lx \n", iprel); 1226 printf("uwt->start = %lx \nuwt->end = %lx \n", 1227 uwt->start, uwt->end); 1228 printf("tabent = %d \n", tabent); 1229 printf("ia64_unwindtablen = %ld \n", 1230 ia64_unwindtablen); 1231 #endif 1232 return NULL; 1233 } 1234 1235 #ifdef UNWIND_DIAGNOSTIC 1236 printf("uwt->start = %lx \nuwt->end = %lx \n" 1237 "uwt->infoptr = %p\n", uwt->start, uwt->end, uwt->infoptr); 1238 #endif 1239 1240 return uwt; 1241 } 1242 1243 1244 /* 1245 * Reads unwind table info and updates register values. 1246 */ 1247 void 1248 patchunwindframe(struct unwind_frame *uwf, uint64_t iprel, uint64_t relocoffset) 1249 { 1250 1251 extern struct recordchain strc[]; 1252 struct staterecord *srec; 1253 struct uwtable_ent *uwt; 1254 uint64_t infoptr, procoffset, slotoffset; 1255 1256 #if 0 /* does not work - moved to assertion at the call site */ 1257 if (iprel < 0) { 1258 panic("unwind ip out of range!!! \n"); 1259 return; 1260 } 1261 #endif 1262 1263 uwt = get_unwind_table_entry(iprel); 1264 1265 if (uwt == NULL) return; 1266 1267 infoptr = (uint64_t) uwt->infoptr + relocoffset; 1268 1269 if (infoptr > relocoffset) { 1270 buildrecordchain(infoptr, NULL); 1271 } else { 1272 return; 1273 } 1274 1275 slotoffset = iprel & 3; 1276 1277 /* procoffset in Number of _slots_ , _not_ a byte offset. */ 1278 1279 procoffset = (((iprel - slotoffset) - (uwt->start)) / 0x10 * 3) 1280 + slotoffset; 1281 srec = buildrecordstack(strc, procoffset); 1282 1283 updateregs(uwf, srec, procoffset); 1284 } 1285