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