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