1 1.9 dholland /* $NetBSD: stackframe.c,v 1.9 2016/07/31 19:33:18 dholland 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.8 dholland /* 23 1.8 dholland * Global variables: 24 1.8 dholland * array of struct recordchain 25 1.8 dholland * size of record chain array. 26 1.8 dholland */ 27 1.1 cherry struct recordchain strc[MAXSTATERECS]; 28 1.1 cherry int rec_cnt = 0; 29 1.1 cherry 30 1.8 dholland /* 31 1.8 dholland * 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.8 dholland void 35 1.8 dholland 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.9 dholland for (rec_cnt = 0; 68 1.9 dholland rec_cnt < MAXSTATERECS && (uint64_t)recptr < unwindend; 69 1.1 cherry rec_cnt++) { 70 1.9 dholland nextrecp = unwind_decode_R1(recptr, &strc[rec_cnt].udesc); 71 1.9 dholland 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.9 dholland nextrecp = unwind_decode_R2(recptr, &strc[rec_cnt].udesc); 80 1.9 dholland if (nextrecp) { 81 1.1 cherry region_len = strc[rec_cnt].udesc.R2.rlen; 82 1.8 dholland /* R2 regions are prologue regions */ 83 1.8 dholland 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.9 dholland nextrecp = unwind_decode_R3(recptr, &strc[rec_cnt].udesc); 90 1.9 dholland 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.9 dholland if (region_type == false) { 99 1.8 dholland /* Prologue Region */ 100 1.9 dholland nextrecp = unwind_decode_P1(recptr, 101 1.9 dholland &strc[rec_cnt].udesc); 102 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P2(recptr, 109 1.9 dholland &strc[rec_cnt].udesc); 110 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P3(recptr, 117 1.9 dholland &strc[rec_cnt].udesc); 118 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P4(recptr, 125 1.9 dholland &strc[rec_cnt].udesc, 126 1.9 dholland region_len); 127 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P5(recptr, 134 1.9 dholland &strc[rec_cnt].udesc); 135 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P6(recptr, 142 1.9 dholland &strc[rec_cnt].udesc); 143 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P7(recptr, 150 1.9 dholland &strc[rec_cnt].udesc); 151 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P8(recptr, 158 1.9 dholland &strc[rec_cnt].udesc); 159 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P9(recptr, 166 1.9 dholland &strc[rec_cnt].udesc); 167 1.9 dholland 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.9 dholland nextrecp = unwind_decode_P10(recptr, 174 1.9 dholland &strc[rec_cnt].udesc); 175 1.9 dholland 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.9 dholland } else { 183 1.1 cherry 184 1.9 dholland nextrecp = unwind_decode_B1(recptr, 185 1.9 dholland &strc[rec_cnt].udesc); 186 1.9 dholland 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.9 dholland nextrecp = unwind_decode_B2(recptr, 193 1.9 dholland &strc[rec_cnt].udesc); 194 1.9 dholland 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.9 dholland nextrecp = unwind_decode_B3(recptr, 201 1.9 dholland &strc[rec_cnt].udesc); 202 1.9 dholland 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.9 dholland nextrecp = unwind_decode_B4(recptr, 209 1.9 dholland &strc[rec_cnt].udesc); 210 1.9 dholland 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.9 dholland nextrecp = unwind_decode_X1(recptr, 217 1.9 dholland &strc[rec_cnt].udesc); 218 1.9 dholland 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.9 dholland nextrecp = unwind_decode_X2(recptr, 225 1.9 dholland &strc[rec_cnt].udesc); 226 1.9 dholland 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.9 dholland nextrecp = unwind_decode_X3(recptr, 234 1.9 dholland &strc[rec_cnt].udesc); 235 1.9 dholland 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.9 dholland nextrecp = unwind_decode_X4(recptr, 242 1.9 dholland &strc[rec_cnt].udesc); 243 1.9 dholland 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.8 dholland /* 266 1.8 dholland * Debug support: dump a record chain entry 267 1.8 dholland */ 268 1.8 dholland void 269 1.8 dholland 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.8 dholland /* 615 1.8 dholland * State record stuff..... based on section 11. and Appendix A. of the 616 1.8 dholland * "Itanium Software Conventions and Runtime Architecture Guide" 617 1.1 cherry */ 618 1.1 cherry 619 1.1 cherry 620 1.8 dholland /* 621 1.8 dholland * 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.8 dholland /* Base of spill area in memory stack frame as a psp relative offset */ 636 1.8 dholland uint64_t spill_base = 0; 637 1.1 cherry 638 1.8 dholland /* 639 1.8 dholland * 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.8 dholland /* 661 1.8 dholland * 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.8 dholland void 667 1.8 dholland modifyrecord(struct staterecord *srec, struct recordchain *rchain, 668 1.8 dholland uint64_t regionoffset) 669 1.1 cherry { 670 1.8 dholland /* 671 1.8 dholland * Default start save GR for prologue_save GRs. 672 1.8 dholland */ 673 1.8 dholland 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.8 dholland /* 680 1.8 dholland * 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.8 dholland /* 733 1.8 dholland * 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.9 dholland if (srec->psp.offset != INVALID) { 742 1.9 dholland printf("!!!saw mem_stack_f more than once. \n"); 743 1.9 dholland } 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.9 dholland /* spsz.offset is "overloaded" */ 748 1.9 dholland 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.9 dholland /* 770 1.9 dholland * XXX: Need to set to prologue_gr(grno) for 771 1.9 dholland * the orphan case ie; _gr/_psprel/_sprel 772 1.9 dholland * not set and therefore default to begin 773 1.9 dholland * 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.9 dholland /* 787 1.9 dholland * XXX: Need to set to prologue_gr(grno) for 788 1.9 dholland * the orphan case ie; _gr/_psprel/_sprel 789 1.9 dholland * not set and therefore default to begin 790 1.9 dholland * 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(¤t_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(¤t_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.8 dholland void 868 1.8 dholland 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.8 dholland /* 922 1.8 dholland * Push a state record on the record stack. 923 1.8 dholland */ 924 1.8 dholland void 925 1.8 dholland 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.8 dholland /* 938 1.8 dholland * Pop n state records off the record stack. 939 1.8 dholland */ 940 1.8 dholland void 941 1.8 dholland 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.8 dholland /* 956 1.8 dholland * Clone the whole record stack upto this one. 957 1.8 dholland */ 958 1.8 dholland void 959 1.8 dholland 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.8 dholland /* 967 1.8 dholland * Discard the current stack, and adopt a clone. 968 1.8 dholland */ 969 1.8 dholland void 970 1.8 dholland 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.8 dholland /* 979 1.8 dholland * 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.9 dholland * procoffset: offset of point of interest, in slots, within procedure 985 1.9 dholland * starting from slot 0 986 1.1 cherry * This routine obeys [1] 987 1.1 cherry */ 988 1.8 dholland struct staterecord * 989 1.8 dholland buildrecordstack(struct recordchain *rchain, uint64_t procoffset) 990 1.1 cherry { 991 1.9 dholland /* Current region length, defaults to zero if not specified */ 992 1.9 dholland uint64_t rlen = 0; 993 1.9 dholland /* Accumulated region length */ 994 1.9 dholland uint64_t roffset = 0; 995 1.9 dholland /* Offset within current region */ 996 1.9 dholland uint64_t rdepth = 0; 997 1.9 dholland 998 1.2 thorpej bool rtype; 999 1.8 dholland int i; 1000 1.1 cherry 1001 1.8 dholland /* Start with bottom of staterecord stack. */ 1002 1.8 dholland unwind_rsp = recordstack; 1003 1.1 cherry 1004 1.1 cherry initrecord(¤t_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.8 dholland if (procoffset < roffset) { 1012 1.8 dholland /* 1013 1.8 dholland * Overshot Region containing 1014 1.8 dholland * procoffset. Bail out. 1015 1.8 dholland */ 1016 1.8 dholland goto out; 1017 1.8 dholland } 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(¤t_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.8 dholland if (procoffset < roffset) { 1029 1.8 dholland /* 1030 1.8 dholland * Overshot Region containing 1031 1.8 dholland * procoffset. Bail out. 1032 1.8 dholland */ 1033 1.8 dholland goto out; 1034 1.8 dholland } 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(¤t_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.8 dholland if (procoffset < roffset) { 1046 1.8 dholland /* 1047 1.8 dholland * Overshot Region containing 1048 1.8 dholland * procoffset. Bail out. 1049 1.8 dholland */ 1050 1.8 dholland goto out; 1051 1.8 dholland } 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(¤t_state); 1056 1.1 cherry 1057 1.1 cherry /* R2 has save info. Continue down. */ 1058 1.8 dholland /* 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(¤t_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.9 dholland modifyrecord(¤t_state, &rchain[i], 1077 1.9 dholland 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(¤t_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 ¤t_state; 1099 1.1 cherry } 1100 1.1 cherry 1101 1.8 dholland void 1102 1.9 dholland updateregs(struct unwind_frame *uwf, struct staterecord *srec, 1103 1.9 dholland 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.8 dholland int i; 1117 1.1 cherry 1118 1.8 dholland #ifdef UNWIND_DIAGNOSTIC 1119 1.8 dholland printf("updateregs(): \n"); 1120 1.8 dholland printf("procoffset (slots) = %lu \n", procoffset); 1121 1.8 dholland #endif 1122 1.1 cherry 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.9 dholland printf("GR%ld: static register save ??? \n", 1142 1.9 dholland 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.9 dholland printf("sprel used without setting up " 1157 1.9 dholland "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.9 dholland memcpy(&gr[i], (char *) uwf->sp + roffset * 4, 1165 1.9 dholland 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.9 dholland printf("psprel used without setting up " 1175 1.9 dholland "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.9 dholland memcpy(&gr[i], (char *) uwf->psp + 16 - (roffset * 4), 1183 1.9 dholland 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.8 dholland /* 1202 1.8 dholland * 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.8 dholland int tabent; 1214 1.1 cherry 1215 1.1 cherry 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.9 dholland 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.6 dholland #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.6 dholland #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.8 dholland } else { 1272 1.8 dholland 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.9 dholland procoffset = (((iprel - slotoffset) - (uwt->start)) / 0x10 * 3) 1280 1.9 dholland + 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