1 //===-------------------------- DwarfInstructions.hpp ---------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 // 9 // Processor specific interpretation of DWARF unwind info. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef __DWARF_INSTRUCTIONS_HPP__ 14 #define __DWARF_INSTRUCTIONS_HPP__ 15 16 #include <stdint.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 20 #include "dwarf2.h" 21 #include "Registers.hpp" 22 #include "DwarfParser.hpp" 23 #include "config.h" 24 25 26 namespace libunwind { 27 28 29 /// DwarfInstructions maps abtract DWARF unwind instructions to a particular 30 /// architecture 31 template <typename A, typename R> 32 class DwarfInstructions { 33 public: 34 typedef typename A::pint_t pint_t; 35 typedef typename A::sint_t sint_t; 36 37 static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, 38 R ®isters); 39 40 private: 41 42 enum { 43 DW_X86_64_RET_ADDR = 16 44 }; 45 46 enum { 47 DW_X86_RET_ADDR = 8 48 }; 49 50 typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation; 51 typedef typename CFI_Parser<A>::PrologInfo PrologInfo; 52 typedef typename CFI_Parser<A>::FDE_Info FDE_Info; 53 typedef typename CFI_Parser<A>::CIE_Info CIE_Info; 54 55 static pint_t evaluateExpression(pint_t expression, A &addressSpace, 56 const R ®isters, 57 pint_t initialStackValue); 58 static pint_t getSavedRegister(A &addressSpace, const R ®isters, 59 pint_t cfa, const RegisterLocation &savedReg); 60 static double getSavedFloatRegister(A &addressSpace, const R ®isters, 61 pint_t cfa, const RegisterLocation &savedReg); 62 static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, 63 pint_t cfa, const RegisterLocation &savedReg); 64 65 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, 66 const R ®isters) { 67 if (prolog.cfaRegister != 0) 68 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + 69 prolog.cfaRegisterOffset); 70 if (prolog.cfaExpression != 0) 71 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, 72 registers, 0); 73 assert(0 && "getCFA(): unknown location"); 74 __builtin_unreachable(); 75 } 76 }; 77 78 79 template <typename A, typename R> 80 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( 81 A &addressSpace, const R ®isters, pint_t cfa, 82 const RegisterLocation &savedReg) { 83 switch (savedReg.location) { 84 case CFI_Parser<A>::kRegisterInCFA: 85 return addressSpace.getRegister(cfa + (pint_t)savedReg.value); 86 87 case CFI_Parser<A>::kRegisterAtExpression: 88 return addressSpace.getRegister( 89 evaluateExpression((pint_t)savedReg.value, addressSpace, 90 registers, cfa)); 91 92 case CFI_Parser<A>::kRegisterIsExpression: 93 return evaluateExpression((pint_t)savedReg.value, addressSpace, 94 registers, cfa); 95 96 case CFI_Parser<A>::kRegisterInRegister: 97 return registers.getRegister((int)savedReg.value); 98 99 case CFI_Parser<A>::kRegisterUnused: 100 case CFI_Parser<A>::kRegisterOffsetFromCFA: 101 // FIX ME 102 break; 103 } 104 _LIBUNWIND_ABORT("unsupported restore location for register"); 105 } 106 107 template <typename A, typename R> 108 double DwarfInstructions<A, R>::getSavedFloatRegister( 109 A &addressSpace, const R ®isters, pint_t cfa, 110 const RegisterLocation &savedReg) { 111 switch (savedReg.location) { 112 case CFI_Parser<A>::kRegisterInCFA: 113 return addressSpace.getDouble(cfa + (pint_t)savedReg.value); 114 115 case CFI_Parser<A>::kRegisterAtExpression: 116 return addressSpace.getDouble( 117 evaluateExpression((pint_t)savedReg.value, addressSpace, 118 registers, cfa)); 119 120 case CFI_Parser<A>::kRegisterIsExpression: 121 case CFI_Parser<A>::kRegisterUnused: 122 case CFI_Parser<A>::kRegisterOffsetFromCFA: 123 case CFI_Parser<A>::kRegisterInRegister: 124 // FIX ME 125 break; 126 } 127 _LIBUNWIND_ABORT("unsupported restore location for float register"); 128 } 129 130 template <typename A, typename R> 131 v128 DwarfInstructions<A, R>::getSavedVectorRegister( 132 A &addressSpace, const R ®isters, pint_t cfa, 133 const RegisterLocation &savedReg) { 134 switch (savedReg.location) { 135 case CFI_Parser<A>::kRegisterInCFA: 136 return addressSpace.getVector(cfa + (pint_t)savedReg.value); 137 138 case CFI_Parser<A>::kRegisterAtExpression: 139 return addressSpace.getVector( 140 evaluateExpression((pint_t)savedReg.value, addressSpace, 141 registers, cfa)); 142 143 case CFI_Parser<A>::kRegisterIsExpression: 144 case CFI_Parser<A>::kRegisterUnused: 145 case CFI_Parser<A>::kRegisterOffsetFromCFA: 146 case CFI_Parser<A>::kRegisterInRegister: 147 // FIX ME 148 break; 149 } 150 _LIBUNWIND_ABORT("unsupported restore location for vector register"); 151 } 152 153 template <typename A, typename R> 154 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, 155 pint_t fdeStart, R ®isters) { 156 FDE_Info fdeInfo; 157 CIE_Info cieInfo; 158 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, 159 &cieInfo) == NULL) { 160 PrologInfo prolog; 161 if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, 162 &prolog)) { 163 // get pointer to cfa (architecture specific) 164 pint_t cfa = getCFA(addressSpace, prolog, registers); 165 166 // restore registers that DWARF says were saved 167 R newRegisters = registers; 168 pint_t returnAddress = 0; 169 const int lastReg = R::lastDwarfRegNum(); 170 assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg && 171 "register range too large"); 172 assert(lastReg >= (int)cieInfo.returnAddressRegister && 173 "register range does not contain return address register"); 174 for (int i = 0; i <= lastReg; ++i) { 175 if (prolog.savedRegisters[i].location != 176 CFI_Parser<A>::kRegisterUnused) { 177 if (registers.validFloatRegister(i)) 178 newRegisters.setFloatRegister( 179 i, getSavedFloatRegister(addressSpace, registers, cfa, 180 prolog.savedRegisters[i])); 181 else if (registers.validVectorRegister(i)) 182 newRegisters.setVectorRegister( 183 i, getSavedVectorRegister(addressSpace, registers, cfa, 184 prolog.savedRegisters[i])); 185 else if (i == (int)cieInfo.returnAddressRegister) 186 returnAddress = getSavedRegister(addressSpace, registers, cfa, 187 prolog.savedRegisters[i]); 188 else if (registers.validRegister(i)) 189 newRegisters.setRegister( 190 i, getSavedRegister(addressSpace, registers, cfa, 191 prolog.savedRegisters[i])); 192 else 193 return UNW_EBADREG; 194 } 195 } 196 197 // By definition, the CFA is the stack pointer at the call site, so 198 // restoring SP means setting it to CFA. 199 newRegisters.setSP(cfa); 200 201 #if defined(_LIBUNWIND_TARGET_AARCH64) 202 // If the target is aarch64 then the return address may have been signed 203 // using the v8.3 pointer authentication extensions. The original 204 // return address needs to be authenticated before the return address is 205 // restored. autia1716 is used instead of autia as autia1716 assembles 206 // to a NOP on pre-v8.3a architectures. 207 if (prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) { 208 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) 209 return UNW_ECROSSRASIGNING; 210 #else 211 register unsigned long long x17 __asm("x17") = returnAddress; 212 register unsigned long long x16 __asm("x16") = cfa; 213 214 // These are the autia1716/autib1716 instructions. The hint instructions 215 // are used here as gcc does not assemble autia1716/autib1716 for pre 216 // armv8.3a targets. 217 if (cieInfo.addressesSignedWithBKey) 218 asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 219 else 220 asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 221 returnAddress = x17; 222 #endif 223 } 224 #endif 225 226 #if defined(_LIBUNWIND_TARGET_SPARC) 227 // Skip call site instruction and delay slot 228 returnAddress += 8; 229 // Skip unimp instruction if function returns a struct 230 if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0) 231 returnAddress += 4; 232 #endif 233 234 // Return address is address after call site instruction, so setting IP to 235 // that does simualates a return. 236 newRegisters.setIP(returnAddress); 237 238 // Simulate the step by replacing the register set with the new ones. 239 registers = newRegisters; 240 241 return UNW_STEP_SUCCESS; 242 } 243 } 244 return UNW_EBADFRAME; 245 } 246 247 template <typename A, typename R> 248 typename A::pint_t 249 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, 250 const R ®isters, 251 pint_t initialStackValue) { 252 const bool log = false; 253 pint_t p = expression; 254 pint_t expressionEnd = expression + 20; // temp, until len read 255 pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd); 256 expressionEnd = p + length; 257 if (log) 258 fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n", 259 (uint64_t)length); 260 pint_t stack[100]; 261 pint_t *sp = stack; 262 *(++sp) = initialStackValue; 263 264 while (p < expressionEnd) { 265 if (log) { 266 for (pint_t *t = sp; t > stack; --t) { 267 fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t)); 268 } 269 } 270 uint8_t opcode = addressSpace.get8(p++); 271 sint_t svalue, svalue2; 272 pint_t value; 273 uint32_t reg; 274 switch (opcode) { 275 case DW_OP_addr: 276 // push immediate address sized value 277 value = addressSpace.getP(p); 278 p += sizeof(pint_t); 279 *(++sp) = value; 280 if (log) 281 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 282 break; 283 284 case DW_OP_deref: 285 // pop stack, dereference, push result 286 value = *sp--; 287 *(++sp) = addressSpace.getP(value); 288 if (log) 289 fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value); 290 break; 291 292 case DW_OP_const1u: 293 // push immediate 1 byte value 294 value = addressSpace.get8(p); 295 p += 1; 296 *(++sp) = value; 297 if (log) 298 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 299 break; 300 301 case DW_OP_const1s: 302 // push immediate 1 byte signed value 303 svalue = (int8_t) addressSpace.get8(p); 304 p += 1; 305 *(++sp) = (pint_t)svalue; 306 if (log) 307 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 308 break; 309 310 case DW_OP_const2u: 311 // push immediate 2 byte value 312 value = addressSpace.get16(p); 313 p += 2; 314 *(++sp) = value; 315 if (log) 316 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 317 break; 318 319 case DW_OP_const2s: 320 // push immediate 2 byte signed value 321 svalue = (int16_t) addressSpace.get16(p); 322 p += 2; 323 *(++sp) = (pint_t)svalue; 324 if (log) 325 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 326 break; 327 328 case DW_OP_const4u: 329 // push immediate 4 byte value 330 value = addressSpace.get32(p); 331 p += 4; 332 *(++sp) = value; 333 if (log) 334 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 335 break; 336 337 case DW_OP_const4s: 338 // push immediate 4 byte signed value 339 svalue = (int32_t)addressSpace.get32(p); 340 p += 4; 341 *(++sp) = (pint_t)svalue; 342 if (log) 343 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 344 break; 345 346 case DW_OP_const8u: 347 // push immediate 8 byte value 348 value = (pint_t)addressSpace.get64(p); 349 p += 8; 350 *(++sp) = value; 351 if (log) 352 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 353 break; 354 355 case DW_OP_const8s: 356 // push immediate 8 byte signed value 357 value = (pint_t)addressSpace.get64(p); 358 p += 8; 359 *(++sp) = value; 360 if (log) 361 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 362 break; 363 364 case DW_OP_constu: 365 // push immediate ULEB128 value 366 value = (pint_t)addressSpace.getULEB128(p, expressionEnd); 367 *(++sp) = value; 368 if (log) 369 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 370 break; 371 372 case DW_OP_consts: 373 // push immediate SLEB128 value 374 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); 375 *(++sp) = (pint_t)svalue; 376 if (log) 377 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 378 break; 379 380 case DW_OP_dup: 381 // push top of stack 382 value = *sp; 383 *(++sp) = value; 384 if (log) 385 fprintf(stderr, "duplicate top of stack\n"); 386 break; 387 388 case DW_OP_drop: 389 // pop 390 --sp; 391 if (log) 392 fprintf(stderr, "pop top of stack\n"); 393 break; 394 395 case DW_OP_over: 396 // dup second 397 value = sp[-1]; 398 *(++sp) = value; 399 if (log) 400 fprintf(stderr, "duplicate second in stack\n"); 401 break; 402 403 case DW_OP_pick: 404 // pick from 405 reg = addressSpace.get8(p); 406 p += 1; 407 value = sp[-reg]; 408 *(++sp) = value; 409 if (log) 410 fprintf(stderr, "duplicate %d in stack\n", reg); 411 break; 412 413 case DW_OP_swap: 414 // swap top two 415 value = sp[0]; 416 sp[0] = sp[-1]; 417 sp[-1] = value; 418 if (log) 419 fprintf(stderr, "swap top of stack\n"); 420 break; 421 422 case DW_OP_rot: 423 // rotate top three 424 value = sp[0]; 425 sp[0] = sp[-1]; 426 sp[-1] = sp[-2]; 427 sp[-2] = value; 428 if (log) 429 fprintf(stderr, "rotate top three of stack\n"); 430 break; 431 432 case DW_OP_xderef: 433 // pop stack, dereference, push result 434 value = *sp--; 435 *sp = *((pint_t*)value); 436 if (log) 437 fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value); 438 break; 439 440 case DW_OP_abs: 441 svalue = (sint_t)*sp; 442 if (svalue < 0) 443 *sp = (pint_t)(-svalue); 444 if (log) 445 fprintf(stderr, "abs\n"); 446 break; 447 448 case DW_OP_and: 449 value = *sp--; 450 *sp &= value; 451 if (log) 452 fprintf(stderr, "and\n"); 453 break; 454 455 case DW_OP_div: 456 svalue = (sint_t)(*sp--); 457 svalue2 = (sint_t)*sp; 458 *sp = (pint_t)(svalue2 / svalue); 459 if (log) 460 fprintf(stderr, "div\n"); 461 break; 462 463 case DW_OP_minus: 464 value = *sp--; 465 *sp = *sp - value; 466 if (log) 467 fprintf(stderr, "minus\n"); 468 break; 469 470 case DW_OP_mod: 471 svalue = (sint_t)(*sp--); 472 svalue2 = (sint_t)*sp; 473 *sp = (pint_t)(svalue2 % svalue); 474 if (log) 475 fprintf(stderr, "module\n"); 476 break; 477 478 case DW_OP_mul: 479 svalue = (sint_t)(*sp--); 480 svalue2 = (sint_t)*sp; 481 *sp = (pint_t)(svalue2 * svalue); 482 if (log) 483 fprintf(stderr, "mul\n"); 484 break; 485 486 case DW_OP_neg: 487 *sp = 0 - *sp; 488 if (log) 489 fprintf(stderr, "neg\n"); 490 break; 491 492 case DW_OP_not: 493 svalue = (sint_t)(*sp); 494 *sp = (pint_t)(~svalue); 495 if (log) 496 fprintf(stderr, "not\n"); 497 break; 498 499 case DW_OP_or: 500 value = *sp--; 501 *sp |= value; 502 if (log) 503 fprintf(stderr, "or\n"); 504 break; 505 506 case DW_OP_plus: 507 value = *sp--; 508 *sp += value; 509 if (log) 510 fprintf(stderr, "plus\n"); 511 break; 512 513 case DW_OP_plus_uconst: 514 // pop stack, add uelb128 constant, push result 515 *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd)); 516 if (log) 517 fprintf(stderr, "add constant\n"); 518 break; 519 520 case DW_OP_shl: 521 value = *sp--; 522 *sp = *sp << value; 523 if (log) 524 fprintf(stderr, "shift left\n"); 525 break; 526 527 case DW_OP_shr: 528 value = *sp--; 529 *sp = *sp >> value; 530 if (log) 531 fprintf(stderr, "shift left\n"); 532 break; 533 534 case DW_OP_shra: 535 value = *sp--; 536 svalue = (sint_t)*sp; 537 *sp = (pint_t)(svalue >> value); 538 if (log) 539 fprintf(stderr, "shift left arithmetric\n"); 540 break; 541 542 case DW_OP_xor: 543 value = *sp--; 544 *sp ^= value; 545 if (log) 546 fprintf(stderr, "xor\n"); 547 break; 548 549 case DW_OP_skip: 550 svalue = (int16_t) addressSpace.get16(p); 551 p += 2; 552 p = (pint_t)((sint_t)p + svalue); 553 if (log) 554 fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue); 555 break; 556 557 case DW_OP_bra: 558 svalue = (int16_t) addressSpace.get16(p); 559 p += 2; 560 if (*sp--) 561 p = (pint_t)((sint_t)p + svalue); 562 if (log) 563 fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue); 564 break; 565 566 case DW_OP_eq: 567 value = *sp--; 568 *sp = (*sp == value); 569 if (log) 570 fprintf(stderr, "eq\n"); 571 break; 572 573 case DW_OP_ge: 574 value = *sp--; 575 *sp = (*sp >= value); 576 if (log) 577 fprintf(stderr, "ge\n"); 578 break; 579 580 case DW_OP_gt: 581 value = *sp--; 582 *sp = (*sp > value); 583 if (log) 584 fprintf(stderr, "gt\n"); 585 break; 586 587 case DW_OP_le: 588 value = *sp--; 589 *sp = (*sp <= value); 590 if (log) 591 fprintf(stderr, "le\n"); 592 break; 593 594 case DW_OP_lt: 595 value = *sp--; 596 *sp = (*sp < value); 597 if (log) 598 fprintf(stderr, "lt\n"); 599 break; 600 601 case DW_OP_ne: 602 value = *sp--; 603 *sp = (*sp != value); 604 if (log) 605 fprintf(stderr, "ne\n"); 606 break; 607 608 case DW_OP_lit0: 609 case DW_OP_lit1: 610 case DW_OP_lit2: 611 case DW_OP_lit3: 612 case DW_OP_lit4: 613 case DW_OP_lit5: 614 case DW_OP_lit6: 615 case DW_OP_lit7: 616 case DW_OP_lit8: 617 case DW_OP_lit9: 618 case DW_OP_lit10: 619 case DW_OP_lit11: 620 case DW_OP_lit12: 621 case DW_OP_lit13: 622 case DW_OP_lit14: 623 case DW_OP_lit15: 624 case DW_OP_lit16: 625 case DW_OP_lit17: 626 case DW_OP_lit18: 627 case DW_OP_lit19: 628 case DW_OP_lit20: 629 case DW_OP_lit21: 630 case DW_OP_lit22: 631 case DW_OP_lit23: 632 case DW_OP_lit24: 633 case DW_OP_lit25: 634 case DW_OP_lit26: 635 case DW_OP_lit27: 636 case DW_OP_lit28: 637 case DW_OP_lit29: 638 case DW_OP_lit30: 639 case DW_OP_lit31: 640 value = static_cast<pint_t>(opcode - DW_OP_lit0); 641 *(++sp) = value; 642 if (log) 643 fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value); 644 break; 645 646 case DW_OP_reg0: 647 case DW_OP_reg1: 648 case DW_OP_reg2: 649 case DW_OP_reg3: 650 case DW_OP_reg4: 651 case DW_OP_reg5: 652 case DW_OP_reg6: 653 case DW_OP_reg7: 654 case DW_OP_reg8: 655 case DW_OP_reg9: 656 case DW_OP_reg10: 657 case DW_OP_reg11: 658 case DW_OP_reg12: 659 case DW_OP_reg13: 660 case DW_OP_reg14: 661 case DW_OP_reg15: 662 case DW_OP_reg16: 663 case DW_OP_reg17: 664 case DW_OP_reg18: 665 case DW_OP_reg19: 666 case DW_OP_reg20: 667 case DW_OP_reg21: 668 case DW_OP_reg22: 669 case DW_OP_reg23: 670 case DW_OP_reg24: 671 case DW_OP_reg25: 672 case DW_OP_reg26: 673 case DW_OP_reg27: 674 case DW_OP_reg28: 675 case DW_OP_reg29: 676 case DW_OP_reg30: 677 case DW_OP_reg31: 678 reg = static_cast<uint32_t>(opcode - DW_OP_reg0); 679 *(++sp) = registers.getRegister((int)reg); 680 if (log) 681 fprintf(stderr, "push reg %d\n", reg); 682 break; 683 684 case DW_OP_regx: 685 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd)); 686 *(++sp) = registers.getRegister((int)reg); 687 if (log) 688 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); 689 break; 690 691 case DW_OP_breg0: 692 case DW_OP_breg1: 693 case DW_OP_breg2: 694 case DW_OP_breg3: 695 case DW_OP_breg4: 696 case DW_OP_breg5: 697 case DW_OP_breg6: 698 case DW_OP_breg7: 699 case DW_OP_breg8: 700 case DW_OP_breg9: 701 case DW_OP_breg10: 702 case DW_OP_breg11: 703 case DW_OP_breg12: 704 case DW_OP_breg13: 705 case DW_OP_breg14: 706 case DW_OP_breg15: 707 case DW_OP_breg16: 708 case DW_OP_breg17: 709 case DW_OP_breg18: 710 case DW_OP_breg19: 711 case DW_OP_breg20: 712 case DW_OP_breg21: 713 case DW_OP_breg22: 714 case DW_OP_breg23: 715 case DW_OP_breg24: 716 case DW_OP_breg25: 717 case DW_OP_breg26: 718 case DW_OP_breg27: 719 case DW_OP_breg28: 720 case DW_OP_breg29: 721 case DW_OP_breg30: 722 case DW_OP_breg31: 723 reg = static_cast<uint32_t>(opcode - DW_OP_breg0); 724 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); 725 svalue += static_cast<sint_t>(registers.getRegister((int)reg)); 726 *(++sp) = (pint_t)(svalue); 727 if (log) 728 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); 729 break; 730 731 case DW_OP_bregx: 732 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd)); 733 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); 734 svalue += static_cast<sint_t>(registers.getRegister((int)reg)); 735 *(++sp) = (pint_t)(svalue); 736 if (log) 737 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); 738 break; 739 740 case DW_OP_fbreg: 741 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented"); 742 break; 743 744 case DW_OP_piece: 745 _LIBUNWIND_ABORT("DW_OP_piece not implemented"); 746 break; 747 748 case DW_OP_deref_size: 749 // pop stack, dereference, push result 750 value = *sp--; 751 switch (addressSpace.get8(p++)) { 752 case 1: 753 value = addressSpace.get8(value); 754 break; 755 case 2: 756 value = addressSpace.get16(value); 757 break; 758 case 4: 759 value = addressSpace.get32(value); 760 break; 761 case 8: 762 value = (pint_t)addressSpace.get64(value); 763 break; 764 default: 765 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size"); 766 } 767 *(++sp) = value; 768 if (log) 769 fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value); 770 break; 771 772 case DW_OP_xderef_size: 773 case DW_OP_nop: 774 case DW_OP_push_object_addres: 775 case DW_OP_call2: 776 case DW_OP_call4: 777 case DW_OP_call_ref: 778 default: 779 _LIBUNWIND_ABORT("DWARF opcode not implemented"); 780 } 781 782 } 783 if (log) 784 fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp); 785 return *sp; 786 } 787 788 789 790 } // namespace libunwind 791 792 #endif // __DWARF_INSTRUCTIONS_HPP__ 793