Path: blob/master/libs/unwind/src/DwarfInstructions.hpp
12346 views
//===-------------------------- DwarfInstructions.hpp ---------------------===//1//2// The LLVM Compiler Infrastructure3//4// This file is dual licensed under the MIT and the University of Illinois Open5// Source Licenses. See LICENSE.TXT for details.6//7//8// Processor specific interpretation of DWARF unwind info.9//10//===----------------------------------------------------------------------===//1112#ifndef __DWARF_INSTRUCTIONS_HPP__13#define __DWARF_INSTRUCTIONS_HPP__1415#include <stdint.h>16#include <stdio.h>17#include <stdlib.h>1819#include "dwarf2.h"20#include "Registers.hpp"21#include "DwarfParser.hpp"22#include "config.h"232425namespace libunwind {262728/// DwarfInstructions maps abtract DWARF unwind instructions to a particular29/// architecture30template <typename A, typename R>31class DwarfInstructions {32public:33typedef typename A::pint_t pint_t;34typedef typename A::sint_t sint_t;3536static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,37R ®isters);3839private:4041enum {42DW_X86_64_RET_ADDR = 1643};4445enum {46DW_X86_RET_ADDR = 847};4849typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;50typedef typename CFI_Parser<A>::PrologInfo PrologInfo;51typedef typename CFI_Parser<A>::FDE_Info FDE_Info;52typedef typename CFI_Parser<A>::CIE_Info CIE_Info;5354static pint_t evaluateExpression(pint_t expression, A &addressSpace,55const R ®isters,56pint_t initialStackValue);57static pint_t getSavedRegister(A &addressSpace, const R ®isters,58pint_t cfa, const RegisterLocation &savedReg);59static double getSavedFloatRegister(A &addressSpace, const R ®isters,60pint_t cfa, const RegisterLocation &savedReg);61static v128 getSavedVectorRegister(A &addressSpace, const R ®isters,62pint_t cfa, const RegisterLocation &savedReg);6364static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,65const R ®isters) {66if (prolog.cfaRegister != 0)67return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +68prolog.cfaRegisterOffset);69if (prolog.cfaExpression != 0)70return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,71registers, 0);72assert(0 && "getCFA(): unknown location");73__builtin_unreachable();74}75};767778template <typename A, typename R>79typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(80A &addressSpace, const R ®isters, pint_t cfa,81const RegisterLocation &savedReg) {82switch (savedReg.location) {83case CFI_Parser<A>::kRegisterInCFA:84return addressSpace.getRegister(cfa + (pint_t)savedReg.value);8586case CFI_Parser<A>::kRegisterAtExpression:87return addressSpace.getRegister(88evaluateExpression((pint_t)savedReg.value, addressSpace,89registers, cfa));9091case CFI_Parser<A>::kRegisterIsExpression:92return evaluateExpression((pint_t)savedReg.value, addressSpace,93registers, cfa);9495case CFI_Parser<A>::kRegisterInRegister:96return registers.getRegister((int)savedReg.value);9798case CFI_Parser<A>::kRegisterUnused:99case CFI_Parser<A>::kRegisterOffsetFromCFA:100// FIX ME101break;102}103_LIBUNWIND_ABORT("unsupported restore location for register");104}105106template <typename A, typename R>107double DwarfInstructions<A, R>::getSavedFloatRegister(108A &addressSpace, const R ®isters, pint_t cfa,109const RegisterLocation &savedReg) {110switch (savedReg.location) {111case CFI_Parser<A>::kRegisterInCFA:112return addressSpace.getDouble(cfa + (pint_t)savedReg.value);113114case CFI_Parser<A>::kRegisterAtExpression:115return addressSpace.getDouble(116evaluateExpression((pint_t)savedReg.value, addressSpace,117registers, cfa));118119case CFI_Parser<A>::kRegisterIsExpression:120case CFI_Parser<A>::kRegisterUnused:121case CFI_Parser<A>::kRegisterOffsetFromCFA:122case CFI_Parser<A>::kRegisterInRegister:123// FIX ME124break;125}126_LIBUNWIND_ABORT("unsupported restore location for float register");127}128129template <typename A, typename R>130v128 DwarfInstructions<A, R>::getSavedVectorRegister(131A &addressSpace, const R ®isters, pint_t cfa,132const RegisterLocation &savedReg) {133switch (savedReg.location) {134case CFI_Parser<A>::kRegisterInCFA:135return addressSpace.getVector(cfa + (pint_t)savedReg.value);136137case CFI_Parser<A>::kRegisterAtExpression:138return addressSpace.getVector(139evaluateExpression((pint_t)savedReg.value, addressSpace,140registers, cfa));141142case CFI_Parser<A>::kRegisterIsExpression:143case CFI_Parser<A>::kRegisterUnused:144case CFI_Parser<A>::kRegisterOffsetFromCFA:145case CFI_Parser<A>::kRegisterInRegister:146// FIX ME147break;148}149_LIBUNWIND_ABORT("unsupported restore location for vector register");150}151152template <typename A, typename R>153int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,154pint_t fdeStart, R ®isters) {155FDE_Info fdeInfo;156CIE_Info cieInfo;157if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,158&cieInfo) == NULL) {159PrologInfo prolog;160if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,161R::getArch(), &prolog)) {162// get pointer to cfa (architecture specific)163pint_t cfa = getCFA(addressSpace, prolog, registers);164165// restore registers that DWARF says were saved166R newRegisters = registers;167pint_t returnAddress = 0;168const int lastReg = R::lastDwarfRegNum();169assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&170"register range too large");171assert(lastReg >= (int)cieInfo.returnAddressRegister &&172"register range does not contain return address register");173for (int i = 0; i <= lastReg; ++i) {174if (prolog.savedRegisters[i].location !=175CFI_Parser<A>::kRegisterUnused) {176if (registers.validFloatRegister(i))177newRegisters.setFloatRegister(178i, getSavedFloatRegister(addressSpace, registers, cfa,179prolog.savedRegisters[i]));180else if (registers.validVectorRegister(i))181newRegisters.setVectorRegister(182i, getSavedVectorRegister(addressSpace, registers, cfa,183prolog.savedRegisters[i]));184else if (i == (int)cieInfo.returnAddressRegister)185returnAddress = getSavedRegister(addressSpace, registers, cfa,186prolog.savedRegisters[i]);187else if (registers.validRegister(i))188newRegisters.setRegister(189i, getSavedRegister(addressSpace, registers, cfa,190prolog.savedRegisters[i]));191else192return UNW_EBADREG;193}194}195196// By definition, the CFA is the stack pointer at the call site, so197// restoring SP means setting it to CFA.198newRegisters.setSP(cfa);199200#if defined(_LIBUNWIND_TARGET_AARCH64)201// If the target is aarch64 then the return address may have been signed202// using the v8.3 pointer authentication extensions. The original203// return address needs to be authenticated before the return address is204// restored. autia1716 is used instead of autia as autia1716 assembles205// to a NOP on pre-v8.3a architectures.206if ((R::getArch() == REGISTERS_ARM64) &&207prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {208#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)209return UNW_ECROSSRASIGNING;210#else211register unsigned long long x17 __asm("x17") = returnAddress;212register unsigned long long x16 __asm("x16") = cfa;213214// These are the autia1716/autib1716 instructions. The hint instructions215// are used here as gcc does not assemble autia1716/autib1716 for pre216// armv8.3a targets.217if (cieInfo.addressesSignedWithBKey)218asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716219else220asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716221returnAddress = x17;222#endif223}224#endif225226#if defined(_LIBUNWIND_TARGET_SPARC)227if (R::getArch() == REGISTERS_SPARC) {228// Skip call site instruction and delay slot229returnAddress += 8;230// Skip unimp instruction if function returns a struct231if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)232returnAddress += 4;233}234#endif235236#if defined(_LIBUNWIND_TARGET_PPC64)237#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)238#define PPC64_ELFV1_R2_OFFSET 40239#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)240#define PPC64_ELFV2_R2_OFFSET 24241// If the instruction at return address is a TOC (r2) restore,242// then r2 was saved and needs to be restored.243// ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,244// while in ELFv1 ABI it is saved at SP + 40.245if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {246pint_t sp = newRegisters.getRegister(UNW_REG_SP);247pint_t r2 = 0;248switch (addressSpace.get32(returnAddress)) {249case PPC64_ELFV1_R2_LOAD_INST_ENCODING:250r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);251break;252case PPC64_ELFV2_R2_LOAD_INST_ENCODING:253r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);254break;255}256if (r2)257newRegisters.setRegister(UNW_PPC64_R2, r2);258}259#endif260261// Return address is address after call site instruction, so setting IP to262// that does simualates a return.263newRegisters.setIP(returnAddress);264265// Simulate the step by replacing the register set with the new ones.266registers = newRegisters;267268return UNW_STEP_SUCCESS;269}270}271return UNW_EBADFRAME;272}273274template <typename A, typename R>275typename A::pint_t276DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,277const R ®isters,278pint_t initialStackValue) {279const bool log = false;280pint_t p = expression;281pint_t expressionEnd = expression + 20; // temp, until len read282pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);283expressionEnd = p + length;284if (log)285fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",286(uint64_t)length);287pint_t stack[100];288pint_t *sp = stack;289*(++sp) = initialStackValue;290291while (p < expressionEnd) {292if (log) {293for (pint_t *t = sp; t > stack; --t) {294fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));295}296}297uint8_t opcode = addressSpace.get8(p++);298sint_t svalue, svalue2;299pint_t value;300uint32_t reg;301switch (opcode) {302case DW_OP_addr:303// push immediate address sized value304value = addressSpace.getP(p);305p += sizeof(pint_t);306*(++sp) = value;307if (log)308fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);309break;310311case DW_OP_deref:312// pop stack, dereference, push result313value = *sp--;314*(++sp) = addressSpace.getP(value);315if (log)316fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);317break;318319case DW_OP_const1u:320// push immediate 1 byte value321value = addressSpace.get8(p);322p += 1;323*(++sp) = value;324if (log)325fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);326break;327328case DW_OP_const1s:329// push immediate 1 byte signed value330svalue = (int8_t) addressSpace.get8(p);331p += 1;332*(++sp) = (pint_t)svalue;333if (log)334fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);335break;336337case DW_OP_const2u:338// push immediate 2 byte value339value = addressSpace.get16(p);340p += 2;341*(++sp) = value;342if (log)343fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);344break;345346case DW_OP_const2s:347// push immediate 2 byte signed value348svalue = (int16_t) addressSpace.get16(p);349p += 2;350*(++sp) = (pint_t)svalue;351if (log)352fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);353break;354355case DW_OP_const4u:356// push immediate 4 byte value357value = addressSpace.get32(p);358p += 4;359*(++sp) = value;360if (log)361fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);362break;363364case DW_OP_const4s:365// push immediate 4 byte signed value366svalue = (int32_t)addressSpace.get32(p);367p += 4;368*(++sp) = (pint_t)svalue;369if (log)370fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);371break;372373case DW_OP_const8u:374// push immediate 8 byte value375value = (pint_t)addressSpace.get64(p);376p += 8;377*(++sp) = value;378if (log)379fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);380break;381382case DW_OP_const8s:383// push immediate 8 byte signed value384value = (pint_t)addressSpace.get64(p);385p += 8;386*(++sp) = value;387if (log)388fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);389break;390391case DW_OP_constu:392// push immediate ULEB128 value393value = (pint_t)addressSpace.getULEB128(p, expressionEnd);394*(++sp) = value;395if (log)396fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);397break;398399case DW_OP_consts:400// push immediate SLEB128 value401svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);402*(++sp) = (pint_t)svalue;403if (log)404fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);405break;406407case DW_OP_dup:408// push top of stack409value = *sp;410*(++sp) = value;411if (log)412fprintf(stderr, "duplicate top of stack\n");413break;414415case DW_OP_drop:416// pop417--sp;418if (log)419fprintf(stderr, "pop top of stack\n");420break;421422case DW_OP_over:423// dup second424value = sp[-1];425*(++sp) = value;426if (log)427fprintf(stderr, "duplicate second in stack\n");428break;429430case DW_OP_pick:431// pick from432reg = addressSpace.get8(p);433p += 1;434value = sp[-reg];435*(++sp) = value;436if (log)437fprintf(stderr, "duplicate %d in stack\n", reg);438break;439440case DW_OP_swap:441// swap top two442value = sp[0];443sp[0] = sp[-1];444sp[-1] = value;445if (log)446fprintf(stderr, "swap top of stack\n");447break;448449case DW_OP_rot:450// rotate top three451value = sp[0];452sp[0] = sp[-1];453sp[-1] = sp[-2];454sp[-2] = value;455if (log)456fprintf(stderr, "rotate top three of stack\n");457break;458459case DW_OP_xderef:460// pop stack, dereference, push result461value = *sp--;462*sp = *((pint_t*)value);463if (log)464fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);465break;466467case DW_OP_abs:468svalue = (sint_t)*sp;469if (svalue < 0)470*sp = (pint_t)(-svalue);471if (log)472fprintf(stderr, "abs\n");473break;474475case DW_OP_and:476value = *sp--;477*sp &= value;478if (log)479fprintf(stderr, "and\n");480break;481482case DW_OP_div:483svalue = (sint_t)(*sp--);484svalue2 = (sint_t)*sp;485*sp = (pint_t)(svalue2 / svalue);486if (log)487fprintf(stderr, "div\n");488break;489490case DW_OP_minus:491value = *sp--;492*sp = *sp - value;493if (log)494fprintf(stderr, "minus\n");495break;496497case DW_OP_mod:498svalue = (sint_t)(*sp--);499svalue2 = (sint_t)*sp;500*sp = (pint_t)(svalue2 % svalue);501if (log)502fprintf(stderr, "module\n");503break;504505case DW_OP_mul:506svalue = (sint_t)(*sp--);507svalue2 = (sint_t)*sp;508*sp = (pint_t)(svalue2 * svalue);509if (log)510fprintf(stderr, "mul\n");511break;512513case DW_OP_neg:514*sp = 0 - *sp;515if (log)516fprintf(stderr, "neg\n");517break;518519case DW_OP_not:520svalue = (sint_t)(*sp);521*sp = (pint_t)(~svalue);522if (log)523fprintf(stderr, "not\n");524break;525526case DW_OP_or:527value = *sp--;528*sp |= value;529if (log)530fprintf(stderr, "or\n");531break;532533case DW_OP_plus:534value = *sp--;535*sp += value;536if (log)537fprintf(stderr, "plus\n");538break;539540case DW_OP_plus_uconst:541// pop stack, add uelb128 constant, push result542*sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));543if (log)544fprintf(stderr, "add constant\n");545break;546547case DW_OP_shl:548value = *sp--;549*sp = *sp << value;550if (log)551fprintf(stderr, "shift left\n");552break;553554case DW_OP_shr:555value = *sp--;556*sp = *sp >> value;557if (log)558fprintf(stderr, "shift left\n");559break;560561case DW_OP_shra:562value = *sp--;563svalue = (sint_t)*sp;564*sp = (pint_t)(svalue >> value);565if (log)566fprintf(stderr, "shift left arithmetric\n");567break;568569case DW_OP_xor:570value = *sp--;571*sp ^= value;572if (log)573fprintf(stderr, "xor\n");574break;575576case DW_OP_skip:577svalue = (int16_t) addressSpace.get16(p);578p += 2;579p = (pint_t)((sint_t)p + svalue);580if (log)581fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);582break;583584case DW_OP_bra:585svalue = (int16_t) addressSpace.get16(p);586p += 2;587if (*sp--)588p = (pint_t)((sint_t)p + svalue);589if (log)590fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);591break;592593case DW_OP_eq:594value = *sp--;595*sp = (*sp == value);596if (log)597fprintf(stderr, "eq\n");598break;599600case DW_OP_ge:601value = *sp--;602*sp = (*sp >= value);603if (log)604fprintf(stderr, "ge\n");605break;606607case DW_OP_gt:608value = *sp--;609*sp = (*sp > value);610if (log)611fprintf(stderr, "gt\n");612break;613614case DW_OP_le:615value = *sp--;616*sp = (*sp <= value);617if (log)618fprintf(stderr, "le\n");619break;620621case DW_OP_lt:622value = *sp--;623*sp = (*sp < value);624if (log)625fprintf(stderr, "lt\n");626break;627628case DW_OP_ne:629value = *sp--;630*sp = (*sp != value);631if (log)632fprintf(stderr, "ne\n");633break;634635case DW_OP_lit0:636case DW_OP_lit1:637case DW_OP_lit2:638case DW_OP_lit3:639case DW_OP_lit4:640case DW_OP_lit5:641case DW_OP_lit6:642case DW_OP_lit7:643case DW_OP_lit8:644case DW_OP_lit9:645case DW_OP_lit10:646case DW_OP_lit11:647case DW_OP_lit12:648case DW_OP_lit13:649case DW_OP_lit14:650case DW_OP_lit15:651case DW_OP_lit16:652case DW_OP_lit17:653case DW_OP_lit18:654case DW_OP_lit19:655case DW_OP_lit20:656case DW_OP_lit21:657case DW_OP_lit22:658case DW_OP_lit23:659case DW_OP_lit24:660case DW_OP_lit25:661case DW_OP_lit26:662case DW_OP_lit27:663case DW_OP_lit28:664case DW_OP_lit29:665case DW_OP_lit30:666case DW_OP_lit31:667value = static_cast<pint_t>(opcode - DW_OP_lit0);668*(++sp) = value;669if (log)670fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);671break;672673case DW_OP_reg0:674case DW_OP_reg1:675case DW_OP_reg2:676case DW_OP_reg3:677case DW_OP_reg4:678case DW_OP_reg5:679case DW_OP_reg6:680case DW_OP_reg7:681case DW_OP_reg8:682case DW_OP_reg9:683case DW_OP_reg10:684case DW_OP_reg11:685case DW_OP_reg12:686case DW_OP_reg13:687case DW_OP_reg14:688case DW_OP_reg15:689case DW_OP_reg16:690case DW_OP_reg17:691case DW_OP_reg18:692case DW_OP_reg19:693case DW_OP_reg20:694case DW_OP_reg21:695case DW_OP_reg22:696case DW_OP_reg23:697case DW_OP_reg24:698case DW_OP_reg25:699case DW_OP_reg26:700case DW_OP_reg27:701case DW_OP_reg28:702case DW_OP_reg29:703case DW_OP_reg30:704case DW_OP_reg31:705reg = static_cast<uint32_t>(opcode - DW_OP_reg0);706*(++sp) = registers.getRegister((int)reg);707if (log)708fprintf(stderr, "push reg %d\n", reg);709break;710711case DW_OP_regx:712reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));713*(++sp) = registers.getRegister((int)reg);714if (log)715fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);716break;717718case DW_OP_breg0:719case DW_OP_breg1:720case DW_OP_breg2:721case DW_OP_breg3:722case DW_OP_breg4:723case DW_OP_breg5:724case DW_OP_breg6:725case DW_OP_breg7:726case DW_OP_breg8:727case DW_OP_breg9:728case DW_OP_breg10:729case DW_OP_breg11:730case DW_OP_breg12:731case DW_OP_breg13:732case DW_OP_breg14:733case DW_OP_breg15:734case DW_OP_breg16:735case DW_OP_breg17:736case DW_OP_breg18:737case DW_OP_breg19:738case DW_OP_breg20:739case DW_OP_breg21:740case DW_OP_breg22:741case DW_OP_breg23:742case DW_OP_breg24:743case DW_OP_breg25:744case DW_OP_breg26:745case DW_OP_breg27:746case DW_OP_breg28:747case DW_OP_breg29:748case DW_OP_breg30:749case DW_OP_breg31:750reg = static_cast<uint32_t>(opcode - DW_OP_breg0);751svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);752svalue += static_cast<sint_t>(registers.getRegister((int)reg));753*(++sp) = (pint_t)(svalue);754if (log)755fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);756break;757758case DW_OP_bregx:759reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));760svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);761svalue += static_cast<sint_t>(registers.getRegister((int)reg));762*(++sp) = (pint_t)(svalue);763if (log)764fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);765break;766767case DW_OP_fbreg:768_LIBUNWIND_ABORT("DW_OP_fbreg not implemented");769break;770771case DW_OP_piece:772_LIBUNWIND_ABORT("DW_OP_piece not implemented");773break;774775case DW_OP_deref_size:776// pop stack, dereference, push result777value = *sp--;778switch (addressSpace.get8(p++)) {779case 1:780value = addressSpace.get8(value);781break;782case 2:783value = addressSpace.get16(value);784break;785case 4:786value = addressSpace.get32(value);787break;788case 8:789value = (pint_t)addressSpace.get64(value);790break;791default:792_LIBUNWIND_ABORT("DW_OP_deref_size with bad size");793}794*(++sp) = value;795if (log)796fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);797break;798799case DW_OP_xderef_size:800case DW_OP_nop:801case DW_OP_push_object_addres:802case DW_OP_call2:803case DW_OP_call4:804case DW_OP_call_ref:805default:806_LIBUNWIND_ABORT("DWARF opcode not implemented");807}808809}810if (log)811fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);812return *sp;813}814815816817} // namespace libunwind818819#endif // __DWARF_INSTRUCTIONS_HPP__820821822