File: /usr/src/linux/arch/ia64/kernel/unwind_decoder.c

1     /*
2      * Copyright (C) 2000 Hewlett-Packard Co
3      * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
4      *
5      * Generic IA-64 unwind info decoder.
6      *
7      * This file is used both by the Linux kernel and objdump.  Please keep
8      * the two copies of this file in sync.
9      *
10      * You need to customize the decoder by defining the following
11      * macros/constants before including this file:
12      *
13      *  Types:
14      *	unw_word	Unsigned integer type with at least 64 bits 
15      *
16      *  Register names:
17      *	UNW_REG_BSP
18      *	UNW_REG_BSPSTORE
19      *	UNW_REG_FPSR
20      *	UNW_REG_LC
21      *	UNW_REG_PFS
22      *	UNW_REG_PR
23      *	UNW_REG_RNAT
24      *	UNW_REG_PSP
25      *	UNW_REG_RP
26      *	UNW_REG_UNAT
27      *
28      *  Decoder action macros:
29      *	UNW_DEC_BAD_CODE(code)
30      *	UNW_DEC_ABI(fmt,abi,context,arg)
31      *	UNW_DEC_BR_GR(fmt,brmask,gr,arg)
32      *	UNW_DEC_BR_MEM(fmt,brmask,arg)
33      *	UNW_DEC_COPY_STATE(fmt,label,arg)
34      *	UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
35      *	UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
36      *	UNW_DEC_FR_MEM(fmt,frmask,arg)
37      *	UNW_DEC_GR_GR(fmt,grmask,gr,arg)
38      *	UNW_DEC_GR_MEM(fmt,grmask,arg)
39      *	UNW_DEC_LABEL_STATE(fmt,label,arg)
40      *	UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
41      *	UNW_DEC_MEM_STACK_V(fmt,t,arg)
42      *	UNW_DEC_PRIUNAT_GR(fmt,r,arg)
43      *	UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
44      *	UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
45      *	UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
46      *	UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
47      *	UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
48      *	UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
49      *	UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
50      *	UNW_DEC_REG_REG(fmt,src,dst,arg)
51      *	UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
52      *	UNW_DEC_REG_WHEN(fmt,reg,t,arg)
53      *	UNW_DEC_RESTORE(fmt,t,abreg,arg)
54      *	UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
55      *	UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
56      *	UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
57      *	UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
58      *	UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
59      *	UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
60      *	UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
61      *	UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
62      *	UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
63      */
64     
65     static unw_word
66     unw_decode_uleb128 (unsigned char **dpp)
67     {
68       unsigned shift = 0;
69       unw_word byte, result = 0;
70       unsigned char *bp = *dpp;
71     
72       while (1)
73         {
74           byte = *bp++;
75           result |= (byte & 0x7f) << shift;
76           if ((byte & 0x80) == 0)
77     	break;
78           shift += 7;
79         }
80       *dpp = bp;
81       return result;
82     }
83     
84     static unsigned char *
85     unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg)
86     {
87       unsigned char byte1, abreg;
88       unw_word t, off;
89     
90       byte1 = *dp++;
91       t = unw_decode_uleb128 (&dp);
92       off = unw_decode_uleb128 (&dp);
93       abreg = (byte1 & 0x7f);
94       if (byte1 & 0x80)
95     	  UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
96       else
97     	  UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
98       return dp;
99     }
100     
101     static unsigned char *
102     unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg)
103     {
104       unsigned char byte1, byte2, abreg, x, ytreg;
105       unw_word t;
106     
107       byte1 = *dp++; byte2 = *dp++;
108       t = unw_decode_uleb128 (&dp);
109       abreg = (byte1 & 0x7f);
110       ytreg = byte2;
111       x = (byte1 >> 7) & 1;
112       if ((byte1 & 0x80) == 0 && ytreg == 0)
113         UNW_DEC_RESTORE(X2, t, abreg, arg);
114       else
115         UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
116       return dp;
117     }
118     
119     static unsigned char *
120     unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg)
121     {
122       unsigned char byte1, byte2, abreg, qp;
123       unw_word t, off;
124     
125       byte1 = *dp++; byte2 = *dp++;
126       t = unw_decode_uleb128 (&dp);
127       off = unw_decode_uleb128 (&dp);
128     
129       qp = (byte1 & 0x3f);
130       abreg = (byte2 & 0x7f);
131     
132       if (byte1 & 0x80)
133         UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
134       else
135         UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
136       return dp;
137     }
138     
139     static unsigned char *
140     unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg)
141     {
142       unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
143       unw_word t;
144     
145       byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
146       t = unw_decode_uleb128 (&dp);
147     
148       qp = (byte1 & 0x3f);
149       abreg = (byte2 & 0x7f);
150       x = (byte2 >> 7) & 1;
151       ytreg = byte3;
152     
153       if ((byte2 & 0x80) == 0 && byte3 == 0)
154         UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
155       else
156         UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
157       return dp;
158     }
159     
160     static unsigned char *
161     unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
162     {
163       int body = (code & 0x20) != 0;
164       unw_word rlen;
165     
166       rlen = (code & 0x1f);
167       UNW_DEC_PROLOGUE(R1, body, rlen, arg);
168       return dp;
169     }
170     
171     static unsigned char *
172     unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
173     {
174       unsigned char byte1, mask, grsave;
175       unw_word rlen;
176     
177       byte1 = *dp++;
178     
179       mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
180       grsave = (byte1 & 0x7f);
181       rlen = unw_decode_uleb128 (&dp);
182       UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
183       return dp;
184     }
185     
186     static unsigned char *
187     unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
188     {
189       unw_word rlen;
190     
191       rlen = unw_decode_uleb128 (&dp);
192       UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
193       return dp;
194     }
195     
196     static unsigned char *
197     unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
198     {
199       unsigned char brmask = (code & 0x1f);
200     
201       UNW_DEC_BR_MEM(P1, brmask, arg);
202       return dp;
203     }
204     
205     static unsigned char *
206     unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
207     {
208       if ((code & 0x10) == 0)
209         {
210           unsigned char byte1 = *dp++;
211     
212           UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
213     		    (byte1 & 0x7f), arg);
214         }
215       else if ((code & 0x08) == 0)
216         {
217           unsigned char byte1 = *dp++, r, dst;
218     
219           r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
220           dst = (byte1 & 0x7f);
221           switch (r)
222     	{
223     	case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
224     	case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
225     	case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
226     	case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
227     	case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
228     	case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
229     	case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
230     	case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
231     	case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
232     	case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
233     	case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
234     	case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
235     	default: UNW_DEC_BAD_CODE(r); break;
236     	}
237         }
238       else if ((code & 0x7) == 0)
239         UNW_DEC_SPILL_MASK(P4, dp, arg);
240       else if ((code & 0x7) == 1)
241         {
242           unw_word grmask, frmask, byte1, byte2, byte3;
243     
244           byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
245           grmask = ((byte1 >> 4) & 0xf);
246           frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
247           UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
248         }
249       else
250         UNW_DEC_BAD_CODE(code);
251       return dp;
252     }
253     
254     static unsigned char *
255     unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
256     {
257       int gregs = (code & 0x10) != 0;
258       unsigned char mask = (code & 0x0f);
259     
260       if (gregs)
261         UNW_DEC_GR_MEM(P6, mask, arg);
262       else
263         UNW_DEC_FR_MEM(P6, mask, arg);
264       return dp;
265     }
266     
267     static unsigned char *
268     unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
269     {
270       unsigned char r, byte1, byte2;
271       unw_word t, size;
272     
273       if ((code & 0x10) == 0)
274         {
275           r = (code & 0xf);
276           t = unw_decode_uleb128 (&dp);
277           switch (r)
278     	{
279     	case 0:
280     	  size = unw_decode_uleb128 (&dp);
281     	  UNW_DEC_MEM_STACK_F(P7, t, size, arg);
282     	  break;
283     
284     	case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
285     	case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
286     	case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
287     	case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
288     	case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
289     	case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
290     	case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
291     	case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
292     	case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
293     	case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
294     	case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
295     	case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
296     	case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
297     	case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
298     	case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
299     	default: UNW_DEC_BAD_CODE(r); break;
300     	}
301         }
302       else
303         {
304           switch (code & 0xf)
305     	{
306     	case 0x0: /* p8 */
307     	  {
308     	    r = *dp++;
309     	    t = unw_decode_uleb128 (&dp);
310     	    switch (r)
311     	      {
312     	      case  1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
313     	      case  2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
314     	      case  3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
315     	      case  4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
316     	      case  5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
317     	      case  6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
318     	      case  7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
319     	      case  8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
320     	      case  9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
321     	      case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
322     	      case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
323     	      case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
324     	      case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
325     	      case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
326     	      case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
327     	      case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
328     	      case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
329     	      case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
330     	      case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
331     	      default: UNW_DEC_BAD_CODE(r); break;
332     	    }
333     	  }
334     	  break;
335     
336     	case 0x1:
337     	  byte1 = *dp++; byte2 = *dp++;
338     	  UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
339     	  break;
340     
341     	case 0xf: /* p10 */
342     	  byte1 = *dp++; byte2 = *dp++;
343     	  UNW_DEC_ABI(P10, byte1, byte2, arg);
344     	  break;
345     
346     	case 0x9:
347     	  return unw_decode_x1 (dp, code, arg);
348     
349     	case 0xa:
350     	  return unw_decode_x2 (dp, code, arg);
351     
352     	case 0xb:
353     	  return unw_decode_x3 (dp, code, arg);
354     
355     	case 0xc:
356     	  return unw_decode_x4 (dp, code, arg);
357     
358     	default:
359     	  UNW_DEC_BAD_CODE(code);
360     	  break;
361     	}
362         }
363       return dp;
364     }
365     
366     static unsigned char *
367     unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
368     {
369       unw_word label = (code & 0x1f);
370     
371       if ((code & 0x20) != 0)
372         UNW_DEC_COPY_STATE(B1, label, arg);
373       else
374         UNW_DEC_LABEL_STATE(B1, label, arg);
375       return dp;
376     }
377     
378     static unsigned char *
379     unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
380     {
381       unw_word t;
382     
383       t = unw_decode_uleb128 (&dp);
384       UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
385       return dp;
386     }
387     
388     static unsigned char *
389     unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
390     {
391       unw_word t, ecount, label;
392     
393       if ((code & 0x10) == 0)
394         {
395           t = unw_decode_uleb128 (&dp);
396           ecount = unw_decode_uleb128 (&dp);
397           UNW_DEC_EPILOGUE(B3, t, ecount, arg);
398         }
399       else if ((code & 0x07) == 0)
400         {
401           label = unw_decode_uleb128 (&dp);
402           if ((code & 0x08) != 0)
403     	UNW_DEC_COPY_STATE(B4, label, arg);
404           else
405     	UNW_DEC_LABEL_STATE(B4, label, arg);
406         }
407       else
408         switch (code & 0x7)
409           {
410           case 1: return unw_decode_x1 (dp, code, arg);
411           case 2: return unw_decode_x2 (dp, code, arg);
412           case 3: return unw_decode_x3 (dp, code, arg);
413           case 4: return unw_decode_x4 (dp, code, arg);
414           default: UNW_DEC_BAD_CODE(code); break;
415           }
416       return dp;
417     }
418     
419     typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
420     
421     static unw_decoder unw_decode_table[2][8] =
422     {
423       /* prologue table: */
424       {
425         unw_decode_r1,	/* 0 */
426         unw_decode_r1,
427         unw_decode_r2,
428         unw_decode_r3,
429         unw_decode_p1,	/* 4 */
430         unw_decode_p2_p5,
431         unw_decode_p6,
432         unw_decode_p7_p10
433       },
434       {
435         unw_decode_r1,	/* 0 */
436         unw_decode_r1,
437         unw_decode_r2,
438         unw_decode_r3,
439         unw_decode_b1,	/* 4 */
440         unw_decode_b1,
441         unw_decode_b2,
442         unw_decode_b3_x4
443       }
444     };
445     
446     /*
447      * Decode one descriptor and return address of next descriptor.
448      */
449     static inline unsigned char *
450     unw_decode (unsigned char *dp, int inside_body, void *arg)
451     {
452       unw_decoder decoder;
453       unsigned char code;
454     
455       code = *dp++;
456       decoder = unw_decode_table[inside_body][code >> 5];
457       dp = (*decoder) (dp, code, arg);
458       return dp;
459     }
460