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