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