/src/binutils-gdb/binutils/unwind-ia64.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf. |
2 | | Copyright (C) 2000-2024 Free Software Foundation, Inc. |
3 | | |
4 | | Contributed by David Mosberger-Tang <davidm@hpl.hp.com> |
5 | | |
6 | | This file is part of GNU Binutils. |
7 | | |
8 | | This program is free software; you can redistribute it and/or modify |
9 | | it under the terms of the GNU General Public License as published by |
10 | | the Free Software Foundation; either version 3, or (at your option) |
11 | | any later version. |
12 | | |
13 | | This program is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with this program; if not, write to the Free Software |
20 | | Foundation, 51 Franklin Street - Fifth Floor, Boston, |
21 | | MA 02110-1301, USA. */ |
22 | | |
23 | | #include "config.h" |
24 | | #include "sysdep.h" |
25 | | #include "unwind-ia64.h" |
26 | | |
27 | | #if __GNUC__ >= 2 |
28 | | /* Define BFD64 here, even if our default architecture is 32 bit ELF |
29 | | as this will allow us to read in and parse 64bit and 32bit ELF files. |
30 | | Only do this if we believe that the compiler can support a 64 bit |
31 | | data type. For now we only rely on GCC being able to do this. */ |
32 | | #define BFD64 |
33 | | #endif |
34 | | #include "bfd.h" |
35 | | |
36 | | static bfd_vma unw_rlen = 0; |
37 | | |
38 | | static void unw_print_brmask (char *, unsigned int); |
39 | | static void unw_print_grmask (char *, unsigned int); |
40 | | static void unw_print_frmask (char *, unsigned int); |
41 | | static void unw_print_abreg (char *, unsigned int); |
42 | | static void unw_print_xyreg (char *, unsigned int, unsigned int); |
43 | | |
44 | | static void |
45 | | unw_print_brmask (char *cp, unsigned int mask) |
46 | 983k | { |
47 | 983k | int sep = 0; |
48 | 983k | int i; |
49 | | |
50 | 4.50M | for (i = 0; mask && (i < 5); ++i) |
51 | 3.51M | { |
52 | 3.51M | if (mask & 1) |
53 | 2.13M | { |
54 | 2.13M | if (sep) |
55 | 1.27M | *cp++ = ','; |
56 | 2.13M | *cp++ = 'b'; |
57 | 2.13M | *cp++ = i + 1 + '0'; |
58 | 2.13M | sep = 1; |
59 | 2.13M | } |
60 | 3.51M | mask >>= 1; |
61 | 3.51M | } |
62 | 983k | *cp = '\0'; |
63 | 983k | } |
64 | | |
65 | | static void |
66 | | unw_print_grmask (char *cp, unsigned int mask) |
67 | 1.25M | { |
68 | 1.25M | int sep = 0; |
69 | 1.25M | int i; |
70 | | |
71 | 6.27M | for (i = 0; i < 4; ++i) |
72 | 5.02M | { |
73 | 5.02M | if (mask & 1) |
74 | 902k | { |
75 | 902k | if (sep) |
76 | 486k | *cp++ = ','; |
77 | 902k | *cp++ = 'r'; |
78 | 902k | *cp++ = i + 4 + '0'; |
79 | 902k | sep = 1; |
80 | 902k | } |
81 | 5.02M | mask >>= 1; |
82 | 5.02M | } |
83 | 1.25M | *cp = '\0'; |
84 | 1.25M | } |
85 | | |
86 | | static void |
87 | | unw_print_frmask (char *cp, unsigned int mask) |
88 | 283k | { |
89 | 283k | int sep = 0; |
90 | 283k | int i; |
91 | | |
92 | 5.95M | for (i = 0; i < 20; ++i) |
93 | 5.67M | { |
94 | 5.67M | if (mask & 1) |
95 | 897k | { |
96 | 897k | if (sep) |
97 | 646k | *cp++ = ','; |
98 | 897k | *cp++ = 'f'; |
99 | 897k | if (i < 4) |
100 | 515k | *cp++ = i + 2 + '0'; |
101 | 382k | else |
102 | 382k | { |
103 | 382k | *cp++ = (i + 2) / 10 + 1 + '0'; |
104 | 382k | *cp++ = (i + 2) % 10 + '0'; |
105 | 382k | } |
106 | 897k | sep = 1; |
107 | 897k | } |
108 | 5.67M | mask >>= 1; |
109 | 5.67M | } |
110 | 283k | *cp = '\0'; |
111 | 283k | } |
112 | | |
113 | | static void |
114 | | unw_print_abreg (char *cp, unsigned int abreg) |
115 | 211k | { |
116 | 211k | static const char * const special_reg[16] = |
117 | 211k | { |
118 | 211k | "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat", |
119 | 211k | "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc", |
120 | 211k | "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15" |
121 | 211k | }; |
122 | | |
123 | 211k | switch ((abreg >> 5) & 0x3) |
124 | 211k | { |
125 | 59.2k | case 0: /* gr */ |
126 | 59.2k | sprintf (cp, "r%u", (abreg & 0x1f)); |
127 | 59.2k | break; |
128 | | |
129 | 41.4k | case 1: /* fr */ |
130 | 41.4k | sprintf (cp, "f%u", (abreg & 0x1f)); |
131 | 41.4k | break; |
132 | | |
133 | 25.7k | case 2: /* br */ |
134 | 25.7k | sprintf (cp, "b%u", (abreg & 0x1f)); |
135 | 25.7k | break; |
136 | | |
137 | 85.2k | case 3: /* special */ |
138 | 85.2k | strcpy (cp, special_reg[abreg & 0xf]); |
139 | 85.2k | break; |
140 | 211k | } |
141 | 211k | } |
142 | | |
143 | | static void |
144 | | unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg) |
145 | 85.0k | { |
146 | 85.0k | switch ((x << 1) | ((ytreg >> 7) & 1)) |
147 | 85.0k | { |
148 | 24.0k | case 0: /* gr */ |
149 | 24.0k | sprintf (cp, "r%u", (ytreg & 0x1f)); |
150 | 24.0k | break; |
151 | | |
152 | 9.93k | case 1: /* fr */ |
153 | 9.93k | sprintf (cp, "f%u", (ytreg & 0x1f)); |
154 | 9.93k | break; |
155 | | |
156 | 14.6k | case 2: /* br */ |
157 | 14.6k | sprintf (cp, "b%u", (ytreg & 0x1f)); |
158 | 14.6k | break; |
159 | | |
160 | 36.3k | default: |
161 | 36.3k | strcpy (cp, "invalid"); |
162 | 36.3k | break; |
163 | 85.0k | } |
164 | 85.0k | } |
165 | | |
166 | | #define UNW_REG_BSP "bsp" |
167 | | #define UNW_REG_BSPSTORE "bspstore" |
168 | | #define UNW_REG_FPSR "fpsr" |
169 | | #define UNW_REG_LC "lc" |
170 | | #define UNW_REG_PFS "pfs" |
171 | | #define UNW_REG_PR "pr" |
172 | | #define UNW_REG_PSP "psp" |
173 | | #define UNW_REG_RNAT "rnat" |
174 | | #define UNW_REG_RP "rp" |
175 | | #define UNW_REG_UNAT "unat" |
176 | | |
177 | | typedef bfd_vma unw_word; |
178 | | |
179 | | #define UNW_DEC_BAD_CODE(code) \ |
180 | 858k | printf (_("Unknown code 0x%02x\n"), code) |
181 | | |
182 | | #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \ |
183 | 26.7M | do \ |
184 | 26.7M | { \ |
185 | 26.7M | unw_rlen = rlen; \ |
186 | 26.7M | *(int *)arg = body; \ |
187 | 26.7M | printf (" %s:%s(rlen=%lu)\n", \ |
188 | 26.7M | fmt, body ? "body" : "prologue", (unsigned long) rlen); \ |
189 | 26.7M | } \ |
190 | 26.7M | while (0) |
191 | | |
192 | | #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \ |
193 | 1.22M | do \ |
194 | 1.22M | { \ |
195 | 1.22M | char regname[16], maskstr[64], *sep; \ |
196 | 1.22M | \ |
197 | 1.22M | unw_rlen = rlen; \ |
198 | 1.22M | *(int *)arg = 0; \ |
199 | 1.22M | \ |
200 | 1.22M | maskstr[0] = '\0'; \ |
201 | 1.22M | sep = ""; \ |
202 | 1.22M | if (mask & 0x8) \ |
203 | 1.22M | { \ |
204 | 677k | strcat (maskstr, "rp"); \ |
205 | 677k | sep = ","; \ |
206 | 677k | } \ |
207 | 1.22M | if (mask & 0x4) \ |
208 | 1.22M | { \ |
209 | 421k | strcat (maskstr, sep); \ |
210 | 421k | strcat (maskstr, "ar.pfs"); \ |
211 | 421k | sep = ","; \ |
212 | 421k | } \ |
213 | 1.22M | if (mask & 0x2) \ |
214 | 1.22M | { \ |
215 | 442k | strcat (maskstr, sep); \ |
216 | 442k | strcat (maskstr, "psp"); \ |
217 | 442k | sep = ","; \ |
218 | 442k | } \ |
219 | 1.22M | if (mask & 0x1) \ |
220 | 1.22M | { \ |
221 | 246k | strcat (maskstr, sep); \ |
222 | 246k | strcat (maskstr, "pr"); \ |
223 | 246k | } \ |
224 | 1.22M | sprintf (regname, "r%u", grsave); \ |
225 | 1.22M | printf (" %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \ |
226 | 1.22M | fmt, maskstr, regname, (unsigned long) rlen); \ |
227 | 1.22M | } \ |
228 | 1.22M | while (0) |
229 | | |
230 | | #define UNW_DEC_FR_MEM(fmt, frmask, arg) \ |
231 | 237k | do \ |
232 | 237k | { \ |
233 | 237k | char frstr[200]; \ |
234 | 237k | \ |
235 | 237k | unw_print_frmask (frstr, frmask); \ |
236 | 237k | printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \ |
237 | 237k | } \ |
238 | 237k | while (0) |
239 | | |
240 | | #define UNW_DEC_GR_MEM(fmt, grmask, arg) \ |
241 | 1.17M | do \ |
242 | 1.17M | { \ |
243 | 1.17M | char grstr[200]; \ |
244 | 1.17M | \ |
245 | 1.17M | unw_print_grmask (grstr, grmask); \ |
246 | 1.17M | printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \ |
247 | 1.17M | } \ |
248 | 1.17M | while (0) |
249 | | |
250 | | #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \ |
251 | 45.9k | do \ |
252 | 45.9k | { \ |
253 | 45.9k | char frstr[200], grstr[20]; \ |
254 | 45.9k | \ |
255 | 45.9k | unw_print_grmask (grstr, grmask); \ |
256 | 45.9k | unw_print_frmask (frstr, frmask); \ |
257 | 45.9k | printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr); \ |
258 | 45.9k | } \ |
259 | 45.9k | while (0) |
260 | | |
261 | | #define UNW_DEC_BR_MEM(fmt, brmask, arg) \ |
262 | 727k | do \ |
263 | 727k | { \ |
264 | 727k | char brstr[20]; \ |
265 | 727k | \ |
266 | 727k | unw_print_brmask (brstr, brmask); \ |
267 | 727k | printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \ |
268 | 727k | } \ |
269 | 727k | while (0) |
270 | | |
271 | | #define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \ |
272 | 256k | do \ |
273 | 256k | { \ |
274 | 256k | char brstr[20]; \ |
275 | 256k | \ |
276 | 256k | unw_print_brmask (brstr, brmask); \ |
277 | 256k | printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \ |
278 | 256k | } \ |
279 | 256k | while (0) |
280 | | |
281 | | #define UNW_DEC_REG_GR(fmt, src, dst, arg) \ |
282 | 186k | printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst) |
283 | | |
284 | | #define UNW_DEC_RP_BR(fmt, dst, arg) \ |
285 | 16.2k | printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst) |
286 | | |
287 | | #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \ |
288 | 132k | printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t) |
289 | | |
290 | | #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \ |
291 | 38.8k | printf ("\t%s:%s_sprel(spoff=0x%lx)\n", \ |
292 | 38.8k | fmt, reg, 4*(unsigned long)spoff) |
293 | | |
294 | | #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \ |
295 | 146k | printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n", \ |
296 | 146k | fmt, reg, 4*(unsigned long)pspoff) |
297 | | |
298 | | #define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \ |
299 | 32.5k | do \ |
300 | 32.5k | { \ |
301 | 32.5k | char grstr[20]; \ |
302 | 32.5k | \ |
303 | 32.5k | unw_print_grmask (grstr, grmask); \ |
304 | 32.5k | printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \ |
305 | 32.5k | } \ |
306 | 32.5k | while (0) |
307 | | |
308 | | #define UNW_DEC_ABI(fmt, abi, context, arg) \ |
309 | 806k | do \ |
310 | 806k | { \ |
311 | 806k | static const char * const abiname[] = \ |
312 | 806k | { \ |
313 | 806k | "@svr4", "@hpux", "@nt" \ |
314 | 806k | }; \ |
315 | 806k | char buf[20]; \ |
316 | 806k | const char *abistr = buf; \ |
317 | 806k | \ |
318 | 806k | if (abi < 3) \ |
319 | 806k | abistr = abiname[abi]; \ |
320 | 806k | else \ |
321 | 806k | sprintf (buf, "0x%x", abi); \ |
322 | 806k | printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n", \ |
323 | 806k | fmt, abistr, context); \ |
324 | 806k | } \ |
325 | 806k | while (0) |
326 | | |
327 | | #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \ |
328 | 6.41k | printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r) |
329 | | |
330 | | #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \ |
331 | 304 | printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t) |
332 | | |
333 | | #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \ |
334 | 341 | printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t) |
335 | | |
336 | | #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \ |
337 | 168 | printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n", \ |
338 | 168 | fmt, 4*(unsigned long)pspoff) |
339 | | |
340 | | #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \ |
341 | 1.44k | printf ("\t%s:priunat_sprel(spoff=0x%lx)\n", \ |
342 | 1.44k | fmt, 4*(unsigned long)spoff) |
343 | | |
344 | | #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \ |
345 | 17.6k | printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n", \ |
346 | 17.6k | fmt, (unsigned long) t, 16*(unsigned long)size) |
347 | | |
348 | | #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \ |
349 | 14.6k | printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t) |
350 | | |
351 | | #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \ |
352 | 15.0k | printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \ |
353 | 15.0k | fmt, 4*(unsigned long)pspoff) |
354 | | |
355 | | #define UNW_DEC_SPILL_MASK(fmt, dp, arg, end) \ |
356 | 14.2k | do \ |
357 | 14.2k | { \ |
358 | 14.2k | static const char *spill_type = "-frb"; \ |
359 | 14.2k | unsigned const char *imaskp = dp; \ |
360 | 14.2k | unsigned char mask = 0; \ |
361 | 14.2k | bfd_vma insn = 0; \ |
362 | 14.2k | \ |
363 | 14.2k | /* PR 18420. */ \ |
364 | 14.2k | if ((dp + (unw_rlen / 4)) > end) \ |
365 | 14.2k | { \ |
366 | 2.10k | printf (_("\nERROR: unwind length too long (0x%lx > 0x%lx)\n\n"), \ |
367 | 2.10k | (long) (unw_rlen / 4), (long)(end - dp)); \ |
368 | 2.10k | /* FIXME: Should we reset unw_rlen ? */ \ |
369 | 2.10k | break; \ |
370 | 2.10k | } \ |
371 | 14.2k | printf ("\t%s:spill_mask(imask=[", fmt); \ |
372 | 12.5M | for (insn = 0; insn < unw_rlen; ++insn) \ |
373 | 12.5M | { \ |
374 | 12.5M | if ((insn % 4) == 0) \ |
375 | 12.5M | mask = *imaskp++; \ |
376 | 12.5M | if (insn > 0 && (insn % 3) == 0) \ |
377 | 12.5M | putchar (','); \ |
378 | 12.5M | putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]); \ |
379 | 12.5M | } \ |
380 | 12.1k | printf ("])\n"); \ |
381 | 12.1k | dp = imaskp; \ |
382 | 12.1k | } \ |
383 | 14.2k | while (0) |
384 | | |
385 | | #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \ |
386 | 29.8k | do \ |
387 | 29.8k | { \ |
388 | 29.8k | char regname[20]; \ |
389 | 29.8k | \ |
390 | 29.8k | unw_print_abreg (regname, abreg); \ |
391 | 29.8k | printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \ |
392 | 29.8k | fmt, regname, (unsigned long) t, 4*(unsigned long)off); \ |
393 | 29.8k | } \ |
394 | 29.8k | while (0) |
395 | | |
396 | | #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \ |
397 | 20.9k | do \ |
398 | 20.9k | { \ |
399 | 20.9k | char regname[20]; \ |
400 | 20.9k | \ |
401 | 20.9k | unw_print_abreg (regname, abreg); \ |
402 | 20.9k | printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \ |
403 | 20.9k | fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff); \ |
404 | 20.9k | } \ |
405 | 20.9k | while (0) |
406 | | |
407 | | #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \ |
408 | 8.45k | do \ |
409 | 8.45k | { \ |
410 | 8.45k | char regname[20]; \ |
411 | 8.45k | \ |
412 | 8.45k | unw_print_abreg (regname, abreg); \ |
413 | 8.45k | printf ("\t%s:restore(t=%lu,reg=%s)\n", \ |
414 | 8.45k | fmt, (unsigned long) t, regname); \ |
415 | 8.45k | } \ |
416 | 8.45k | while (0) |
417 | | |
418 | | #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \ |
419 | 33.2k | do \ |
420 | 33.2k | { \ |
421 | 33.2k | char abregname[20], tregname[20]; \ |
422 | 33.2k | \ |
423 | 33.2k | unw_print_abreg (abregname, abreg); \ |
424 | 33.2k | unw_print_xyreg (tregname, x, ytreg); \ |
425 | 33.2k | printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n", \ |
426 | 33.2k | fmt, (unsigned long) t, abregname, tregname); \ |
427 | 33.2k | } \ |
428 | 33.2k | while (0) |
429 | | |
430 | | #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \ |
431 | 24.9k | do \ |
432 | 24.9k | { \ |
433 | 24.9k | char regname[20]; \ |
434 | 24.9k | \ |
435 | 24.9k | unw_print_abreg (regname, abreg); \ |
436 | 24.9k | printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \ |
437 | 24.9k | fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff); \ |
438 | 24.9k | } \ |
439 | 24.9k | while (0) |
440 | | |
441 | | #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \ |
442 | 36.2k | do \ |
443 | 36.2k | { \ |
444 | 36.2k | char regname[20]; \ |
445 | 36.2k | \ |
446 | 36.2k | unw_print_abreg (regname, abreg); \ |
447 | 36.2k | printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\ |
448 | 36.2k | fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\ |
449 | 36.2k | } \ |
450 | 36.2k | while (0) |
451 | | |
452 | | #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \ |
453 | 6.25k | do \ |
454 | 6.25k | { \ |
455 | 6.25k | char regname[20]; \ |
456 | 6.25k | \ |
457 | 6.25k | unw_print_abreg (regname, abreg); \ |
458 | 6.25k | printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n", \ |
459 | 6.25k | fmt, qp, (unsigned long) t, regname); \ |
460 | 6.25k | } \ |
461 | 6.25k | while (0) |
462 | | |
463 | | #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \ |
464 | 51.8k | do \ |
465 | 51.8k | { \ |
466 | 51.8k | char regname[20], tregname[20]; \ |
467 | 51.8k | \ |
468 | 51.8k | unw_print_abreg (regname, abreg); \ |
469 | 51.8k | unw_print_xyreg (tregname, x, ytreg); \ |
470 | 51.8k | printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n", \ |
471 | 51.8k | fmt, qp, (unsigned long) t, regname, tregname); \ |
472 | 51.8k | } \ |
473 | 51.8k | while (0) |
474 | | |
475 | | #define UNW_DEC_LABEL_STATE(fmt, label, arg) \ |
476 | 138k | printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label) |
477 | | |
478 | | #define UNW_DEC_COPY_STATE(fmt, label, arg) \ |
479 | 206k | printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label) |
480 | | |
481 | | #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \ |
482 | 209k | printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n", \ |
483 | 209k | fmt, (unsigned long) t, (unsigned long) ecount) |
484 | | |
485 | | /* |
486 | | * Generic IA-64 unwind info decoder. |
487 | | * |
488 | | * This file is used both by the Linux kernel and objdump. Please |
489 | | * keep the two copies of this file in sync (modulo differences in the |
490 | | * prototypes...). |
491 | | * |
492 | | * You need to customize the decoder by defining the following |
493 | | * macros/constants before including this file: |
494 | | * |
495 | | * Types: |
496 | | * unw_word Unsigned integer type with at least 64 bits |
497 | | * |
498 | | * Register names: |
499 | | * UNW_REG_BSP |
500 | | * UNW_REG_BSPSTORE |
501 | | * UNW_REG_FPSR |
502 | | * UNW_REG_LC |
503 | | * UNW_REG_PFS |
504 | | * UNW_REG_PR |
505 | | * UNW_REG_RNAT |
506 | | * UNW_REG_PSP |
507 | | * UNW_REG_RP |
508 | | * UNW_REG_UNAT |
509 | | * |
510 | | * Decoder action macros: |
511 | | * UNW_DEC_BAD_CODE(code) |
512 | | * UNW_DEC_ABI(fmt,abi,context,arg) |
513 | | * UNW_DEC_BR_GR(fmt,brmask,gr,arg) |
514 | | * UNW_DEC_BR_MEM(fmt,brmask,arg) |
515 | | * UNW_DEC_COPY_STATE(fmt,label,arg) |
516 | | * UNW_DEC_EPILOGUE(fmt,t,ecount,arg) |
517 | | * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg) |
518 | | * UNW_DEC_FR_MEM(fmt,frmask,arg) |
519 | | * UNW_DEC_GR_GR(fmt,grmask,gr,arg) |
520 | | * UNW_DEC_GR_MEM(fmt,grmask,arg) |
521 | | * UNW_DEC_LABEL_STATE(fmt,label,arg) |
522 | | * UNW_DEC_MEM_STACK_F(fmt,t,size,arg) |
523 | | * UNW_DEC_MEM_STACK_V(fmt,t,arg) |
524 | | * UNW_DEC_PRIUNAT_GR(fmt,r,arg) |
525 | | * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) |
526 | | * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) |
527 | | * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg) |
528 | | * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg) |
529 | | * UNW_DEC_PROLOGUE(fmt,body,rlen,arg) |
530 | | * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg) |
531 | | * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg) |
532 | | * UNW_DEC_REG_REG(fmt,src,dst,arg) |
533 | | * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg) |
534 | | * UNW_DEC_REG_WHEN(fmt,reg,t,arg) |
535 | | * UNW_DEC_RESTORE(fmt,t,abreg,arg) |
536 | | * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg) |
537 | | * UNW_DEC_SPILL_BASE(fmt,pspoff,arg) |
538 | | * UNW_DEC_SPILL_MASK(fmt,imaskp,arg) |
539 | | * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg) |
540 | | * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg) |
541 | | * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg) |
542 | | * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg) |
543 | | * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg) |
544 | | * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg) |
545 | | */ |
546 | | |
547 | | static unw_word |
548 | | unw_decode_uleb128 (const unsigned char **dpp, const unsigned char * end) |
549 | 3.85M | { |
550 | 3.85M | unsigned shift = 0; |
551 | 3.85M | int status = 1; |
552 | 3.85M | unw_word byte, result = 0; |
553 | 3.85M | const unsigned char *bp = *dpp; |
554 | | |
555 | 6.88M | while (bp < end) |
556 | 6.87M | { |
557 | 6.87M | byte = *bp++; |
558 | 6.87M | if (shift < sizeof (result) * 8) |
559 | 6.10M | { |
560 | 6.10M | result |= (byte & 0x7f) << shift; |
561 | 6.10M | if ((result >> shift) != (byte & 0x7f)) |
562 | | /* Overflow. */ |
563 | 47.0k | status |= 2; |
564 | 6.10M | shift += 7; |
565 | 6.10M | } |
566 | 774k | else if ((byte & 0x7f) != 0) |
567 | 748k | status |= 2; |
568 | | |
569 | 6.87M | if ((byte & 0x80) == 0) |
570 | 3.85M | { |
571 | 3.85M | status &= ~1; |
572 | 3.85M | break; |
573 | 3.85M | } |
574 | 6.87M | } |
575 | | |
576 | 3.85M | *dpp = bp; |
577 | 3.85M | if (status != 0) |
578 | 51.9k | printf (_("Bad uleb128\n")); |
579 | | |
580 | 3.85M | return result; |
581 | 3.85M | } |
582 | | |
583 | | static const unsigned char * |
584 | | unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, |
585 | | void *arg ATTRIBUTE_UNUSED, const unsigned char * end) |
586 | 51.0k | { |
587 | 51.0k | unsigned char byte1, abreg; |
588 | 51.0k | unw_word t, off; |
589 | | |
590 | 51.0k | if ((end - dp) < 3) |
591 | 246 | { |
592 | 246 | printf (_("\t<corrupt X1>\n")); |
593 | 246 | return end; |
594 | 246 | } |
595 | | |
596 | 50.8k | byte1 = *dp++; |
597 | 50.8k | t = unw_decode_uleb128 (&dp, end); |
598 | 50.8k | off = unw_decode_uleb128 (&dp, end); |
599 | 50.8k | abreg = (byte1 & 0x7f); |
600 | 50.8k | if (byte1 & 0x80) |
601 | 29.8k | UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg); |
602 | 20.9k | else |
603 | 20.9k | UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg); |
604 | 50.8k | return dp; |
605 | 51.0k | } |
606 | | |
607 | | static const unsigned char * |
608 | | unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, |
609 | | void *arg ATTRIBUTE_UNUSED, const unsigned char * end) |
610 | 41.8k | { |
611 | 41.8k | unsigned char byte1, byte2, abreg, x, ytreg; |
612 | 41.8k | unw_word t; |
613 | | |
614 | 41.8k | if ((end - dp) < 3) |
615 | 98 | { |
616 | 98 | printf (_("\t<corrupt X2>\n")); |
617 | 98 | return end; |
618 | 98 | } |
619 | | |
620 | 41.7k | byte1 = *dp++; |
621 | 41.7k | byte2 = *dp++; |
622 | 41.7k | t = unw_decode_uleb128 (&dp, end); |
623 | 41.7k | abreg = (byte1 & 0x7f); |
624 | 41.7k | ytreg = byte2; |
625 | 41.7k | x = (byte1 >> 7) & 1; |
626 | 41.7k | if ((byte1 & 0x80) == 0 && ytreg == 0) |
627 | 8.45k | UNW_DEC_RESTORE ("X2", t, abreg, arg); |
628 | 33.2k | else |
629 | 33.2k | UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg); |
630 | 41.7k | return dp; |
631 | 41.8k | } |
632 | | |
633 | | static const unsigned char * |
634 | | unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, |
635 | | void *arg ATTRIBUTE_UNUSED, const unsigned char * end) |
636 | 61.3k | { |
637 | 61.3k | unsigned char byte1, byte2, abreg, qp; |
638 | 61.3k | unw_word t, off; |
639 | | |
640 | 61.3k | if ((end - dp) < 4) |
641 | 277 | { |
642 | 277 | printf (_("\t<corrupt X3>\n")); |
643 | 277 | return end; |
644 | 277 | } |
645 | | |
646 | 61.1k | byte1 = *dp++; |
647 | 61.1k | byte2 = *dp++; |
648 | 61.1k | t = unw_decode_uleb128 (&dp, end); |
649 | 61.1k | off = unw_decode_uleb128 (&dp, end); |
650 | | |
651 | 61.1k | qp = (byte1 & 0x3f); |
652 | 61.1k | abreg = (byte2 & 0x7f); |
653 | | |
654 | 61.1k | if (byte1 & 0x80) |
655 | 24.9k | UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg); |
656 | 36.2k | else |
657 | 36.2k | UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg); |
658 | 61.1k | return dp; |
659 | 61.3k | } |
660 | | |
661 | | static const unsigned char * |
662 | | unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, |
663 | | void *arg ATTRIBUTE_UNUSED, const unsigned char * end) |
664 | 58.4k | { |
665 | 58.4k | unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg; |
666 | 58.4k | unw_word t; |
667 | | |
668 | 58.4k | if ((end - dp) < 4) |
669 | 376 | { |
670 | 376 | printf (_("\t<corrupt X4>\n")); |
671 | 376 | return end; |
672 | 376 | } |
673 | | |
674 | 58.0k | byte1 = *dp++; |
675 | 58.0k | byte2 = *dp++; |
676 | 58.0k | byte3 = *dp++; |
677 | 58.0k | t = unw_decode_uleb128 (&dp, end); |
678 | | |
679 | 58.0k | qp = (byte1 & 0x3f); |
680 | 58.0k | abreg = (byte2 & 0x7f); |
681 | 58.0k | x = (byte2 >> 7) & 1; |
682 | 58.0k | ytreg = byte3; |
683 | | |
684 | 58.0k | if ((byte2 & 0x80) == 0 && byte3 == 0) |
685 | 6.25k | UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg); |
686 | 51.8k | else |
687 | 51.8k | UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg); |
688 | 58.0k | return dp; |
689 | 58.4k | } |
690 | | |
691 | | static const unsigned char * |
692 | | unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg, |
693 | | const unsigned char * end ATTRIBUTE_UNUSED) |
694 | 25.1M | { |
695 | 25.1M | int body = (code & 0x20) != 0; |
696 | 25.1M | unw_word rlen; |
697 | | |
698 | 25.1M | rlen = (code & 0x1f); |
699 | 25.1M | UNW_DEC_PROLOGUE ("R1", body, rlen, arg); |
700 | 25.1M | return dp; |
701 | 25.1M | } |
702 | | |
703 | | static const unsigned char * |
704 | | unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg, |
705 | | const unsigned char * end) |
706 | 1.22M | { |
707 | 1.22M | unsigned char byte1, mask, grsave; |
708 | 1.22M | unw_word rlen; |
709 | | |
710 | 1.22M | if ((end - dp) < 2) |
711 | 883 | { |
712 | 883 | printf (_("\t<corrupt R2>\n")); |
713 | 883 | return end; |
714 | 883 | } |
715 | | |
716 | 1.22M | byte1 = *dp++; |
717 | | |
718 | 1.22M | mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); |
719 | 1.22M | grsave = (byte1 & 0x7f); |
720 | 1.22M | rlen = unw_decode_uleb128 (& dp, end); |
721 | 1.22M | UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg); |
722 | 1.22M | return dp; |
723 | 1.22M | } |
724 | | |
725 | | static const unsigned char * |
726 | | unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg, |
727 | | const unsigned char * end) |
728 | 1.57M | { |
729 | 1.57M | unw_word rlen; |
730 | | |
731 | 1.57M | rlen = unw_decode_uleb128 (& dp, end); |
732 | 1.57M | UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg); |
733 | 1.57M | return dp; |
734 | 1.57M | } |
735 | | |
736 | | static const unsigned char * |
737 | | unw_decode_p1 (const unsigned char *dp, unsigned int code, |
738 | | void *arg ATTRIBUTE_UNUSED, |
739 | | const unsigned char * end ATTRIBUTE_UNUSED) |
740 | 727k | { |
741 | 727k | unsigned char brmask = (code & 0x1f); |
742 | | |
743 | 727k | UNW_DEC_BR_MEM ("P1", brmask, arg); |
744 | 727k | return dp; |
745 | 727k | } |
746 | | |
747 | | static const unsigned char * |
748 | | unw_decode_p2_p5 (const unsigned char *dp, unsigned int code, |
749 | | void *arg ATTRIBUTE_UNUSED, |
750 | | const unsigned char * end) |
751 | 663k | { |
752 | 663k | if ((code & 0x10) == 0) |
753 | 256k | { |
754 | 256k | unsigned char byte1; |
755 | | |
756 | 256k | if ((end - dp) < 1) |
757 | 219 | { |
758 | 219 | printf (_("\t<corrupt P2>\n")); |
759 | 219 | return end; |
760 | 219 | } |
761 | | |
762 | 256k | byte1 = *dp++; |
763 | | |
764 | 256k | UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1), |
765 | 256k | (byte1 & 0x7f), arg); |
766 | 256k | } |
767 | 407k | else if ((code & 0x08) == 0) |
768 | 237k | { |
769 | 237k | unsigned char byte1, r, dst; |
770 | | |
771 | 237k | if ((end - dp) < 1) |
772 | 149 | { |
773 | 149 | printf (_("\t<corrupt P3>\n")); |
774 | 149 | return end; |
775 | 149 | } |
776 | | |
777 | 237k | byte1 = *dp++; |
778 | | |
779 | 237k | r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); |
780 | 237k | dst = (byte1 & 0x7f); |
781 | 237k | switch (r) |
782 | 237k | { |
783 | 11.1k | case 0: |
784 | 11.1k | UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg); |
785 | 11.1k | break; |
786 | 4.58k | case 1: |
787 | 4.58k | UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg); |
788 | 4.58k | break; |
789 | 4.16k | case 2: |
790 | 4.16k | UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg); |
791 | 4.16k | break; |
792 | 12.2k | case 3: |
793 | 12.2k | UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg); |
794 | 12.2k | break; |
795 | 9.44k | case 4: |
796 | 9.44k | UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg); |
797 | 9.44k | break; |
798 | 43.4k | case 5: |
799 | 43.4k | UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg); |
800 | 43.4k | break; |
801 | 16.2k | case 6: |
802 | 16.2k | UNW_DEC_RP_BR ("P3", dst, arg); |
803 | 16.2k | break; |
804 | 71.9k | case 7: |
805 | 71.9k | UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg); |
806 | 71.9k | break; |
807 | 6.40k | case 8: |
808 | 6.40k | UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg); |
809 | 6.40k | break; |
810 | 10.8k | case 9: |
811 | 10.8k | UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg); |
812 | 10.8k | break; |
813 | 12.1k | case 10: |
814 | 12.1k | UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg); |
815 | 12.1k | break; |
816 | 6.41k | case 11: |
817 | 6.41k | UNW_DEC_PRIUNAT_GR ("P3", dst, arg); |
818 | 6.41k | break; |
819 | 28.0k | default: |
820 | 28.0k | UNW_DEC_BAD_CODE (r); |
821 | 28.0k | break; |
822 | 237k | } |
823 | 237k | } |
824 | 170k | else if ((code & 0x7) == 0) |
825 | 14.2k | UNW_DEC_SPILL_MASK ("P4", dp, arg, end); |
826 | 155k | else if ((code & 0x7) == 1) |
827 | 46.2k | { |
828 | 46.2k | unw_word grmask, frmask, byte1, byte2, byte3; |
829 | | |
830 | 46.2k | if ((end - dp) < 3) |
831 | 291 | { |
832 | 291 | printf (_("\t<corrupt P5>\n")); |
833 | 291 | return end; |
834 | 291 | } |
835 | 45.9k | byte1 = *dp++; |
836 | 45.9k | byte2 = *dp++; |
837 | 45.9k | byte3 = *dp++; |
838 | 45.9k | grmask = ((byte1 >> 4) & 0xf); |
839 | 45.9k | frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3; |
840 | 45.9k | UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg); |
841 | 45.9k | } |
842 | 109k | else |
843 | 109k | UNW_DEC_BAD_CODE (code); |
844 | | |
845 | 663k | return dp; |
846 | 663k | } |
847 | | |
848 | | static const unsigned char * |
849 | | unw_decode_p6 (const unsigned char *dp, unsigned int code, |
850 | | void *arg ATTRIBUTE_UNUSED, |
851 | | const unsigned char * end ATTRIBUTE_UNUSED) |
852 | 1.41M | { |
853 | 1.41M | int gregs = (code & 0x10) != 0; |
854 | 1.41M | unsigned char mask = (code & 0x0f); |
855 | | |
856 | 1.41M | if (gregs) |
857 | 1.17M | UNW_DEC_GR_MEM ("P6", mask, arg); |
858 | 237k | else |
859 | 237k | UNW_DEC_FR_MEM ("P6", mask, arg); |
860 | 1.41M | return dp; |
861 | 1.41M | } |
862 | | |
863 | | static const unsigned char * |
864 | | unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg, |
865 | | const unsigned char * end) |
866 | 1.86M | { |
867 | 1.86M | unsigned char r, byte1, byte2; |
868 | 1.86M | unw_word t, size; |
869 | | |
870 | 1.86M | if ((code & 0x10) == 0) |
871 | 346k | { |
872 | 346k | r = (code & 0xf); |
873 | 346k | t = unw_decode_uleb128 (&dp, end); |
874 | 346k | switch (r) |
875 | 346k | { |
876 | 17.6k | case 0: |
877 | 17.6k | size = unw_decode_uleb128 (&dp, end); |
878 | 17.6k | UNW_DEC_MEM_STACK_F ("P7", t, size, arg); |
879 | 17.6k | break; |
880 | | |
881 | 14.6k | case 1: |
882 | 14.6k | UNW_DEC_MEM_STACK_V ("P7", t, arg); |
883 | 14.6k | break; |
884 | 15.0k | case 2: |
885 | 15.0k | UNW_DEC_SPILL_BASE ("P7", t, arg); |
886 | 15.0k | break; |
887 | 25.5k | case 3: |
888 | 25.5k | UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg); |
889 | 25.5k | break; |
890 | 13.9k | case 4: |
891 | 13.9k | UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg); |
892 | 13.9k | break; |
893 | 7.84k | case 5: |
894 | 7.84k | UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg); |
895 | 7.84k | break; |
896 | 25.2k | case 6: |
897 | 25.2k | UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg); |
898 | 25.2k | break; |
899 | 51.9k | case 7: |
900 | 51.9k | UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg); |
901 | 51.9k | break; |
902 | 25.5k | case 8: |
903 | 25.5k | UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg); |
904 | 25.5k | break; |
905 | 15.7k | case 9: |
906 | 15.7k | UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg); |
907 | 15.7k | break; |
908 | 13.4k | case 10: |
909 | 13.4k | UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg); |
910 | 13.4k | break; |
911 | 30.6k | case 11: |
912 | 30.6k | UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg); |
913 | 30.6k | break; |
914 | 18.3k | case 12: |
915 | 18.3k | UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg); |
916 | 18.3k | break; |
917 | 21.8k | case 13: |
918 | 21.8k | UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg); |
919 | 21.8k | break; |
920 | 31.7k | case 14: |
921 | 31.7k | UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg); |
922 | 31.7k | break; |
923 | 17.2k | case 15: |
924 | 17.2k | UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg); |
925 | 17.2k | break; |
926 | 0 | default: |
927 | 0 | UNW_DEC_BAD_CODE (r); |
928 | 0 | break; |
929 | 346k | } |
930 | 346k | } |
931 | 1.51M | else |
932 | 1.51M | { |
933 | 1.51M | switch (code & 0xf) |
934 | 1.51M | { |
935 | 56.9k | case 0x0: /* p8 */ |
936 | 56.9k | { |
937 | 56.9k | if ((end - dp) < 2) |
938 | 224 | { |
939 | 224 | printf (_("\t<corrupt P8>\n")); |
940 | 224 | return end; |
941 | 224 | } |
942 | | |
943 | 56.7k | r = *dp++; |
944 | 56.7k | t = unw_decode_uleb128 (&dp, end); |
945 | 56.7k | switch (r) |
946 | 56.7k | { |
947 | 1.75k | case 1: |
948 | 1.75k | UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg); |
949 | 1.75k | break; |
950 | 138 | case 2: |
951 | 138 | UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg); |
952 | 138 | break; |
953 | 1.83k | case 3: |
954 | 1.83k | UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg); |
955 | 1.83k | break; |
956 | 1.28k | case 4: |
957 | 1.28k | UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg); |
958 | 1.28k | break; |
959 | 602 | case 5: |
960 | 602 | UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg); |
961 | 602 | break; |
962 | 3.46k | case 6: |
963 | 3.46k | UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg); |
964 | 3.46k | break; |
965 | 3.03k | case 7: |
966 | 3.03k | UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg); |
967 | 3.03k | break; |
968 | 329 | case 8: |
969 | 329 | UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg); |
970 | 329 | break; |
971 | 129 | case 9: |
972 | 129 | UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg); |
973 | 129 | break; |
974 | 448 | case 10: |
975 | 448 | UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg); |
976 | 448 | break; |
977 | 558 | case 11: |
978 | 558 | UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg); |
979 | 558 | break; |
980 | 151 | case 12: |
981 | 151 | UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg); |
982 | 151 | break; |
983 | 473 | case 13: |
984 | 473 | UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg); |
985 | 473 | break; |
986 | 358 | case 14: |
987 | 358 | UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg); |
988 | 358 | break; |
989 | 3.92k | case 15: |
990 | 3.92k | UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg); |
991 | 3.92k | break; |
992 | 304 | case 16: |
993 | 304 | UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg); |
994 | 304 | break; |
995 | 168 | case 17: |
996 | 168 | UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg); |
997 | 168 | break; |
998 | 1.44k | case 18: |
999 | 1.44k | UNW_DEC_PRIUNAT_SPREL ("P8", t, arg); |
1000 | 1.44k | break; |
1001 | 341 | case 19: |
1002 | 341 | UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg); |
1003 | 341 | break; |
1004 | 36.0k | default: |
1005 | 36.0k | UNW_DEC_BAD_CODE (r); |
1006 | 36.0k | break; |
1007 | 56.7k | } |
1008 | 56.7k | } |
1009 | 56.7k | break; |
1010 | | |
1011 | 56.7k | case 0x1: |
1012 | 32.8k | if ((end - dp) < 2) |
1013 | 292 | { |
1014 | 292 | printf (_("\t<corrupt P9>\n")); |
1015 | 292 | return end; |
1016 | 292 | } |
1017 | | |
1018 | 32.5k | byte1 = *dp++; |
1019 | 32.5k | byte2 = *dp++; |
1020 | 32.5k | UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg); |
1021 | 32.5k | break; |
1022 | | |
1023 | 807k | case 0xf: /* p10 */ |
1024 | 807k | if ((end - dp) < 2) |
1025 | 856 | { |
1026 | 856 | printf (_("\t<corrupt P10>\n")); |
1027 | 856 | return end; |
1028 | 856 | } |
1029 | | |
1030 | 806k | byte1 = *dp++; |
1031 | 806k | byte2 = *dp++; |
1032 | 806k | UNW_DEC_ABI ("P10", byte1, byte2, arg); |
1033 | 806k | break; |
1034 | | |
1035 | 39.9k | case 0x9: |
1036 | 39.9k | return unw_decode_x1 (dp, code, arg, end); |
1037 | | |
1038 | 27.4k | case 0xa: |
1039 | 27.4k | return unw_decode_x2 (dp, code, arg, end); |
1040 | | |
1041 | 47.6k | case 0xb: |
1042 | 47.6k | return unw_decode_x3 (dp, code, arg, end); |
1043 | | |
1044 | 49.9k | case 0xc: |
1045 | 49.9k | return unw_decode_x4 (dp, code, arg, end); |
1046 | | |
1047 | 455k | default: |
1048 | 455k | UNW_DEC_BAD_CODE (code); |
1049 | 455k | break; |
1050 | 1.51M | } |
1051 | 1.51M | } |
1052 | 1.69M | return dp; |
1053 | 1.86M | } |
1054 | | |
1055 | | static const unsigned char * |
1056 | | unw_decode_b1 (const unsigned char *dp, unsigned int code, |
1057 | | void *arg ATTRIBUTE_UNUSED, |
1058 | | const unsigned char * end ATTRIBUTE_UNUSED) |
1059 | 329k | { |
1060 | 329k | unw_word label = (code & 0x1f); |
1061 | | |
1062 | 329k | if ((code & 0x20) != 0) |
1063 | 199k | UNW_DEC_COPY_STATE ("B1", label, arg); |
1064 | 130k | else |
1065 | 130k | UNW_DEC_LABEL_STATE ("B1", label, arg); |
1066 | 329k | return dp; |
1067 | 329k | } |
1068 | | |
1069 | | static const unsigned char * |
1070 | | unw_decode_b2 (const unsigned char *dp, unsigned int code, |
1071 | | void *arg ATTRIBUTE_UNUSED, |
1072 | | const unsigned char * end) |
1073 | 119k | { |
1074 | 119k | unw_word t; |
1075 | | |
1076 | 119k | t = unw_decode_uleb128 (& dp, end); |
1077 | 119k | UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg); |
1078 | 119k | return dp; |
1079 | 119k | } |
1080 | | |
1081 | | static const unsigned char * |
1082 | | unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg, |
1083 | | const unsigned char * end) |
1084 | 381k | { |
1085 | 381k | unw_word t, ecount, label; |
1086 | | |
1087 | 381k | if ((code & 0x10) == 0) |
1088 | 89.8k | { |
1089 | 89.8k | t = unw_decode_uleb128 (&dp, end); |
1090 | 89.8k | ecount = unw_decode_uleb128 (&dp, end); |
1091 | 89.8k | UNW_DEC_EPILOGUE ("B3", t, ecount, arg); |
1092 | 89.8k | } |
1093 | 292k | else if ((code & 0x07) == 0) |
1094 | 15.4k | { |
1095 | 15.4k | label = unw_decode_uleb128 (&dp, end); |
1096 | 15.4k | if ((code & 0x08) != 0) |
1097 | 7.16k | UNW_DEC_COPY_STATE ("B4", label, arg); |
1098 | 8.23k | else |
1099 | 8.23k | UNW_DEC_LABEL_STATE ("B4", label, arg); |
1100 | 15.4k | } |
1101 | 276k | else |
1102 | 276k | switch (code & 0x7) |
1103 | 276k | { |
1104 | 11.1k | case 1: |
1105 | 11.1k | return unw_decode_x1 (dp, code, arg, end); |
1106 | 14.3k | case 2: |
1107 | 14.3k | return unw_decode_x2 (dp, code, arg, end); |
1108 | 13.7k | case 3: |
1109 | 13.7k | return unw_decode_x3 (dp, code, arg, end); |
1110 | 8.52k | case 4: |
1111 | 8.52k | return unw_decode_x4 (dp, code, arg, end); |
1112 | 228k | default: |
1113 | 228k | UNW_DEC_BAD_CODE (code); |
1114 | 228k | break; |
1115 | 276k | } |
1116 | 334k | return dp; |
1117 | 381k | } |
1118 | | |
1119 | | typedef const unsigned char *(*unw_decoder) |
1120 | | (const unsigned char *, unsigned int, void *, const unsigned char *); |
1121 | | |
1122 | | static const unw_decoder unw_decode_table[2][8] = |
1123 | | { |
1124 | | /* prologue table: */ |
1125 | | { |
1126 | | unw_decode_r1, /* 0 */ |
1127 | | unw_decode_r1, |
1128 | | unw_decode_r2, |
1129 | | unw_decode_r3, |
1130 | | unw_decode_p1, /* 4 */ |
1131 | | unw_decode_p2_p5, |
1132 | | unw_decode_p6, |
1133 | | unw_decode_p7_p10 |
1134 | | }, |
1135 | | { |
1136 | | unw_decode_r1, /* 0 */ |
1137 | | unw_decode_r1, |
1138 | | unw_decode_r2, |
1139 | | unw_decode_r3, |
1140 | | unw_decode_b1, /* 4 */ |
1141 | | unw_decode_b1, |
1142 | | unw_decode_b2, |
1143 | | unw_decode_b3_x4 |
1144 | | } |
1145 | | }; |
1146 | | |
1147 | | /* Decode one descriptor and return address of next descriptor. */ |
1148 | | const unsigned char * |
1149 | | unw_decode (const unsigned char *dp, int inside_body, |
1150 | | void *ptr_inside_body, const unsigned char * end) |
1151 | 33.4M | { |
1152 | 33.4M | unw_decoder decoder; |
1153 | 33.4M | unsigned char code; |
1154 | | |
1155 | 33.4M | if ((end - dp) < 1) |
1156 | 0 | { |
1157 | 0 | printf (_("\t<corrupt IA64 descriptor>\n")); |
1158 | 0 | return end; |
1159 | 0 | } |
1160 | | |
1161 | 33.4M | code = *dp++; |
1162 | 33.4M | decoder = unw_decode_table[inside_body][code >> 5]; |
1163 | 33.4M | return (*decoder) (dp, code, ptr_inside_body, end); |
1164 | 33.4M | } |