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