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