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