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