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