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