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