brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.8 KiB · d2822e8 Raw
971 lines · plain
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-exception6//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 "DwarfParser.hpp"20#include "Registers.hpp"21#include "config.h"22#include "dwarf2.h"23#include "libunwind_ext.h"24 25namespace libunwind {26 27 28/// DwarfInstructions maps abstract DWARF unwind instructions to a particular29/// architecture30template <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, const typename R::link_reg_t &pc,37                           pint_t fdeStart, R &registers, bool &isSignalFrame,38                           bool stage2);39 40private:41 42  enum {43    DW_X86_64_RET_ADDR = 1644  };45 46  enum {47    DW_X86_RET_ADDR = 848  };49 50  typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;51  typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;52  typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;53  typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;54 55  static pint_t evaluateExpression(pint_t expression, A &addressSpace,56                                   const R &registers,57                                   pint_t initialStackValue);58  static pint_t getSavedRegister(A &addressSpace, const R &registers,59                                 pint_t cfa, const RegisterLocation &savedReg);60  static double getSavedFloatRegister(A &addressSpace, const R &registers,61                                  pint_t cfa, const RegisterLocation &savedReg);62  static v128 getSavedVectorRegister(A &addressSpace, const R &registers,63                                  pint_t cfa, const RegisterLocation &savedReg);64 65  static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,66                       const R &registers) {67    if (prolog.cfaRegister != 0) {68      uintptr_t cfaRegister = registers.getRegister((int)prolog.cfaRegister);69      return (pint_t)(cfaRegister + prolog.cfaRegisterOffset);70    }71    if (prolog.cfaExpression != 0)72      return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,73                                registers, 0);74    assert(0 && "getCFA(): unknown location");75    __builtin_unreachable();76  }77#if defined(_LIBUNWIND_TARGET_AARCH64)78  static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa,79                                    PrologInfo &prolog);80  static bool isReturnAddressSignedWithPC(A &addressSpace, R registers,81                                          pint_t cfa, PrologInfo &prolog);82#endif83};84 85template <typename R>86auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {87  return r.getWCookie();88}89template <typename R> uint64_t getSparcWCookie(const R &, long) {90  return 0;91}92 93template <typename A, typename R>94typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(95    A &addressSpace, const R &registers, pint_t cfa,96    const RegisterLocation &savedReg) {97  switch (savedReg.location) {98  case CFI_Parser<A>::kRegisterInCFA:99    return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);100 101  case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific102    return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^103           getSparcWCookie(registers, 0));104 105  case CFI_Parser<A>::kRegisterAtExpression:106    return (pint_t)addressSpace.getRegister(evaluateExpression(107        (pint_t)savedReg.value, addressSpace, registers, cfa));108 109  case CFI_Parser<A>::kRegisterIsExpression:110    return evaluateExpression((pint_t)savedReg.value, addressSpace,111                              registers, cfa);112 113  case CFI_Parser<A>::kRegisterInRegister:114    return registers.getRegister((int)savedReg.value);115  case CFI_Parser<A>::kRegisterUndefined:116    return 0;117  case CFI_Parser<A>::kRegisterUnused:118  case CFI_Parser<A>::kRegisterOffsetFromCFA:119    // FIX ME120    break;121  }122  _LIBUNWIND_ABORT("unsupported restore location for register");123}124 125template <typename A, typename R>126double DwarfInstructions<A, R>::getSavedFloatRegister(127    A &addressSpace, const R &registers, pint_t cfa,128    const RegisterLocation &savedReg) {129  switch (savedReg.location) {130  case CFI_Parser<A>::kRegisterInCFA:131    return addressSpace.getDouble(cfa + (pint_t)savedReg.value);132 133  case CFI_Parser<A>::kRegisterAtExpression:134    return addressSpace.getDouble(135        evaluateExpression((pint_t)savedReg.value, addressSpace,136                            registers, cfa));137  case CFI_Parser<A>::kRegisterUndefined:138    return 0.0;139  case CFI_Parser<A>::kRegisterInRegister:140#ifndef _LIBUNWIND_TARGET_ARM141    return registers.getFloatRegister((int)savedReg.value);142#endif143  case CFI_Parser<A>::kRegisterIsExpression:144  case CFI_Parser<A>::kRegisterUnused:145  case CFI_Parser<A>::kRegisterOffsetFromCFA:146  case CFI_Parser<A>::kRegisterInCFADecrypt:147    // FIX ME148    break;149  }150  _LIBUNWIND_ABORT("unsupported restore location for float register");151}152 153template <typename A, typename R>154v128 DwarfInstructions<A, R>::getSavedVectorRegister(155    A &addressSpace, const R &registers, pint_t cfa,156    const RegisterLocation &savedReg) {157  switch (savedReg.location) {158  case CFI_Parser<A>::kRegisterInCFA:159    return addressSpace.getVector(cfa + (pint_t)savedReg.value);160 161  case CFI_Parser<A>::kRegisterAtExpression:162    return addressSpace.getVector(163        evaluateExpression((pint_t)savedReg.value, addressSpace,164                            registers, cfa));165 166  case CFI_Parser<A>::kRegisterIsExpression:167  case CFI_Parser<A>::kRegisterUnused:168  case CFI_Parser<A>::kRegisterUndefined:169  case CFI_Parser<A>::kRegisterOffsetFromCFA:170  case CFI_Parser<A>::kRegisterInRegister:171  case CFI_Parser<A>::kRegisterInCFADecrypt:172    // FIX ME173    break;174  }175  _LIBUNWIND_ABORT("unsupported restore location for vector register");176}177#if defined(_LIBUNWIND_TARGET_AARCH64)178template <typename A, typename R>179bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace,180                                                    R registers, pint_t cfa,181                                                    PrologInfo &prolog) {182  pint_t raSignState;183  auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];184  if (regloc.location == CFI_Parser<A>::kRegisterUnused)185    raSignState = static_cast<pint_t>(regloc.value);186  else187    raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);188 189  // Only bit[0] is meaningful.190  return raSignState & 0x01;191}192 193template <typename A, typename R>194bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,195                                                          R registers,196                                                          pint_t cfa,197                                                          PrologInfo &prolog) {198  pint_t raSignState;199  auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];200  if (regloc.location == CFI_Parser<A>::kRegisterUnused)201    raSignState = static_cast<pint_t>(regloc.value);202  else203    raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);204 205  // Only bit[1] is meaningful.206  return raSignState & 0x02;207}208#endif209 210template <typename A, typename R>211int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace,212                                           const typename R::link_reg_t &pc,213                                           pint_t fdeStart, R &registers,214                                           bool &isSignalFrame, bool stage2) {215  FDE_Info fdeInfo;216  CIE_Info cieInfo;217  if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,218                               &cieInfo) == NULL) {219    PrologInfo prolog;220    if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,221                                            R::getArch(), &prolog)) {222      // get pointer to cfa (architecture specific)223      pint_t cfa = getCFA(addressSpace, prolog, registers);224 225      (void)stage2;226      // __unw_step_stage2 is not used for cross unwinding, so we use227      // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are228      // building for AArch64 natively.229#if defined(__aarch64__)230      if (stage2 && cieInfo.mteTaggedFrame) {231        pint_t sp = registers.getSP();232        pint_t p = sp;233        // AArch64 doesn't require the value of SP to be 16-byte aligned at234        // all times, only at memory accesses and public interfaces [1]. Thus,235        // a signal could arrive at a point where SP is not aligned properly.236        // In that case, the kernel fixes up [2] the signal frame, but we237        // still have a misaligned SP in the previous frame. If that signal238        // handler caused stack unwinding, we would have an unaligned SP.239        // We do not need to fix up the CFA, as that is the SP at a "public240        // interface".241        // [1]:242        // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack243        // [2]:244        // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718245        p &= ~0xfULL;246        // CFA is the bottom of the current stack frame.247        for (; p < cfa; p += 16) {248          __asm__ __volatile__(".arch armv8.5-a\n"249                               ".arch_extension memtag\n"250                               "stg %[Ptr], [%[Ptr]]\n"251                               :252                               : [Ptr] "r"(p)253                               : "memory");254        }255      }256#endif257      // restore registers that DWARF says were saved258      R newRegisters = registers;259 260      // Typically, the CFA is the stack pointer at the call site in261      // the previous frame. However, there are scenarios in which this is not262      // true. For example, if we switched to a new stack. In that case, the263      // value of the previous SP might be indicated by a CFI directive.264      //265      // We set the SP here to the CFA, allowing for it to be overridden266      // by a CFI directive later on.267      newRegisters.setSP(cfa);268 269      typename R::reg_t returnAddress = 0;270      constexpr int lastReg = R::lastDwarfRegNum();271      static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=272                        lastReg,273                    "register range too large");274      assert(lastReg >= (int)cieInfo.returnAddressRegister &&275             "register range does not contain return address register");276      for (int i = 0; i <= lastReg; ++i) {277        if (prolog.savedRegisters[i].location !=278            CFI_Parser<A>::kRegisterUnused) {279          if (registers.validFloatRegister(i))280            newRegisters.setFloatRegister(281                i, getSavedFloatRegister(addressSpace, registers, cfa,282                                         prolog.savedRegisters[i]));283          else if (registers.validVectorRegister(i))284            newRegisters.setVectorRegister(285                i, getSavedVectorRegister(addressSpace, registers, cfa,286                                          prolog.savedRegisters[i]));287          else if (i == (int)cieInfo.returnAddressRegister)288            returnAddress = getSavedRegister(addressSpace, registers, cfa,289                                             prolog.savedRegisters[i]);290          else if (registers.validRegister(i))291            newRegisters.setRegister(292                i, getSavedRegister(addressSpace, registers, cfa,293                                    prolog.savedRegisters[i]));294          else295            return UNW_EBADREG;296        } else if (i == (int)cieInfo.returnAddressRegister) {297            // Leaf function keeps the return address in register and there is no298            // explicit instructions how to restore it.299            returnAddress = registers.getRegister(cieInfo.returnAddressRegister);300        }301      }302 303      isSignalFrame = cieInfo.isSignalFrame;304 305#if defined(_LIBUNWIND_TARGET_AARCH64) &&                                      \306    !defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)307      // There are two ways of return address signing: pac-ret (enabled via308      // -mbranch-protection=pac-ret) and ptrauth-returns (enabled as part of309      // Apple's arm64e or experimental pauthtest ABI on Linux). The code310      // below handles signed RA for pac-ret, while ptrauth-returns uses311      // different logic.312      // TODO: unify logic for both cases, see313      // https://github.com/llvm/llvm-project/issues/160110314      //315      // If the target is aarch64 then the return address may have been signed316      // using the v8.3 pointer authentication extensions. The original317      // return address needs to be authenticated before the return address is318      // restored. autia1716 is used instead of autia as autia1716 assembles319      // to a NOP on pre-v8.3a architectures.320      if ((R::getArch() == REGISTERS_ARM64) &&321          isReturnAddressSigned(addressSpace, registers, cfa, prolog) &&322          returnAddress != 0) {323#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)324        return UNW_ECROSSRASIGNING;325#else326        register unsigned long long x17 __asm("x17") = returnAddress;327        register unsigned long long x16 __asm("x16") = cfa;328 329        // We use the hint versions of the authentication instructions below to330        // ensure they're assembled by the compiler even for targets with no331        // FEAT_PAuth/FEAT_PAuth_LR support.332        if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) {333          register unsigned long long x15 __asm("x15") =334              prolog.ptrAuthDiversifier;335          if (cieInfo.addressesSignedWithBKey) {336            asm("hint 0x27\n\t" // pacm337                "hint 0xe"338                : "+r"(x17)339                : "r"(x16), "r"(x15)); // autib1716340          } else {341            asm("hint 0x27\n\t" // pacm342                "hint 0xc"343                : "+r"(x17)344                : "r"(x16), "r"(x15)); // autia1716345          }346        } else {347          if (cieInfo.addressesSignedWithBKey)348            asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716349          else350            asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716351        }352        returnAddress = x17;353#endif354      }355#endif356 357#if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) &&    \358    defined(__ARM_FEATURE_PAUTH)359      if ((R::getArch() == REGISTERS_ARM) &&360          prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE].value) {361        pint_t pac =362            getSavedRegister(addressSpace, registers, cfa,363                             prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE]);364        __asm__ __volatile__("autg %0, %1, %2"365                             :366                             : "r"(pac), "r"(returnAddress), "r"(cfa)367                             :);368      }369#endif370 371#if defined(_LIBUNWIND_TARGET_SPARC)372      if (R::getArch() == REGISTERS_SPARC) {373        // Skip call site instruction and delay slot374        returnAddress += 8;375        // Skip unimp instruction if function returns a struct376        if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)377          returnAddress += 4;378      }379#endif380 381#if defined(_LIBUNWIND_TARGET_SPARC64)382      // Skip call site instruction and delay slot.383      if (R::getArch() == REGISTERS_SPARC64)384        returnAddress += 8;385#endif386 387#if defined(_LIBUNWIND_TARGET_PPC64)388#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)389#define PPC64_ELFV1_R2_OFFSET 40390#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)391#define PPC64_ELFV2_R2_OFFSET 24392      // If the instruction at return address is a TOC (r2) restore,393      // then r2 was saved and needs to be restored.394      // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,395      // while in ELFv1 ABI it is saved at SP + 40.396      if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {397        pint_t sp = newRegisters.getRegister(UNW_REG_SP);398        pint_t r2 = 0;399        switch (addressSpace.get32(returnAddress)) {400        case PPC64_ELFV1_R2_LOAD_INST_ENCODING:401          r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);402          break;403        case PPC64_ELFV2_R2_LOAD_INST_ENCODING:404          r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);405          break;406        }407        if (r2)408          newRegisters.setRegister(UNW_PPC64_R2, r2);409      }410#endif411 412      // Return address is address after call site instruction, so setting IP to413      // that does simulates a return.414      newRegisters.setIP(returnAddress);415 416      // Simulate the step by replacing the register set with the new ones.417      registers = newRegisters;418 419      return UNW_STEP_SUCCESS;420    }421  }422  return UNW_EBADFRAME;423}424 425template <typename A, typename R>426typename A::pint_t427DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,428                                            const R &registers,429                                            pint_t initialStackValue) {430  const bool log = false;431  pint_t p = expression;432  pint_t expressionEnd = expression + 20; // temp, until len read433  pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);434  expressionEnd = p + length;435  if (log)436    fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",437            (uint64_t)length);438  pint_t stack[100];439  pint_t *sp = stack;440  *(++sp) = initialStackValue;441 442  while (p < expressionEnd) {443    if (log) {444      for (pint_t *t = sp; t > stack; --t) {445        fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));446      }447    }448    uint8_t opcode = addressSpace.get8(p++);449    sint_t svalue, svalue2;450    pint_t value;451    uint32_t reg;452    switch (opcode) {453    case DW_OP_addr:454      // push immediate address sized value455      value = addressSpace.getP(p);456      p += sizeof(pint_t);457      *(++sp) = value;458      if (log)459        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);460      break;461 462    case DW_OP_deref:463      // pop stack, dereference, push result464      value = *sp--;465      *(++sp) = addressSpace.getP(value);466      if (log)467        fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);468      break;469 470    case DW_OP_const1u:471      // push immediate 1 byte value472      value = addressSpace.get8(p);473      p += 1;474      *(++sp) = value;475      if (log)476        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);477      break;478 479    case DW_OP_const1s:480      // push immediate 1 byte signed value481      svalue = (int8_t) addressSpace.get8(p);482      p += 1;483      *(++sp) = (pint_t)svalue;484      if (log)485        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);486      break;487 488    case DW_OP_const2u:489      // push immediate 2 byte value490      value = addressSpace.get16(p);491      p += 2;492      *(++sp) = value;493      if (log)494        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);495      break;496 497    case DW_OP_const2s:498      // push immediate 2 byte signed value499      svalue = (int16_t) addressSpace.get16(p);500      p += 2;501      *(++sp) = (pint_t)svalue;502      if (log)503        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);504      break;505 506    case DW_OP_const4u:507      // push immediate 4 byte value508      value = addressSpace.get32(p);509      p += 4;510      *(++sp) = value;511      if (log)512        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);513      break;514 515    case DW_OP_const4s:516      // push immediate 4 byte signed value517      svalue = (int32_t)addressSpace.get32(p);518      p += 4;519      *(++sp) = (pint_t)svalue;520      if (log)521        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);522      break;523 524    case DW_OP_const8u:525      // push immediate 8 byte value526      value = (pint_t)addressSpace.get64(p);527      p += 8;528      *(++sp) = value;529      if (log)530        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);531      break;532 533    case DW_OP_const8s:534      // push immediate 8 byte signed value535      value = (pint_t)addressSpace.get64(p);536      p += 8;537      *(++sp) = value;538      if (log)539        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);540      break;541 542    case DW_OP_constu:543      // push immediate ULEB128 value544      value = (pint_t)addressSpace.getULEB128(p, expressionEnd);545      *(++sp) = value;546      if (log)547        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);548      break;549 550    case DW_OP_consts:551      // push immediate SLEB128 value552      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);553      *(++sp) = (pint_t)svalue;554      if (log)555        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);556      break;557 558    case DW_OP_dup:559      // push top of stack560      value = *sp;561      *(++sp) = value;562      if (log)563        fprintf(stderr, "duplicate top of stack\n");564      break;565 566    case DW_OP_drop:567      // pop568      --sp;569      if (log)570        fprintf(stderr, "pop top of stack\n");571      break;572 573    case DW_OP_over:574      // dup second575      value = sp[-1];576      *(++sp) = value;577      if (log)578        fprintf(stderr, "duplicate second in stack\n");579      break;580 581    case DW_OP_pick:582      // pick from583      reg = addressSpace.get8(p);584      p += 1;585      value = sp[-(int)reg];586      *(++sp) = value;587      if (log)588        fprintf(stderr, "duplicate %d in stack\n", reg);589      break;590 591    case DW_OP_swap:592      // swap top two593      value = sp[0];594      sp[0] = sp[-1];595      sp[-1] = value;596      if (log)597        fprintf(stderr, "swap top of stack\n");598      break;599 600    case DW_OP_rot:601      // rotate top three602      value = sp[0];603      sp[0] = sp[-1];604      sp[-1] = sp[-2];605      sp[-2] = value;606      if (log)607        fprintf(stderr, "rotate top three of stack\n");608      break;609 610    case DW_OP_xderef:611      // pop stack, dereference, push result612      value = *sp--;613      *sp = *((pint_t*)value);614      if (log)615        fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);616      break;617 618    case DW_OP_abs:619      svalue = (sint_t)*sp;620      if (svalue < 0)621        *sp = (pint_t)(-svalue);622      if (log)623        fprintf(stderr, "abs\n");624      break;625 626    case DW_OP_and:627      value = *sp--;628      *sp &= value;629      if (log)630        fprintf(stderr, "and\n");631      break;632 633    case DW_OP_div:634      svalue = (sint_t)(*sp--);635      svalue2 = (sint_t)*sp;636      *sp = (pint_t)(svalue2 / svalue);637      if (log)638        fprintf(stderr, "div\n");639      break;640 641    case DW_OP_minus:642      value = *sp--;643      *sp = *sp - value;644      if (log)645        fprintf(stderr, "minus\n");646      break;647 648    case DW_OP_mod:649      svalue = (sint_t)(*sp--);650      svalue2 = (sint_t)*sp;651      *sp = (pint_t)(svalue2 % svalue);652      if (log)653        fprintf(stderr, "module\n");654      break;655 656    case DW_OP_mul:657      svalue = (sint_t)(*sp--);658      svalue2 = (sint_t)*sp;659      *sp = (pint_t)(svalue2 * svalue);660      if (log)661        fprintf(stderr, "mul\n");662      break;663 664    case DW_OP_neg:665      *sp = 0 - *sp;666      if (log)667        fprintf(stderr, "neg\n");668      break;669 670    case DW_OP_not:671      svalue = (sint_t)(*sp);672      *sp = (pint_t)(~svalue);673      if (log)674        fprintf(stderr, "not\n");675      break;676 677    case DW_OP_or:678      value = *sp--;679      *sp |= value;680      if (log)681        fprintf(stderr, "or\n");682      break;683 684    case DW_OP_plus:685      value = *sp--;686      *sp += value;687      if (log)688        fprintf(stderr, "plus\n");689      break;690 691    case DW_OP_plus_uconst:692      // pop stack, add uelb128 constant, push result693      *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));694      if (log)695        fprintf(stderr, "add constant\n");696      break;697 698    case DW_OP_shl:699      value = *sp--;700      *sp = *sp << value;701      if (log)702        fprintf(stderr, "shift left\n");703      break;704 705    case DW_OP_shr:706      value = *sp--;707      *sp = *sp >> value;708      if (log)709        fprintf(stderr, "shift left\n");710      break;711 712    case DW_OP_shra:713      value = *sp--;714      svalue = (sint_t)*sp;715      *sp = (pint_t)(svalue >> value);716      if (log)717        fprintf(stderr, "shift left arithmetic\n");718      break;719 720    case DW_OP_xor:721      value = *sp--;722      *sp ^= value;723      if (log)724        fprintf(stderr, "xor\n");725      break;726 727    case DW_OP_skip:728      svalue = (int16_t) addressSpace.get16(p);729      p += 2;730      p = (pint_t)((sint_t)p + svalue);731      if (log)732        fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);733      break;734 735    case DW_OP_bra:736      svalue = (int16_t) addressSpace.get16(p);737      p += 2;738      if (*sp--)739        p = (pint_t)((sint_t)p + svalue);740      if (log)741        fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);742      break;743 744    case DW_OP_eq:745      value = *sp--;746      *sp = (*sp == value);747      if (log)748        fprintf(stderr, "eq\n");749      break;750 751    case DW_OP_ge:752      value = *sp--;753      *sp = (*sp >= value);754      if (log)755        fprintf(stderr, "ge\n");756      break;757 758    case DW_OP_gt:759      value = *sp--;760      *sp = (*sp > value);761      if (log)762        fprintf(stderr, "gt\n");763      break;764 765    case DW_OP_le:766      value = *sp--;767      *sp = (*sp <= value);768      if (log)769        fprintf(stderr, "le\n");770      break;771 772    case DW_OP_lt:773      value = *sp--;774      *sp = (*sp < value);775      if (log)776        fprintf(stderr, "lt\n");777      break;778 779    case DW_OP_ne:780      value = *sp--;781      *sp = (*sp != value);782      if (log)783        fprintf(stderr, "ne\n");784      break;785 786    case DW_OP_lit0:787    case DW_OP_lit1:788    case DW_OP_lit2:789    case DW_OP_lit3:790    case DW_OP_lit4:791    case DW_OP_lit5:792    case DW_OP_lit6:793    case DW_OP_lit7:794    case DW_OP_lit8:795    case DW_OP_lit9:796    case DW_OP_lit10:797    case DW_OP_lit11:798    case DW_OP_lit12:799    case DW_OP_lit13:800    case DW_OP_lit14:801    case DW_OP_lit15:802    case DW_OP_lit16:803    case DW_OP_lit17:804    case DW_OP_lit18:805    case DW_OP_lit19:806    case DW_OP_lit20:807    case DW_OP_lit21:808    case DW_OP_lit22:809    case DW_OP_lit23:810    case DW_OP_lit24:811    case DW_OP_lit25:812    case DW_OP_lit26:813    case DW_OP_lit27:814    case DW_OP_lit28:815    case DW_OP_lit29:816    case DW_OP_lit30:817    case DW_OP_lit31:818      value = static_cast<pint_t>(opcode - DW_OP_lit0);819      *(++sp) = value;820      if (log)821        fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);822      break;823 824    case DW_OP_reg0:825    case DW_OP_reg1:826    case DW_OP_reg2:827    case DW_OP_reg3:828    case DW_OP_reg4:829    case DW_OP_reg5:830    case DW_OP_reg6:831    case DW_OP_reg7:832    case DW_OP_reg8:833    case DW_OP_reg9:834    case DW_OP_reg10:835    case DW_OP_reg11:836    case DW_OP_reg12:837    case DW_OP_reg13:838    case DW_OP_reg14:839    case DW_OP_reg15:840    case DW_OP_reg16:841    case DW_OP_reg17:842    case DW_OP_reg18:843    case DW_OP_reg19:844    case DW_OP_reg20:845    case DW_OP_reg21:846    case DW_OP_reg22:847    case DW_OP_reg23:848    case DW_OP_reg24:849    case DW_OP_reg25:850    case DW_OP_reg26:851    case DW_OP_reg27:852    case DW_OP_reg28:853    case DW_OP_reg29:854    case DW_OP_reg30:855    case DW_OP_reg31:856      reg = static_cast<uint32_t>(opcode - DW_OP_reg0);857      *(++sp) = registers.getRegister((int)reg);858      if (log)859        fprintf(stderr, "push reg %d\n", reg);860      break;861 862    case DW_OP_regx:863      reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));864      *(++sp) = registers.getRegister((int)reg);865      if (log)866        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);867      break;868 869    case DW_OP_breg0:870    case DW_OP_breg1:871    case DW_OP_breg2:872    case DW_OP_breg3:873    case DW_OP_breg4:874    case DW_OP_breg5:875    case DW_OP_breg6:876    case DW_OP_breg7:877    case DW_OP_breg8:878    case DW_OP_breg9:879    case DW_OP_breg10:880    case DW_OP_breg11:881    case DW_OP_breg12:882    case DW_OP_breg13:883    case DW_OP_breg14:884    case DW_OP_breg15:885    case DW_OP_breg16:886    case DW_OP_breg17:887    case DW_OP_breg18:888    case DW_OP_breg19:889    case DW_OP_breg20:890    case DW_OP_breg21:891    case DW_OP_breg22:892    case DW_OP_breg23:893    case DW_OP_breg24:894    case DW_OP_breg25:895    case DW_OP_breg26:896    case DW_OP_breg27:897    case DW_OP_breg28:898    case DW_OP_breg29:899    case DW_OP_breg30:900    case DW_OP_breg31:901      reg = static_cast<uint32_t>(opcode - DW_OP_breg0);902      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);903      svalue += static_cast<sint_t>(registers.getRegister((int)reg));904      *(++sp) = (pint_t)(svalue);905      if (log)906        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);907      break;908 909    case DW_OP_bregx:910      reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));911      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);912      svalue += static_cast<sint_t>(registers.getRegister((int)reg));913      *(++sp) = (pint_t)(svalue);914      if (log)915        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);916      break;917 918    case DW_OP_fbreg:919      _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");920      break;921 922    case DW_OP_piece:923      _LIBUNWIND_ABORT("DW_OP_piece not implemented");924      break;925 926    case DW_OP_deref_size:927      // pop stack, dereference, push result928      value = *sp--;929      switch (addressSpace.get8(p++)) {930      case 1:931        value = addressSpace.get8(value);932        break;933      case 2:934        value = addressSpace.get16(value);935        break;936      case 4:937        value = addressSpace.get32(value);938        break;939      case 8:940        value = (pint_t)addressSpace.get64(value);941        break;942      default:943        _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");944      }945      *(++sp) = value;946      if (log)947        fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);948      break;949 950    case DW_OP_xderef_size:951    case DW_OP_nop:952    case DW_OP_push_object_addres:953    case DW_OP_call2:954    case DW_OP_call4:955    case DW_OP_call_ref:956    default:957      _LIBUNWIND_ABORT("DWARF opcode not implemented");958    }959 960  }961  if (log)962    fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);963  return *sp;964}965 966 967 968} // namespace libunwind969 970#endif // __DWARF_INSTRUCTIONS_HPP__971