Path: blob/main/contrib/llvm-project/libunwind/src/DwarfInstructions.hpp
35154 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//7// Processor specific interpretation of DWARF unwind info.8//9//===----------------------------------------------------------------------===//1011#ifndef __DWARF_INSTRUCTIONS_HPP__12#define __DWARF_INSTRUCTIONS_HPP__1314#include <stdint.h>15#include <stdio.h>16#include <stdlib.h>1718#include "DwarfParser.hpp"19#include "Registers.hpp"20#include "config.h"21#include "dwarf2.h"22#include "libunwind_ext.h"232425namespace libunwind {262728/// DwarfInstructions maps abstract 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, bool &isSignalFrame, bool stage2);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#if defined(_LIBUNWIND_TARGET_AARCH64)76static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa,77PrologInfo &prolog);78#endif79};8081template <typename R>82auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {83return r.getWCookie();84}85template <typename R> uint64_t getSparcWCookie(const R &, long) {86return 0;87}8889template <typename A, typename R>90typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(91A &addressSpace, const R ®isters, pint_t cfa,92const RegisterLocation &savedReg) {93switch (savedReg.location) {94case CFI_Parser<A>::kRegisterInCFA:95return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);9697case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific98return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^99getSparcWCookie(registers, 0));100101case CFI_Parser<A>::kRegisterAtExpression:102return (pint_t)addressSpace.getRegister(evaluateExpression(103(pint_t)savedReg.value, addressSpace, registers, cfa));104105case CFI_Parser<A>::kRegisterIsExpression:106return evaluateExpression((pint_t)savedReg.value, addressSpace,107registers, cfa);108109case CFI_Parser<A>::kRegisterInRegister:110return registers.getRegister((int)savedReg.value);111112case CFI_Parser<A>::kRegisterUnused:113case CFI_Parser<A>::kRegisterOffsetFromCFA:114// FIX ME115break;116}117_LIBUNWIND_ABORT("unsupported restore location for register");118}119120template <typename A, typename R>121double DwarfInstructions<A, R>::getSavedFloatRegister(122A &addressSpace, const R ®isters, pint_t cfa,123const RegisterLocation &savedReg) {124switch (savedReg.location) {125case CFI_Parser<A>::kRegisterInCFA:126return addressSpace.getDouble(cfa + (pint_t)savedReg.value);127128case CFI_Parser<A>::kRegisterAtExpression:129return addressSpace.getDouble(130evaluateExpression((pint_t)savedReg.value, addressSpace,131registers, cfa));132case CFI_Parser<A>::kRegisterInRegister:133#ifndef _LIBUNWIND_TARGET_ARM134return registers.getFloatRegister((int)savedReg.value);135#endif136case CFI_Parser<A>::kRegisterIsExpression:137case CFI_Parser<A>::kRegisterUnused:138case CFI_Parser<A>::kRegisterOffsetFromCFA:139case CFI_Parser<A>::kRegisterInCFADecrypt:140// FIX ME141break;142}143_LIBUNWIND_ABORT("unsupported restore location for float register");144}145146template <typename A, typename R>147v128 DwarfInstructions<A, R>::getSavedVectorRegister(148A &addressSpace, const R ®isters, pint_t cfa,149const RegisterLocation &savedReg) {150switch (savedReg.location) {151case CFI_Parser<A>::kRegisterInCFA:152return addressSpace.getVector(cfa + (pint_t)savedReg.value);153154case CFI_Parser<A>::kRegisterAtExpression:155return addressSpace.getVector(156evaluateExpression((pint_t)savedReg.value, addressSpace,157registers, cfa));158159case CFI_Parser<A>::kRegisterIsExpression:160case CFI_Parser<A>::kRegisterUnused:161case CFI_Parser<A>::kRegisterOffsetFromCFA:162case CFI_Parser<A>::kRegisterInRegister:163case CFI_Parser<A>::kRegisterInCFADecrypt:164// FIX ME165break;166}167_LIBUNWIND_ABORT("unsupported restore location for vector register");168}169#if defined(_LIBUNWIND_TARGET_AARCH64)170template <typename A, typename R>171bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,172pint_t cfa, PrologInfo &prolog) {173pint_t raSignState;174auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];175if (regloc.location == CFI_Parser<A>::kRegisterUnused)176raSignState = static_cast<pint_t>(regloc.value);177else178raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);179180// Only bit[0] is meaningful.181return raSignState & 0x01;182}183#endif184185template <typename A, typename R>186int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,187pint_t fdeStart, R ®isters,188bool &isSignalFrame, bool stage2) {189FDE_Info fdeInfo;190CIE_Info cieInfo;191if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,192&cieInfo) == NULL) {193PrologInfo prolog;194if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,195R::getArch(), &prolog)) {196// get pointer to cfa (architecture specific)197pint_t cfa = getCFA(addressSpace, prolog, registers);198199(void)stage2;200// __unw_step_stage2 is not used for cross unwinding, so we use201// __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are202// building for AArch64 natively.203#if defined(__aarch64__)204if (stage2 && cieInfo.mteTaggedFrame) {205pint_t sp = registers.getSP();206pint_t p = sp;207// AArch64 doesn't require the value of SP to be 16-byte aligned at208// all times, only at memory accesses and public interfaces [1]. Thus,209// a signal could arrive at a point where SP is not aligned properly.210// In that case, the kernel fixes up [2] the signal frame, but we211// still have a misaligned SP in the previous frame. If that signal212// handler caused stack unwinding, we would have an unaligned SP.213// We do not need to fix up the CFA, as that is the SP at a "public214// interface".215// [1]:216// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack217// [2]:218// https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718219p &= ~0xfULL;220// CFA is the bottom of the current stack frame.221for (; p < cfa; p += 16) {222__asm__ __volatile__(".arch armv8.5-a\n"223".arch_extension memtag\n"224"stg %[Ptr], [%[Ptr]]\n"225:226: [Ptr] "r"(p)227: "memory");228}229}230#endif231// restore registers that DWARF says were saved232R newRegisters = registers;233234// Typically, the CFA is the stack pointer at the call site in235// the previous frame. However, there are scenarios in which this is not236// true. For example, if we switched to a new stack. In that case, the237// value of the previous SP might be indicated by a CFI directive.238//239// We set the SP here to the CFA, allowing for it to be overridden240// by a CFI directive later on.241newRegisters.setSP(cfa);242243pint_t returnAddress = 0;244constexpr int lastReg = R::lastDwarfRegNum();245static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=246lastReg,247"register range too large");248assert(lastReg >= (int)cieInfo.returnAddressRegister &&249"register range does not contain return address register");250for (int i = 0; i <= lastReg; ++i) {251if (prolog.savedRegisters[i].location !=252CFI_Parser<A>::kRegisterUnused) {253if (registers.validFloatRegister(i))254newRegisters.setFloatRegister(255i, getSavedFloatRegister(addressSpace, registers, cfa,256prolog.savedRegisters[i]));257else if (registers.validVectorRegister(i))258newRegisters.setVectorRegister(259i, getSavedVectorRegister(addressSpace, registers, cfa,260prolog.savedRegisters[i]));261else if (i == (int)cieInfo.returnAddressRegister)262returnAddress = getSavedRegister(addressSpace, registers, cfa,263prolog.savedRegisters[i]);264else if (registers.validRegister(i))265newRegisters.setRegister(266i, getSavedRegister(addressSpace, registers, cfa,267prolog.savedRegisters[i]));268else269return UNW_EBADREG;270}271}272273isSignalFrame = cieInfo.isSignalFrame;274275#if defined(_LIBUNWIND_TARGET_AARCH64)276// If the target is aarch64 then the return address may have been signed277// using the v8.3 pointer authentication extensions. The original278// return address needs to be authenticated before the return address is279// restored. autia1716 is used instead of autia as autia1716 assembles280// to a NOP on pre-v8.3a architectures.281if ((R::getArch() == REGISTERS_ARM64) &&282getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) &&283returnAddress != 0) {284#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)285return UNW_ECROSSRASIGNING;286#else287register unsigned long long x17 __asm("x17") = returnAddress;288register unsigned long long x16 __asm("x16") = cfa;289290// These are the autia1716/autib1716 instructions. The hint instructions291// are used here as gcc does not assemble autia1716/autib1716 for pre292// armv8.3a targets.293if (cieInfo.addressesSignedWithBKey)294asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716295else296asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716297returnAddress = x17;298#endif299}300#endif301302#if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) && \303defined(__ARM_FEATURE_PAUTH)304if ((R::getArch() == REGISTERS_ARM) &&305prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE].value) {306pint_t pac =307getSavedRegister(addressSpace, registers, cfa,308prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE]);309__asm__ __volatile__("autg %0, %1, %2"310:311: "r"(pac), "r"(returnAddress), "r"(cfa)312:);313}314#endif315316#if defined(_LIBUNWIND_TARGET_SPARC)317if (R::getArch() == REGISTERS_SPARC) {318// Skip call site instruction and delay slot319returnAddress += 8;320// Skip unimp instruction if function returns a struct321if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)322returnAddress += 4;323}324#endif325326#if defined(_LIBUNWIND_TARGET_SPARC64)327// Skip call site instruction and delay slot.328if (R::getArch() == REGISTERS_SPARC64)329returnAddress += 8;330#endif331332#if defined(_LIBUNWIND_TARGET_PPC64)333#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)334#define PPC64_ELFV1_R2_OFFSET 40335#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)336#define PPC64_ELFV2_R2_OFFSET 24337// If the instruction at return address is a TOC (r2) restore,338// then r2 was saved and needs to be restored.339// ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,340// while in ELFv1 ABI it is saved at SP + 40.341if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {342pint_t sp = newRegisters.getRegister(UNW_REG_SP);343pint_t r2 = 0;344switch (addressSpace.get32(returnAddress)) {345case PPC64_ELFV1_R2_LOAD_INST_ENCODING:346r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);347break;348case PPC64_ELFV2_R2_LOAD_INST_ENCODING:349r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);350break;351}352if (r2)353newRegisters.setRegister(UNW_PPC64_R2, r2);354}355#endif356357// Return address is address after call site instruction, so setting IP to358// that does simulates a return.359newRegisters.setIP(returnAddress);360361// Simulate the step by replacing the register set with the new ones.362registers = newRegisters;363364return UNW_STEP_SUCCESS;365}366}367return UNW_EBADFRAME;368}369370template <typename A, typename R>371typename A::pint_t372DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,373const R ®isters,374pint_t initialStackValue) {375const bool log = false;376pint_t p = expression;377pint_t expressionEnd = expression + 20; // temp, until len read378pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);379expressionEnd = p + length;380if (log)381fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",382(uint64_t)length);383pint_t stack[100];384pint_t *sp = stack;385*(++sp) = initialStackValue;386387while (p < expressionEnd) {388if (log) {389for (pint_t *t = sp; t > stack; --t) {390fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));391}392}393uint8_t opcode = addressSpace.get8(p++);394sint_t svalue, svalue2;395pint_t value;396uint32_t reg;397switch (opcode) {398case DW_OP_addr:399// push immediate address sized value400value = addressSpace.getP(p);401p += sizeof(pint_t);402*(++sp) = value;403if (log)404fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);405break;406407case DW_OP_deref:408// pop stack, dereference, push result409value = *sp--;410*(++sp) = addressSpace.getP(value);411if (log)412fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);413break;414415case DW_OP_const1u:416// push immediate 1 byte value417value = addressSpace.get8(p);418p += 1;419*(++sp) = value;420if (log)421fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);422break;423424case DW_OP_const1s:425// push immediate 1 byte signed value426svalue = (int8_t) addressSpace.get8(p);427p += 1;428*(++sp) = (pint_t)svalue;429if (log)430fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);431break;432433case DW_OP_const2u:434// push immediate 2 byte value435value = addressSpace.get16(p);436p += 2;437*(++sp) = value;438if (log)439fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);440break;441442case DW_OP_const2s:443// push immediate 2 byte signed value444svalue = (int16_t) addressSpace.get16(p);445p += 2;446*(++sp) = (pint_t)svalue;447if (log)448fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);449break;450451case DW_OP_const4u:452// push immediate 4 byte value453value = addressSpace.get32(p);454p += 4;455*(++sp) = value;456if (log)457fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);458break;459460case DW_OP_const4s:461// push immediate 4 byte signed value462svalue = (int32_t)addressSpace.get32(p);463p += 4;464*(++sp) = (pint_t)svalue;465if (log)466fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);467break;468469case DW_OP_const8u:470// push immediate 8 byte value471value = (pint_t)addressSpace.get64(p);472p += 8;473*(++sp) = value;474if (log)475fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);476break;477478case DW_OP_const8s:479// push immediate 8 byte signed value480value = (pint_t)addressSpace.get64(p);481p += 8;482*(++sp) = value;483if (log)484fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);485break;486487case DW_OP_constu:488// push immediate ULEB128 value489value = (pint_t)addressSpace.getULEB128(p, expressionEnd);490*(++sp) = value;491if (log)492fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);493break;494495case DW_OP_consts:496// push immediate SLEB128 value497svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);498*(++sp) = (pint_t)svalue;499if (log)500fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);501break;502503case DW_OP_dup:504// push top of stack505value = *sp;506*(++sp) = value;507if (log)508fprintf(stderr, "duplicate top of stack\n");509break;510511case DW_OP_drop:512// pop513--sp;514if (log)515fprintf(stderr, "pop top of stack\n");516break;517518case DW_OP_over:519// dup second520value = sp[-1];521*(++sp) = value;522if (log)523fprintf(stderr, "duplicate second in stack\n");524break;525526case DW_OP_pick:527// pick from528reg = addressSpace.get8(p);529p += 1;530value = sp[-(int)reg];531*(++sp) = value;532if (log)533fprintf(stderr, "duplicate %d in stack\n", reg);534break;535536case DW_OP_swap:537// swap top two538value = sp[0];539sp[0] = sp[-1];540sp[-1] = value;541if (log)542fprintf(stderr, "swap top of stack\n");543break;544545case DW_OP_rot:546// rotate top three547value = sp[0];548sp[0] = sp[-1];549sp[-1] = sp[-2];550sp[-2] = value;551if (log)552fprintf(stderr, "rotate top three of stack\n");553break;554555case DW_OP_xderef:556// pop stack, dereference, push result557value = *sp--;558*sp = *((pint_t*)value);559if (log)560fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);561break;562563case DW_OP_abs:564svalue = (sint_t)*sp;565if (svalue < 0)566*sp = (pint_t)(-svalue);567if (log)568fprintf(stderr, "abs\n");569break;570571case DW_OP_and:572value = *sp--;573*sp &= value;574if (log)575fprintf(stderr, "and\n");576break;577578case DW_OP_div:579svalue = (sint_t)(*sp--);580svalue2 = (sint_t)*sp;581*sp = (pint_t)(svalue2 / svalue);582if (log)583fprintf(stderr, "div\n");584break;585586case DW_OP_minus:587value = *sp--;588*sp = *sp - value;589if (log)590fprintf(stderr, "minus\n");591break;592593case DW_OP_mod:594svalue = (sint_t)(*sp--);595svalue2 = (sint_t)*sp;596*sp = (pint_t)(svalue2 % svalue);597if (log)598fprintf(stderr, "module\n");599break;600601case DW_OP_mul:602svalue = (sint_t)(*sp--);603svalue2 = (sint_t)*sp;604*sp = (pint_t)(svalue2 * svalue);605if (log)606fprintf(stderr, "mul\n");607break;608609case DW_OP_neg:610*sp = 0 - *sp;611if (log)612fprintf(stderr, "neg\n");613break;614615case DW_OP_not:616svalue = (sint_t)(*sp);617*sp = (pint_t)(~svalue);618if (log)619fprintf(stderr, "not\n");620break;621622case DW_OP_or:623value = *sp--;624*sp |= value;625if (log)626fprintf(stderr, "or\n");627break;628629case DW_OP_plus:630value = *sp--;631*sp += value;632if (log)633fprintf(stderr, "plus\n");634break;635636case DW_OP_plus_uconst:637// pop stack, add uelb128 constant, push result638*sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));639if (log)640fprintf(stderr, "add constant\n");641break;642643case DW_OP_shl:644value = *sp--;645*sp = *sp << value;646if (log)647fprintf(stderr, "shift left\n");648break;649650case DW_OP_shr:651value = *sp--;652*sp = *sp >> value;653if (log)654fprintf(stderr, "shift left\n");655break;656657case DW_OP_shra:658value = *sp--;659svalue = (sint_t)*sp;660*sp = (pint_t)(svalue >> value);661if (log)662fprintf(stderr, "shift left arithmetic\n");663break;664665case DW_OP_xor:666value = *sp--;667*sp ^= value;668if (log)669fprintf(stderr, "xor\n");670break;671672case DW_OP_skip:673svalue = (int16_t) addressSpace.get16(p);674p += 2;675p = (pint_t)((sint_t)p + svalue);676if (log)677fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);678break;679680case DW_OP_bra:681svalue = (int16_t) addressSpace.get16(p);682p += 2;683if (*sp--)684p = (pint_t)((sint_t)p + svalue);685if (log)686fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);687break;688689case DW_OP_eq:690value = *sp--;691*sp = (*sp == value);692if (log)693fprintf(stderr, "eq\n");694break;695696case DW_OP_ge:697value = *sp--;698*sp = (*sp >= value);699if (log)700fprintf(stderr, "ge\n");701break;702703case DW_OP_gt:704value = *sp--;705*sp = (*sp > value);706if (log)707fprintf(stderr, "gt\n");708break;709710case DW_OP_le:711value = *sp--;712*sp = (*sp <= value);713if (log)714fprintf(stderr, "le\n");715break;716717case DW_OP_lt:718value = *sp--;719*sp = (*sp < value);720if (log)721fprintf(stderr, "lt\n");722break;723724case DW_OP_ne:725value = *sp--;726*sp = (*sp != value);727if (log)728fprintf(stderr, "ne\n");729break;730731case DW_OP_lit0:732case DW_OP_lit1:733case DW_OP_lit2:734case DW_OP_lit3:735case DW_OP_lit4:736case DW_OP_lit5:737case DW_OP_lit6:738case DW_OP_lit7:739case DW_OP_lit8:740case DW_OP_lit9:741case DW_OP_lit10:742case DW_OP_lit11:743case DW_OP_lit12:744case DW_OP_lit13:745case DW_OP_lit14:746case DW_OP_lit15:747case DW_OP_lit16:748case DW_OP_lit17:749case DW_OP_lit18:750case DW_OP_lit19:751case DW_OP_lit20:752case DW_OP_lit21:753case DW_OP_lit22:754case DW_OP_lit23:755case DW_OP_lit24:756case DW_OP_lit25:757case DW_OP_lit26:758case DW_OP_lit27:759case DW_OP_lit28:760case DW_OP_lit29:761case DW_OP_lit30:762case DW_OP_lit31:763value = static_cast<pint_t>(opcode - DW_OP_lit0);764*(++sp) = value;765if (log)766fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);767break;768769case DW_OP_reg0:770case DW_OP_reg1:771case DW_OP_reg2:772case DW_OP_reg3:773case DW_OP_reg4:774case DW_OP_reg5:775case DW_OP_reg6:776case DW_OP_reg7:777case DW_OP_reg8:778case DW_OP_reg9:779case DW_OP_reg10:780case DW_OP_reg11:781case DW_OP_reg12:782case DW_OP_reg13:783case DW_OP_reg14:784case DW_OP_reg15:785case DW_OP_reg16:786case DW_OP_reg17:787case DW_OP_reg18:788case DW_OP_reg19:789case DW_OP_reg20:790case DW_OP_reg21:791case DW_OP_reg22:792case DW_OP_reg23:793case DW_OP_reg24:794case DW_OP_reg25:795case DW_OP_reg26:796case DW_OP_reg27:797case DW_OP_reg28:798case DW_OP_reg29:799case DW_OP_reg30:800case DW_OP_reg31:801reg = static_cast<uint32_t>(opcode - DW_OP_reg0);802*(++sp) = registers.getRegister((int)reg);803if (log)804fprintf(stderr, "push reg %d\n", reg);805break;806807case DW_OP_regx:808reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));809*(++sp) = registers.getRegister((int)reg);810if (log)811fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);812break;813814case DW_OP_breg0:815case DW_OP_breg1:816case DW_OP_breg2:817case DW_OP_breg3:818case DW_OP_breg4:819case DW_OP_breg5:820case DW_OP_breg6:821case DW_OP_breg7:822case DW_OP_breg8:823case DW_OP_breg9:824case DW_OP_breg10:825case DW_OP_breg11:826case DW_OP_breg12:827case DW_OP_breg13:828case DW_OP_breg14:829case DW_OP_breg15:830case DW_OP_breg16:831case DW_OP_breg17:832case DW_OP_breg18:833case DW_OP_breg19:834case DW_OP_breg20:835case DW_OP_breg21:836case DW_OP_breg22:837case DW_OP_breg23:838case DW_OP_breg24:839case DW_OP_breg25:840case DW_OP_breg26:841case DW_OP_breg27:842case DW_OP_breg28:843case DW_OP_breg29:844case DW_OP_breg30:845case DW_OP_breg31:846reg = static_cast<uint32_t>(opcode - DW_OP_breg0);847svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);848svalue += static_cast<sint_t>(registers.getRegister((int)reg));849*(++sp) = (pint_t)(svalue);850if (log)851fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);852break;853854case DW_OP_bregx:855reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));856svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);857svalue += static_cast<sint_t>(registers.getRegister((int)reg));858*(++sp) = (pint_t)(svalue);859if (log)860fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);861break;862863case DW_OP_fbreg:864_LIBUNWIND_ABORT("DW_OP_fbreg not implemented");865break;866867case DW_OP_piece:868_LIBUNWIND_ABORT("DW_OP_piece not implemented");869break;870871case DW_OP_deref_size:872// pop stack, dereference, push result873value = *sp--;874switch (addressSpace.get8(p++)) {875case 1:876value = addressSpace.get8(value);877break;878case 2:879value = addressSpace.get16(value);880break;881case 4:882value = addressSpace.get32(value);883break;884case 8:885value = (pint_t)addressSpace.get64(value);886break;887default:888_LIBUNWIND_ABORT("DW_OP_deref_size with bad size");889}890*(++sp) = value;891if (log)892fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);893break;894895case DW_OP_xderef_size:896case DW_OP_nop:897case DW_OP_push_object_addres:898case DW_OP_call2:899case DW_OP_call4:900case DW_OP_call_ref:901default:902_LIBUNWIND_ABORT("DWARF opcode not implemented");903}904905}906if (log)907fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);908return *sp;909}910911912913} // namespace libunwind914915#endif // __DWARF_INSTRUCTIONS_HPP__916917918