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