]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/unwind-ia64.c
Fix potential illegal memory access by readelf when parsing corrupt IA64 unwind infor...
[thirdparty/binutils-gdb.git] / binutils / unwind-ia64.c
1 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2 Copyright (C) 2000-2019 Free Software Foundation, Inc.
3
4 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5
6 This file is part of GNU Binutils.
7
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.
12
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.
17
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. */
22
23 #include "config.h"
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.
31 Only do this if we believe that the compiler can support a 64 bit
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
37 static bfd_vma unw_rlen = 0;
38
39 static void unw_print_brmask (char *, unsigned int);
40 static void unw_print_grmask (char *, unsigned int);
41 static void unw_print_frmask (char *, unsigned int);
42 static void unw_print_abreg (char *, unsigned int);
43 static void unw_print_xyreg (char *, unsigned int, unsigned int);
44
45 static void
46 unw_print_brmask (char *cp, unsigned int mask)
47 {
48 int sep = 0;
49 int i;
50
51 for (i = 0; mask && (i < 5); ++i)
52 {
53 if (mask & 1)
54 {
55 if (sep)
56 *cp++ = ',';
57 *cp++ = 'b';
58 *cp++ = i + 1 + '0';
59 sep = 1;
60 }
61 mask >>= 1;
62 }
63 *cp = '\0';
64 }
65
66 static void
67 unw_print_grmask (char *cp, unsigned int mask)
68 {
69 int sep = 0;
70 int i;
71
72 for (i = 0; i < 4; ++i)
73 {
74 if (mask & 1)
75 {
76 if (sep)
77 *cp++ = ',';
78 *cp++ = 'r';
79 *cp++ = i + 4 + '0';
80 sep = 1;
81 }
82 mask >>= 1;
83 }
84 *cp = '\0';
85 }
86
87 static void
88 unw_print_frmask (char *cp, unsigned int mask)
89 {
90 int sep = 0;
91 int i;
92
93 for (i = 0; i < 20; ++i)
94 {
95 if (mask & 1)
96 {
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;
108 }
109 mask >>= 1;
110 }
111 *cp = '\0';
112 }
113
114 static void
115 unw_print_abreg (char *cp, unsigned int abreg)
116 {
117 static const char * const special_reg[16] =
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
144 static void
145 unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
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
174 typedef bfd_vma unw_word;
175
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; \
184 printf (" %s:%s(rlen=%lu)\n", \
185 fmt, body ? "body" : "prologue", (unsigned long) rlen); \
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); \
222 printf (" %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \
223 fmt, maskstr, regname, (unsigned long) rlen); \
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); \
233 printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \
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); \
243 printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \
244 } \
245 while (0)
246
247 #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \
248 do \
249 { \
250 char frstr[200], grstr[20]; \
251 \
252 unw_print_grmask (grstr, grmask); \
253 unw_print_frmask (frstr, frmask); \
254 printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr); \
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); \
264 printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \
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); \
274 printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \
275 } \
276 while (0)
277
278 #define UNW_DEC_REG_GR(fmt, src, dst, arg) \
279 printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
280
281 #define UNW_DEC_RP_BR(fmt, dst, arg) \
282 printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
283
284 #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \
285 printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
286
287 #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \
288 printf ("\t%s:%s_sprel(spoff=0x%lx)\n", \
289 fmt, reg, 4*(unsigned long)spoff)
290
291 #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \
292 printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n", \
293 fmt, reg, 4*(unsigned long)pspoff)
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); \
301 printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \
302 } \
303 while (0)
304
305 #define UNW_DEC_ABI(fmt, abi, context, arg) \
306 do \
307 { \
308 static const char * const abiname[] = \
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); \
319 printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n", \
320 fmt, abistr, context); \
321 } \
322 while (0)
323
324 #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \
325 printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
326
327 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \
328 printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
329
330 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \
331 printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
332
333 #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \
334 printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n", \
335 fmt, 4*(unsigned long)pspoff)
336
337 #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \
338 printf ("\t%s:priunat_sprel(spoff=0x%lx)\n", \
339 fmt, 4*(unsigned long)spoff)
340
341 #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \
342 printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n", \
343 fmt, (unsigned long) t, 16*(unsigned long)size)
344
345 #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \
346 printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
347
348 #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \
349 printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \
350 fmt, 4*(unsigned long)pspoff)
351
352 #define UNW_DEC_SPILL_MASK(fmt, dp, arg, end) \
353 do \
354 { \
355 static const char *spill_type = "-frb"; \
356 unsigned const char *imaskp = dp; \
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 } \
368 printf ("\t%s:spill_mask(imask=[", fmt); \
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[20]; \
386 \
387 unw_print_abreg (regname, abreg); \
388 printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \
389 fmt, regname, (unsigned long) t, 4*(unsigned long)off); \
390 } \
391 while (0)
392
393 #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \
394 do \
395 { \
396 char regname[20]; \
397 \
398 unw_print_abreg (regname, abreg); \
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); \
401 } \
402 while (0)
403
404 #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \
405 do \
406 { \
407 char regname[20]; \
408 \
409 unw_print_abreg (regname, abreg); \
410 printf ("\t%s:restore(t=%lu,reg=%s)\n", \
411 fmt, (unsigned long) t, regname); \
412 } \
413 while (0)
414
415 #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \
416 do \
417 { \
418 char abregname[20], tregname[20]; \
419 \
420 unw_print_abreg (abregname, abreg); \
421 unw_print_xyreg (tregname, x, ytreg); \
422 printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n", \
423 fmt, (unsigned long) t, abregname, tregname); \
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); \
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); \
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); \
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);\
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); \
455 printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n", \
456 fmt, qp, (unsigned long) t, regname); \
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); \
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); \
469 } \
470 while (0)
471
472 #define UNW_DEC_LABEL_STATE(fmt, label, arg) \
473 printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
474
475 #define UNW_DEC_COPY_STATE(fmt, label, arg) \
476 printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
477
478 #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \
479 printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n", \
480 fmt, (unsigned long) t, (unsigned long) ecount)
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:
493 * unw_word Unsigned integer type with at least 64 bits
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
544 static unw_word
545 unw_decode_uleb128 (const unsigned char **dpp, const unsigned char * end)
546 {
547 unsigned shift = 0;
548 unw_word byte, result = 0;
549 const unsigned char *bp = *dpp;
550
551 while (bp < end)
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
567 static const unsigned char *
568 unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
569 void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
570 {
571 unsigned char byte1, abreg;
572 unw_word t, off;
573
574 byte1 = *dp++;
575 t = unw_decode_uleb128 (&dp, end);
576 off = unw_decode_uleb128 (&dp, end);
577 abreg = (byte1 & 0x7f);
578 if (byte1 & 0x80)
579 UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
580 else
581 UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
582 return dp;
583 }
584
585 static const unsigned char *
586 unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
587 void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
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, end);
595 abreg = (byte1 & 0x7f);
596 ytreg = byte2;
597 x = (byte1 >> 7) & 1;
598 if ((byte1 & 0x80) == 0 && ytreg == 0)
599 UNW_DEC_RESTORE ("X2", t, abreg, arg);
600 else
601 UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg);
602 return dp;
603 }
604
605 static const unsigned char *
606 unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
607 void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
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, end);
615 off = unw_decode_uleb128 (&dp, end);
616
617 qp = (byte1 & 0x3f);
618 abreg = (byte2 & 0x7f);
619
620 if (byte1 & 0x80)
621 UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
622 else
623 UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
624 return dp;
625 }
626
627 static const unsigned char *
628 unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
629 void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
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, end);
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)
645 UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
646 else
647 UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
648 return dp;
649 }
650
651 static const unsigned char *
652 unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg,
653 const unsigned char * end ATTRIBUTE_UNUSED)
654 {
655 int body = (code & 0x20) != 0;
656 unw_word rlen;
657
658 rlen = (code & 0x1f);
659 UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
660 return dp;
661 }
662
663 static const unsigned char *
664 unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg,
665 const unsigned char * end)
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, end);
675 UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
676 return dp;
677 }
678
679 static const unsigned char *
680 unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg,
681 const unsigned char * end)
682 {
683 unw_word rlen;
684
685 rlen = unw_decode_uleb128 (& dp, end);
686 UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
687 return dp;
688 }
689
690 static const unsigned char *
691 unw_decode_p1 (const unsigned char *dp, unsigned int code,
692 void *arg ATTRIBUTE_UNUSED,
693 const unsigned char * end ATTRIBUTE_UNUSED)
694 {
695 unsigned char brmask = (code & 0x1f);
696
697 UNW_DEC_BR_MEM ("P1", brmask, arg);
698 return dp;
699 }
700
701 static const unsigned char *
702 unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
703 void *arg ATTRIBUTE_UNUSED,
704 const unsigned char * end)
705 {
706 if ((code & 0x10) == 0)
707 {
708 unsigned char byte1 = *dp++;
709
710 UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
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:
722 UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
723 break;
724 case 1:
725 UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
726 break;
727 case 2:
728 UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
729 break;
730 case 3:
731 UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
732 break;
733 case 4:
734 UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
735 break;
736 case 5:
737 UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
738 break;
739 case 6:
740 UNW_DEC_RP_BR ("P3", dst, arg);
741 break;
742 case 7:
743 UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
744 break;
745 case 8:
746 UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
747 break;
748 case 9:
749 UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
750 break;
751 case 10:
752 UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
753 break;
754 case 11:
755 UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
756 break;
757 default:
758 UNW_DEC_BAD_CODE (r);
759 break;
760 }
761 }
762 else if ((code & 0x7) == 0)
763 UNW_DEC_SPILL_MASK ("P4", dp, arg, end);
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;
773 UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
774 }
775 else
776 UNW_DEC_BAD_CODE (code);
777
778 return dp;
779 }
780
781 static const unsigned char *
782 unw_decode_p6 (const unsigned char *dp, unsigned int code,
783 void *arg ATTRIBUTE_UNUSED,
784 const unsigned char * end ATTRIBUTE_UNUSED)
785 {
786 int gregs = (code & 0x10) != 0;
787 unsigned char mask = (code & 0x0f);
788
789 if (gregs)
790 UNW_DEC_GR_MEM ("P6", mask, arg);
791 else
792 UNW_DEC_FR_MEM ("P6", mask, arg);
793 return dp;
794 }
795
796 static const unsigned char *
797 unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg,
798 const unsigned char * end)
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, end);
807 switch (r)
808 {
809 case 0:
810 size = unw_decode_uleb128 (&dp, end);
811 UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
812 break;
813
814 case 1:
815 UNW_DEC_MEM_STACK_V ("P7", t, arg);
816 break;
817 case 2:
818 UNW_DEC_SPILL_BASE ("P7", t, arg);
819 break;
820 case 3:
821 UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
822 break;
823 case 4:
824 UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
825 break;
826 case 5:
827 UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
828 break;
829 case 6:
830 UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
831 break;
832 case 7:
833 UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
834 break;
835 case 8:
836 UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
837 break;
838 case 9:
839 UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
840 break;
841 case 10:
842 UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
843 break;
844 case 11:
845 UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
846 break;
847 case 12:
848 UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
849 break;
850 case 13:
851 UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
852 break;
853 case 14:
854 UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
855 break;
856 case 15:
857 UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
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, end);
872 switch (r)
873 {
874 case 1:
875 UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
876 break;
877 case 2:
878 UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
879 break;
880 case 3:
881 UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
882 break;
883 case 4:
884 UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
885 break;
886 case 5:
887 UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
888 break;
889 case 6:
890 UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
891 break;
892 case 7:
893 UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
894 break;
895 case 8:
896 UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
897 break;
898 case 9:
899 UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
900 break;
901 case 10:
902 UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
903 break;
904 case 11:
905 UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
906 break;
907 case 12:
908 UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
909 break;
910 case 13:
911 UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
912 break;
913 case 14:
914 UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
915 break;
916 case 15:
917 UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
918 break;
919 case 16:
920 UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
921 break;
922 case 17:
923 UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
924 break;
925 case 18:
926 UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
927 break;
928 case 19:
929 UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
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++;
941 UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
942 break;
943
944 case 0xf: /* p10 */
945 byte1 = *dp++;
946 byte2 = *dp++;
947 UNW_DEC_ABI ("P10", byte1, byte2, arg);
948 break;
949
950 case 0x9:
951 return unw_decode_x1 (dp, code, arg, end);
952
953 case 0xa:
954 return unw_decode_x2 (dp, code, arg, end);
955
956 case 0xb:
957 return unw_decode_x3 (dp, code, arg, end);
958
959 case 0xc:
960 return unw_decode_x4 (dp, code, arg, end);
961
962 default:
963 UNW_DEC_BAD_CODE (code);
964 break;
965 }
966 }
967 return dp;
968 }
969
970 static const unsigned char *
971 unw_decode_b1 (const unsigned char *dp, unsigned int code,
972 void *arg ATTRIBUTE_UNUSED,
973 const unsigned char * end ATTRIBUTE_UNUSED)
974 {
975 unw_word label = (code & 0x1f);
976
977 if ((code & 0x20) != 0)
978 UNW_DEC_COPY_STATE ("B1", label, arg);
979 else
980 UNW_DEC_LABEL_STATE ("B1", label, arg);
981 return dp;
982 }
983
984 static const unsigned char *
985 unw_decode_b2 (const unsigned char *dp, unsigned int code,
986 void *arg ATTRIBUTE_UNUSED,
987 const unsigned char * end)
988 {
989 unw_word t;
990
991 t = unw_decode_uleb128 (& dp, end);
992 UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
993 return dp;
994 }
995
996 static const unsigned char *
997 unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg,
998 const unsigned char * end)
999 {
1000 unw_word t, ecount, label;
1001
1002 if ((code & 0x10) == 0)
1003 {
1004 t = unw_decode_uleb128 (&dp, end);
1005 ecount = unw_decode_uleb128 (&dp, end);
1006 UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
1007 }
1008 else if ((code & 0x07) == 0)
1009 {
1010 label = unw_decode_uleb128 (&dp, end);
1011 if ((code & 0x08) != 0)
1012 UNW_DEC_COPY_STATE ("B4", label, arg);
1013 else
1014 UNW_DEC_LABEL_STATE ("B4", label, arg);
1015 }
1016 else
1017 switch (code & 0x7)
1018 {
1019 case 1:
1020 return unw_decode_x1 (dp, code, arg, end);
1021 case 2:
1022 return unw_decode_x2 (dp, code, arg, end);
1023 case 3:
1024 return unw_decode_x3 (dp, code, arg, end);
1025 case 4:
1026 return unw_decode_x4 (dp, code, arg, end);
1027 default:
1028 UNW_DEC_BAD_CODE (code);
1029 break;
1030 }
1031 return dp;
1032 }
1033
1034 typedef const unsigned char *(*unw_decoder)
1035 (const unsigned char *, unsigned int, void *, const unsigned char *);
1036
1037 static const unw_decoder unw_decode_table[2][8] =
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. */
1063 const unsigned char *
1064 unw_decode (const unsigned char *dp, int inside_body,
1065 void *ptr_inside_body, const unsigned char * end)
1066 {
1067 unw_decoder decoder;
1068 unsigned char code;
1069
1070 code = *dp++;
1071 decoder = unw_decode_table[inside_body][code >> 5];
1072 return (*decoder) (dp, code, ptr_inside_body, end);
1073 }