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