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