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