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