1 /* $NetBSD: stackframe.c,v 1.3 2007/02/28 04:21:51 thorpej Exp $ */
3 /* Contributed to the NetBSD foundation by Cherry G. Mathew <cherry@mahiti.org>
4 * This file contains routines to use decoded unwind descriptor entries
5 * to build a stack configuration. The unwinder consults the stack
6 * configuration to fetch registers used to unwind the frame.
8 * [1] section. 11.4.2.6., Itanium Software Conventions and
9 * Runtime Architecture Guide.
12 #include <sys/cdefs.h>
13 #include <sys/param.h>
14 #include <sys/systm.h>
17 #include <ia64/unwind/decode.h>
18 #include <ia64/unwind/stackframe.h>
20 //#define UNWIND_DIAGNOSTIC
23 array of struct recordchain
24 size of record chain array.
26 struct recordchain strc
[MAXSTATERECS
];
29 /* Build a recordchain of a region, given the pointer to unwind table
30 * entry, and the number of entries to decode.
33 void buildrecordchain(uint64_t unwind_infop
, struct recordchain
*xxx
)
37 uint64_t unwindstart
, unwindend
;
39 uint64_t region_len
= 0;
40 bool region_type
= false; /* Prologue */
44 } *uwhp
= (void *) unwind_infop
;
46 char *nextrecp
, *recptr
= (char *) unwind_infop
+ sizeof(uint64_t);
48 unwindstart
= (uint64_t) recptr
;
50 if (UNW_VER(uwhp
->uwh
) != 1) {
51 printf("Wrong unwind version! \n");
55 unwindlen
= UNW_LENGTH(uwhp
->uwh
) * sizeof(uint64_t);
56 unwindend
= unwindstart
+ unwindlen
;
58 #ifdef UNWIND_DIAGNOSTIC
59 printf("recptr = %p \n", recptr
);
60 printf("unwindlen = %lx \n", unwindlen
);
61 printf("unwindend = %lx \n", unwindend
);
64 /* XXX: Ignore zero length records. */
67 for(rec_cnt
= 0; rec_cnt
< MAXSTATERECS
&& (uint64_t)recptr
< unwindend
;
69 if ((nextrecp
= unwind_decode_R1(recptr
, &strc
[rec_cnt
].udesc
))){
70 region_len
= strc
[rec_cnt
].udesc
.R1
.rlen
;
71 region_type
= strc
[rec_cnt
].udesc
.R1
.r
;
72 strc
[rec_cnt
].type
= R1
;
77 if ((nextrecp
= unwind_decode_R2(recptr
, &strc
[rec_cnt
].udesc
))){
78 region_len
= strc
[rec_cnt
].udesc
.R2
.rlen
;
79 region_type
= false; /* R2 regions are prologue regions */
80 strc
[rec_cnt
].type
= R2
;
85 if ((nextrecp
= unwind_decode_R3(recptr
, &strc
[rec_cnt
].udesc
))){
86 region_len
= strc
[rec_cnt
].udesc
.R3
.rlen
;
87 region_type
= strc
[rec_cnt
].udesc
.R3
.r
;
88 strc
[rec_cnt
].type
= R3
;
93 if(region_type
== false) { /* Prologue Region */
94 if ((nextrecp
= unwind_decode_P1(recptr
, &strc
[rec_cnt
].udesc
))){
95 strc
[rec_cnt
].type
= P1
;
100 if ((nextrecp
= unwind_decode_P2(recptr
, &strc
[rec_cnt
].udesc
))){
101 strc
[rec_cnt
].type
= P2
;
106 if ((nextrecp
= unwind_decode_P3(recptr
, &strc
[rec_cnt
].udesc
))){
107 strc
[rec_cnt
].type
= P3
;
113 if ((nextrecp
= unwind_decode_P4(recptr
, &strc
[rec_cnt
].udesc
, region_len
))){
114 strc
[rec_cnt
].type
= P4
;
120 if ((nextrecp
= unwind_decode_P5(recptr
, &strc
[rec_cnt
].udesc
))){
121 strc
[rec_cnt
].type
= P5
;
126 if ((nextrecp
= unwind_decode_P6(recptr
, &strc
[rec_cnt
].udesc
))){
127 strc
[rec_cnt
].type
= P6
;
132 if ((nextrecp
= unwind_decode_P7(recptr
, &strc
[rec_cnt
].udesc
))){
133 strc
[rec_cnt
].type
= P7
;
138 if ((nextrecp
= unwind_decode_P8(recptr
, &strc
[rec_cnt
].udesc
))){
139 strc
[rec_cnt
].type
= P8
;
144 if ((nextrecp
= unwind_decode_P9(recptr
, &strc
[rec_cnt
].udesc
))){
145 strc
[rec_cnt
].type
= P9
;
150 if ((nextrecp
= unwind_decode_P10(recptr
, &strc
[rec_cnt
].udesc
))){
151 strc
[rec_cnt
].type
= P10
;
156 printf("Skipping prologue desc slot :: %d \n", rec_cnt
);
161 if ((nextrecp
= unwind_decode_B1(recptr
, &strc
[rec_cnt
].udesc
))){
162 strc
[rec_cnt
].type
= B1
;
167 if ((nextrecp
= unwind_decode_B2(recptr
, &strc
[rec_cnt
].udesc
))){
168 strc
[rec_cnt
].type
= B2
;
173 if ((nextrecp
= unwind_decode_B3(recptr
, &strc
[rec_cnt
].udesc
))){
174 strc
[rec_cnt
].type
= B3
;
179 if ((nextrecp
= unwind_decode_B4(recptr
, &strc
[rec_cnt
].udesc
))){
180 strc
[rec_cnt
].type
= B4
;
185 if ((nextrecp
= unwind_decode_X1(recptr
, &strc
[rec_cnt
].udesc
))){
186 strc
[rec_cnt
].type
= X1
;
191 if ((nextrecp
= unwind_decode_X2(recptr
, &strc
[rec_cnt
].udesc
))){
192 strc
[rec_cnt
].type
= X2
;
198 if ((nextrecp
= unwind_decode_X3(recptr
, &strc
[rec_cnt
].udesc
))){
199 strc
[rec_cnt
].type
= X3
;
204 if ((nextrecp
= unwind_decode_X4(recptr
, &strc
[rec_cnt
].udesc
))){
205 strc
[rec_cnt
].type
= X4
;
210 printf("Skipping body desc slot :: %d \n", rec_cnt
);
216 #ifdef UNWIND_DIAGNOSTIC
218 for(i
= 0;i
< rec_cnt
;i
++) {
219 dump_recordchain(&strc
[i
]);
222 #endif /* UNWIND_DIAGNOSTIC */
229 /* Debug support: dump a record chain entry */
230 void dump_recordchain(struct recordchain
*rchain
)
233 switch(rchain
->type
) {
238 if(rchain
->udesc
.R1
.r
)
241 printf("prologue (");
242 printf("rlen = %ld) \n", rchain
->udesc
.R1
.rlen
);
247 printf("prologue_gr (");
248 printf("mask = %x, ", rchain
->udesc
.R2
.mask
);
249 printf("grsave = %d, ", rchain
->udesc
.R2
.grsave
);
250 printf("rlen = %ld )\n", rchain
->udesc
.R2
.rlen
);
255 if(rchain
->udesc
.R3
.r
)
258 printf("prologue (");
259 printf("rlen = %ld )\n", rchain
->udesc
.R3
.rlen
);
264 printf("br_mem (brmask = %x) \n", rchain
->udesc
.P1
.brmask
);
269 printf("br_gr(brmask = %x, ", rchain
->udesc
.P2
.brmask
);
270 printf("gr = %d ) \n", rchain
->udesc
.P2
.gr
);
275 switch(rchain
->udesc
.P3
.r
) {
304 printf("bspstore_gr");
310 printf("priunat_gr");
313 printf("unknown desc: %d", rchain
->udesc
.P3
.r
);
316 printf("(gr/br = %d) \n", rchain
->udesc
.P3
.grbr
);
321 printf("P4: (unimplemented): \n");
326 printf("frgr_mem(grmask = %x, frmask = %x )\n",
327 rchain
->udesc
.P5
.grmask
, rchain
->udesc
.P5
.frmask
);
332 if(rchain
->udesc
.P6
.r
)
336 printf("rmask = %x) \n", rchain
->udesc
.P6
.rmask
);
341 switch(rchain
->udesc
.P7
.r
) {
343 printf("memstack_f( ");
344 printf("t = %ld, ", rchain
->udesc
.P7
.t
);
345 printf("size = %ld) \n", rchain
->udesc
.P7
.size
);
348 printf("memstack_v( ");
349 printf("t = %ld) \n", rchain
->udesc
.P7
.t
);
352 printf("spillbase( ");
353 printf("pspoff = %ld) \n", rchain
->udesc
.P7
.t
);
356 printf("psp_sprel( ");
357 printf("spoff = %ld) \n", rchain
->udesc
.P7
.t
);
361 printf("t = %ld) \n", rchain
->udesc
.P7
.t
);
364 printf("rp_psprel( ");
365 printf("pspoff = %ld) \n", rchain
->udesc
.P7
.t
);
368 printf("pfs_when( ");
369 printf("t = %ld) \n", rchain
->udesc
.P7
.t
);
372 printf("pfs_psprel( ");
373 printf("pspoff = %ld) \n", rchain
->udesc
.P7
.t
);
376 printf("preds_when( ");
377 printf("t = %ld) \n", rchain
->udesc
.P7
.t
);
380 printf("preds_psprel( ");
381 printf("pspoff = %ld) \n", rchain
->udesc
.P7
.t
);
385 printf("t = %ld) \n", rchain
->udesc
.P7
.t
);
388 printf("lc_psprel( ");
389 printf("pspoff = %ld) \n", rchain
->udesc
.P7
.t
);
392 printf("unat_when( ");
393 printf("t = %ld) \n", rchain
->udesc
.P7
.t
);
396 printf("unat_psprel( ");
397 printf("pspoff = %ld) \n", rchain
->udesc
.P7
.t
);
400 printf("fpsr_when( ");
401 printf("t = %ld) \n", rchain
->udesc
.P7
.t
);
404 printf("fpsr_psprel( ");
405 printf("pspoff = %ld) \n", rchain
->udesc
.P7
.t
);
408 printf("unknown \n");
415 switch(rchain
->udesc
.P8
.r
) {
417 printf("rp_sprel( ");
418 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
421 printf("pfs_sprel( ");
422 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
425 printf("preds_sprel( ");
426 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
429 printf("lc_sprel( ");
430 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
433 printf("unat_sprel( ");
434 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
437 printf("fpsr_sprel( ");
438 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
441 printf("bsp_when( ");
442 printf("t = %ld) \n", rchain
->udesc
.P8
.t
);
445 printf("bsp_psprel( ");
446 printf("pspoff = %ld) \n", rchain
->udesc
.P8
.t
);
449 printf("bsp_sprel( ");
450 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
453 printf("bspstore_when( ");
454 printf("t = %ld) \n", rchain
->udesc
.P8
.t
);
457 printf("bspstore_psprel( ");
458 printf("pspoff = %ld) \n", rchain
->udesc
.P8
.t
);
461 printf("bspstore_sprel( ");
462 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
465 printf("rnat_when( ");
466 printf("t = %ld) \n", rchain
->udesc
.P8
.t
);
469 printf("rnat_psprel( ");
470 printf("pspoff = %ld) \n", rchain
->udesc
.P8
.t
);
473 printf("rnat_sprel( ");
474 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
477 printf("priunat_when_gr( ");
478 printf("t = %ld) \n", rchain
->udesc
.P8
.t
);
481 printf("priunat_psprel( ");
482 printf("pspoff = %ld) \n", rchain
->udesc
.P8
.t
);
485 printf("priunat_sprel( ");
486 printf("spoff = %ld) \n", rchain
->udesc
.P8
.t
);
489 printf("priunat_when_mem( ");
490 printf("t = %ld) \n", rchain
->udesc
.P8
.t
);
494 printf("unknown \n");
501 printf("(grmask = %x, gr = %d) \n",
502 rchain
->udesc
.P9
.grmask
, rchain
->udesc
.P9
.gr
);
508 switch(rchain
->udesc
.P10
.abi
) {
510 printf("Unix SVR4) \n");
522 if(rchain
->udesc
.B1
.r
)
523 printf("copy_state( ");
525 printf("label_state( ");
526 printf("label = %d) \n", rchain
->udesc
.B1
.label
);
532 printf("(ecount = %d, t = %ld)\n",
533 rchain
->udesc
.B2
.ecount
, rchain
->udesc
.B2
.t
);
539 printf("(t = %ld, ecount = %ld) \n",
540 rchain
->udesc
.B3
.t
, rchain
->udesc
.B3
.ecount
);
546 if(rchain
->udesc
.B4
.r
)
547 printf("copy_state( ");
549 printf("label_state( ");
551 printf("label = %ld) \n", rchain
->udesc
.B4
.label
);
572 printf("\tunknow: \n");
577 /* State record stuff..... based on section 11. and Appendix A. of the
578 *"Itanium Software Conventions and Runtime Architecture Guide"
583 * 1. Two arrays of staterecords: recordstack[], recordstackcopy[]
584 * XXX: Since we don't use malloc, we have two arbitrary sized arrays
585 * providing guaranteed memory from the BSS. See the TODO file
587 * 2. Two head variables to hold the member index: unwind_rsp,unwind_rscp
590 struct staterecord recordstack
[MAXSTATERECS
];
591 struct staterecord recordstackcopy
[MAXSTATERECS
];
592 struct staterecord current_state
;
593 struct staterecord
*unwind_rsp
, *unwind_rscp
;
596 uint64_t spill_base
= 0; /* Base of spill area in memory stack frame as a psp relative offset */
598 /* Initialises a staterecord from a given template,
599 * with default values as described by the Runtime Spec.
603 initrecord(struct staterecord
*target
)
605 target
->bsp
.where
= UNSAVED
;
606 target
->bsp
.when
= 0;
607 target
->bsp
.offset
= INVALID
;
608 target
->psp
.where
= UNSAVED
;
609 target
->psp
.when
= 0;
610 target
->psp
.offset
= INVALID
;
611 target
->rp
.where
= UNSAVED
;
613 target
->rp
.offset
= INVALID
;
614 target
->pfs
.where
= UNSAVED
;
615 target
->pfs
.when
= 0;
616 target
->pfs
.offset
= INVALID
;
620 /* Modifies a staterecord structure by parsing
621 * a single record chain structure.
622 * regionoffset is the offset within a (prologue) region
623 * where the stack unwinding began.
626 void modifyrecord(struct staterecord
*srec
, struct recordchain
*rchain
,
627 uint64_t regionoffset
)
631 uint64_t grno
= 32; /* Default start save GR for prologue_save
637 switch (rchain
->type
) {
640 /* R2, prologue_gr is the only region encoding
641 * with register save info.
644 grno
= rchain
->udesc
.R2
.grsave
;
646 if (rchain
->udesc
.R2
.mask
& R2MASKRP
) {
648 srec
->rp
.where
= GRREL
;
649 srec
->rp
.offset
= grno
++;
652 if (rchain
->udesc
.R2
.mask
& R2MASKPFS
) {
654 srec
->pfs
.where
= GRREL
;
655 srec
->pfs
.offset
= grno
++;
658 if (rchain
->udesc
.R2
.mask
& R2MASKPSP
) {
660 srec
->psp
.where
= GRREL
;
661 srec
->psp
.offset
= grno
++;
666 switch (rchain
->udesc
.P3
.r
) {
668 if (srec
->psp
.when
< regionoffset
) {
669 srec
->psp
.where
= GRREL
;
670 srec
->psp
.offset
= rchain
->udesc
.P3
.grbr
;
675 if (srec
->rp
.when
< regionoffset
) {
676 srec
->rp
.where
= GRREL
;
677 srec
->rp
.offset
= rchain
->udesc
.P3
.grbr
;
682 if (srec
->pfs
.when
< regionoffset
) {
683 srec
->pfs
.where
= GRREL
;
684 srec
->pfs
.offset
= rchain
->udesc
.P3
.grbr
;
692 /* XXX: P4 spill_mask and P7: spill_base are for GRs, FRs, and BRs.
693 * We're not particularly worried about those right now.
697 switch (rchain
->udesc
.P7
.r
) {
699 case 0: /* mem_stack_f */
700 if (srec
->psp
.offset
!= INVALID
) printf("!!!saw mem_stack_f more than once. \n");
701 srec
->psp
.when
= rchain
->udesc
.P7
.t
;
702 if (srec
->psp
.when
< regionoffset
) {
703 srec
->psp
.where
= IMMED
;
704 srec
->psp
.offset
= rchain
->udesc
.P7
.size
; /* spsz.offset is "overloaded" */
708 case 1: /* mem_stack_v */
709 srec
->psp
.when
= rchain
->udesc
.P7
.t
;
712 case 2: /* spill_base */
713 spill_base
= rchain
->udesc
.P7
.t
;
716 case 3: /* psp_sprel */
717 if (srec
->psp
.when
< regionoffset
) {
718 srec
->psp
.where
= SPREL
;
719 srec
->psp
.offset
= rchain
->udesc
.P7
.t
;
723 case 4: /* rp_when */
724 srec
->rp
.when
= rchain
->udesc
.P7
.t
;
725 /* XXX: Need to set to prologue_gr(grno) for the orphan case
726 * ie; _gr/_psprel/_sprel not set and therefore default
727 * to begin from the gr specified in prologue_gr.
731 case 5: /* rp_psprel */
732 if (srec
->rp
.when
< regionoffset
) {
733 srec
->rp
.where
= PSPREL
;
734 srec
->rp
.offset
= rchain
->udesc
.P7
.t
;
738 case 6: /* pfs_when */
739 srec
->pfs
.when
= rchain
->udesc
.P7
.t
;
740 /* XXX: Need to set to prologue_gr(grno) for the orphan case
741 * ie; _gr/_psprel/_sprel not set and therefore default
742 * to begin from the gr specified in prologue_gr.
746 case 7: /* pfs_psprel */
747 if (srec
->pfs
.when
< regionoffset
) {
748 srec
->pfs
.where
= PSPREL
;
749 srec
->pfs
.offset
= rchain
->udesc
.P7
.t
;
757 switch (rchain
->udesc
.P8
.r
) {
758 case 1: /* rp_sprel */
759 if (srec
->rp
.when
< regionoffset
) {
760 srec
->rp
.where
= SPREL
;
761 srec
->rp
.offset
= rchain
->udesc
.P8
.t
;
764 case 2: /* pfs_sprel */
765 if (srec
->pfs
.when
< regionoffset
) {
766 srec
->pfs
.where
= SPREL
;
767 srec
->pfs
.offset
= rchain
->udesc
.P8
.t
;
776 rchain
->udesc
.B1
.r
? switchrecordstack(0) :
781 if (regionoffset
< rchain
->udesc
.B2
.t
) {
782 poprecord(¤t_state
, rchain
->udesc
.B2
.ecount
);
786 if (regionoffset
< rchain
->udesc
.B3
.t
) {
787 poprecord(¤t_state
, rchain
->udesc
.B3
.ecount
);
791 rchain
->udesc
.B4
.r
? switchrecordstack(0) :
813 printf("XXX: Ignored. \n");
819 void dump_staterecord(struct staterecord
*srec
)
821 printf("rp.where: ");
822 switch(srec
->rp
.where
) {
842 printf(", rp.when = %lu, ", srec
->rp
.when
);
843 printf("rp.offset = %lu \n", srec
->rp
.offset
);
846 printf("pfs.where: ");
847 switch(srec
->pfs
.where
) {
867 printf(", pfs.when = %lu, ", srec
->pfs
.when
);
868 printf("pfs.offset = %lu \n", srec
->pfs
.offset
);
874 /* Push a state record on the record stack. */
876 void pushrecord(struct staterecord
*srec
)
878 if(unwind_rsp
>= recordstack
+ MAXSTATERECS
) {
879 printf("Push exceeded array size!!! \n");
883 memcpy(unwind_rsp
, srec
, sizeof(struct staterecord
));
888 /* Pop n state records off the record stack. */
890 void poprecord(struct staterecord
*srec
, int n
)
892 if(unwind_rsp
== recordstack
) {
893 printf("Popped beyond end of Stack!!! \n");
897 memcpy(srec
, unwind_rsp
, sizeof(struct staterecord
));
899 memset(unwind_rsp
, 0, sizeof(struct staterecord
) * n
);
904 /* Clone the whole record stack upto this one. */
905 void clonerecordstack(u_int label
)
907 memcpy(recordstackcopy
, recordstack
,
908 (unwind_rsp
- recordstack
) * sizeof(struct staterecord
));
909 unwind_rscp
= unwind_rsp
;
912 /* Discard the current stack, and adopt a clone. */
913 void switchrecordstack(u_int label
)
915 memcpy((void *) recordstack
, (void *) recordstackcopy
,
916 (unwind_rscp
- recordstackcopy
) * sizeof(struct staterecord
));
917 unwind_rsp
= unwind_rscp
;
921 /* In the context of a procedure:
922 * Parses through a record chain, building, pushing and/or popping staterecords,
923 * or cloning/destroying stacks of staterecords as required.
925 * rchain: pointer to recordchain array.
926 * procoffset: offset of point of interest, in slots, within procedure starting from slot 0
927 * This routine obeys [1]
929 struct staterecord
*buildrecordstack(struct recordchain
*rchain
, uint64_t procoffset
)
932 uint64_t rlen
= 0; /* Current region length, defaults to zero, if not specified */
933 uint64_t roffset
= 0; /* Accumulated region length */
934 uint64_t rdepth
= 0; /* Offset within current region */
937 char *spill_mask
= NULL
; /* Specifies when preserved registers are spilled, as a bit mask */
942 unwind_rsp
= recordstack
; /* Start with bottom of staterecord stack. */
944 initrecord(¤t_state
);
949 for (i
= 0;i
< rec_cnt
;i
++) {
951 switch (rchain
[i
].type
) {
953 rlen
= rchain
[i
].udesc
.R1
.rlen
;
954 rdepth
= procoffset
- roffset
;
955 if (rdepth
< 0) goto out
; /* Overshot Region containing procoffset. Bailout. */
957 rtype
= rchain
[i
].udesc
.R1
.r
;
959 pushrecord(¤t_state
);
964 rlen
= rchain
[i
].udesc
.R3
.rlen
;
965 rdepth
= procoffset
- roffset
;
966 if (rdepth
< 0) goto out
; /* Overshot Region containing procoffset. Bailout. */
968 rtype
= rchain
[i
].udesc
.R3
.r
;
970 pushrecord(¤t_state
);
975 rlen
= rchain
[i
].udesc
.R2
.rlen
;
976 rdepth
= procoffset
- roffset
;
977 if (rdepth
< 0) goto out
; /* Overshot Region containing procoffset. Bailout. */
979 rtype
= false; /* prologue region */
980 pushrecord(¤t_state
);
982 /* R2 has save info. Continue down. */
994 modifyrecord(¤t_state
, &rchain
[i
], rdepth
);
1001 modifyrecord(¤t_state
, &rchain
[i
], rlen
- 1 - rdepth
);
1009 printf("Error: Unknown descriptor type!!! \n");
1013 #if UNWIND_DIAGNOSTIC
1014 dump_staterecord(¤t_state
);
1022 return ¤t_state
;
1025 void updateregs(struct unwind_frame
*uwf
, struct staterecord
*srec
, uint64_t procoffset
)
1028 #ifdef UNWIND_DIAGNOSTIC
1029 printf("updateregs(): \n");
1030 printf("procoffset (slots) = %lu \n", procoffset
);
1032 /* XXX: Update uwf for regs other than rp and pfs*/
1033 uint64_t roffset
= 0;
1036 /* Uses shadow arrays to update uwf from srec in a loop. */
1037 /* Count of number of regstate elements in struct staterecord */
1038 int statecount
= sizeof(struct staterecord
)/sizeof(struct regstate
);
1039 /* Pointer to current regstate. */
1040 struct regstate
*stptr
= (void *) srec
;
1041 /* Pointer to current unwind_frame element */
1042 uint64_t *gr
= (void *) uwf
;
1047 for(i
= 0; i
< statecount
; i
++) {
1048 switch (stptr
[i
].where
) {
1049 case IMMED
: /* currently only mem_stack_f */
1050 if (stptr
[i
].when
>= procoffset
) break;
1051 uwf
->psp
-= (stptr
[i
].offset
<< 4);
1055 if (stptr
[i
].when
>= procoffset
) break;
1057 roffset
= stptr
[i
].offset
;
1065 printf("GR%ld: static register save ??? \n", roffset
);
1069 /* Fetch from bsp + offset - 32 + Adjust for RNAT. */
1071 gr
[i
] = ia64_getrse_gr(uwf
->bsp
, roffset
);
1075 if (stptr
[i
].when
>= procoffset
) break;
1077 /* Check if frame has been setup. */
1078 if (srec
->psp
.offset
== INVALID
) {
1079 printf("sprel used without setting up stackframe!!! \n");
1083 roffset
= stptr
[i
].offset
;
1085 /* Fetch from sp + offset */
1086 memcpy(&gr
[i
], (char *) uwf
->sp
+ roffset
* 4, sizeof(uint64_t));
1091 if (stptr
[i
].when
>= procoffset
) break;
1093 /* Check if frame has been setup. */
1094 if (srec
->psp
.offset
== INVALID
) {
1095 printf("psprel used without setting up stackframe!!! \n");
1099 roffset
= stptr
[i
].offset
;
1101 /* Fetch from sp + offset */
1102 memcpy(&gr
[i
], (char *) uwf
->psp
+ 16 - (roffset
* 4), sizeof(uint64_t));
1108 #ifdef UNWIND_DIAGNOSTIC
1109 printf ("updateregs: reg[%d] is UNSAVED \n", i
);
1112 /* XXX: Not implemented yet. */
1120 /* Locates unwind table entry, given unwind table entry info.
1121 * Expects the variables ia64_unwindtab, and ia64_unwindtablen
1122 * to be set appropriately.
1125 struct uwtable_ent
*
1126 get_unwind_table_entry(uint64_t iprel
)
1129 extern uint64_t ia64_unwindtab
, ia64_unwindtablen
;
1131 struct uwtable_ent
*uwt
;
1136 for(uwt
= (struct uwtable_ent
*) ia64_unwindtab
, tabent
= 0;
1137 /* The Runtime spec tells me the table entries are sorted. */
1138 uwt
->end
<= iprel
&& tabent
< ia64_unwindtablen
;
1139 uwt
++, tabent
+= sizeof(struct uwtable_ent
));
1142 if (!(uwt
->start
<= iprel
&& iprel
< uwt
->end
)) {
1143 #ifdef UNWIND_DIAGNOSTIC
1144 printf("Entry not found \n");
1145 printf("iprel = %lx \n", iprel
);
1146 printf("uwt->start = %lx \nuwt->end = %lx \n",
1147 uwt
->start
, uwt
->end
);
1148 printf("tabent = %d \n", tabent
);
1149 printf("ia64_unwindtablen = %ld \n",
1155 #ifdef UNWIND_DIAGNOSTIC
1156 printf("uwt->start = %lx \nuwt->end = %lx \n"
1157 "uwt->infoptr = %p\n", uwt
->start
, uwt
->end
, uwt
->infoptr
);
1165 * Reads unwind table info and updates register values.
1169 patchunwindframe(struct unwind_frame
*uwf
, uint64_t iprel
, uint64_t relocoffset
)
1172 extern struct recordchain strc
[];
1173 struct staterecord
*srec
;
1174 struct uwtable_ent
*uwt
;
1175 uint64_t infoptr
, procoffset
, slotoffset
;
1178 panic("unwind ip out of range!!! \n");
1183 uwt
= get_unwind_table_entry(iprel
);
1185 if (uwt
== NULL
) return;
1187 infoptr
= (uint64_t) uwt
->infoptr
+ relocoffset
;
1189 if (infoptr
> relocoffset
) {
1190 buildrecordchain(infoptr
, NULL
);
1194 slotoffset
= iprel
& 3;
1196 /* procoffset in Number of _slots_ , _not_ a byte offset. */
1198 procoffset
= (((iprel
- slotoffset
) - (uwt
->start
)) / 0x10 * 3) + slotoffset
;
1199 srec
= buildrecordstack(strc
, procoffset
);
1201 updateregs(uwf
, srec
, procoffset
);