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