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