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