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