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