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