Path: blob/main/system/lib/libunwind/src/DwarfInstructions.hpp
6175 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 isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa,77PrologInfo &prolog);78static bool isReturnAddressSignedWithPC(A &addressSpace, R registers,79pint_t cfa, PrologInfo &prolog);80#endif81};8283template <typename R>84auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {85return r.getWCookie();86}87template <typename R> uint64_t getSparcWCookie(const R &, long) {88return 0;89}9091template <typename A, typename R>92typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(93A &addressSpace, const R ®isters, pint_t cfa,94const RegisterLocation &savedReg) {95switch (savedReg.location) {96case CFI_Parser<A>::kRegisterInCFA:97return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);9899case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific100return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^101getSparcWCookie(registers, 0));102103case CFI_Parser<A>::kRegisterAtExpression:104return (pint_t)addressSpace.getRegister(evaluateExpression(105(pint_t)savedReg.value, addressSpace, registers, cfa));106107case CFI_Parser<A>::kRegisterIsExpression:108return evaluateExpression((pint_t)savedReg.value, addressSpace,109registers, cfa);110111case CFI_Parser<A>::kRegisterInRegister:112return registers.getRegister((int)savedReg.value);113case CFI_Parser<A>::kRegisterUndefined:114return 0;115case CFI_Parser<A>::kRegisterUnused:116case CFI_Parser<A>::kRegisterOffsetFromCFA:117// FIX ME118break;119}120_LIBUNWIND_ABORT("unsupported restore location for register");121}122123template <typename A, typename R>124double DwarfInstructions<A, R>::getSavedFloatRegister(125A &addressSpace, const R ®isters, pint_t cfa,126const RegisterLocation &savedReg) {127switch (savedReg.location) {128case CFI_Parser<A>::kRegisterInCFA:129return addressSpace.getDouble(cfa + (pint_t)savedReg.value);130131case CFI_Parser<A>::kRegisterAtExpression:132return addressSpace.getDouble(133evaluateExpression((pint_t)savedReg.value, addressSpace,134registers, cfa));135case CFI_Parser<A>::kRegisterUndefined:136return 0.0;137case CFI_Parser<A>::kRegisterInRegister:138#ifndef _LIBUNWIND_TARGET_ARM139return registers.getFloatRegister((int)savedReg.value);140#endif141case CFI_Parser<A>::kRegisterIsExpression:142case CFI_Parser<A>::kRegisterUnused:143case CFI_Parser<A>::kRegisterOffsetFromCFA:144case CFI_Parser<A>::kRegisterInCFADecrypt:145// FIX ME146break;147}148_LIBUNWIND_ABORT("unsupported restore location for float register");149}150151template <typename A, typename R>152v128 DwarfInstructions<A, R>::getSavedVectorRegister(153A &addressSpace, const R ®isters, pint_t cfa,154const RegisterLocation &savedReg) {155switch (savedReg.location) {156case CFI_Parser<A>::kRegisterInCFA:157return addressSpace.getVector(cfa + (pint_t)savedReg.value);158159case CFI_Parser<A>::kRegisterAtExpression:160return addressSpace.getVector(161evaluateExpression((pint_t)savedReg.value, addressSpace,162registers, cfa));163164case CFI_Parser<A>::kRegisterIsExpression:165case CFI_Parser<A>::kRegisterUnused:166case CFI_Parser<A>::kRegisterUndefined:167case CFI_Parser<A>::kRegisterOffsetFromCFA:168case CFI_Parser<A>::kRegisterInRegister:169case CFI_Parser<A>::kRegisterInCFADecrypt:170// FIX ME171break;172}173_LIBUNWIND_ABORT("unsupported restore location for vector register");174}175#if defined(_LIBUNWIND_TARGET_AARCH64)176template <typename A, typename R>177bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace,178R registers, pint_t cfa,179PrologInfo &prolog) {180pint_t raSignState;181auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];182if (regloc.location == CFI_Parser<A>::kRegisterUnused)183raSignState = static_cast<pint_t>(regloc.value);184else185raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);186187// Only bit[0] is meaningful.188return raSignState & 0x01;189}190191template <typename A, typename R>192bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,193R registers,194pint_t cfa,195PrologInfo &prolog) {196pint_t raSignState;197auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];198if (regloc.location == CFI_Parser<A>::kRegisterUnused)199raSignState = static_cast<pint_t>(regloc.value);200else201raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);202203// Only bit[1] is meaningful.204return raSignState & 0x02;205}206#endif207208template <typename A, typename R>209int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,210pint_t fdeStart, R ®isters,211bool &isSignalFrame, bool stage2) {212FDE_Info fdeInfo;213CIE_Info cieInfo;214if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,215&cieInfo) == NULL) {216PrologInfo prolog;217if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,218R::getArch(), &prolog)) {219// get pointer to cfa (architecture specific)220pint_t cfa = getCFA(addressSpace, prolog, registers);221222(void)stage2;223// __unw_step_stage2 is not used for cross unwinding, so we use224// __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are225// building for AArch64 natively.226#if defined(__aarch64__)227if (stage2 && cieInfo.mteTaggedFrame) {228pint_t sp = registers.getSP();229pint_t p = sp;230// AArch64 doesn't require the value of SP to be 16-byte aligned at231// all times, only at memory accesses and public interfaces [1]. Thus,232// a signal could arrive at a point where SP is not aligned properly.233// In that case, the kernel fixes up [2] the signal frame, but we234// still have a misaligned SP in the previous frame. If that signal235// handler caused stack unwinding, we would have an unaligned SP.236// We do not need to fix up the CFA, as that is the SP at a "public237// interface".238// [1]:239// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack240// [2]:241// https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718242p &= ~0xfULL;243// CFA is the bottom of the current stack frame.244for (; p < cfa; p += 16) {245__asm__ __volatile__(".arch armv8.5-a\n"246".arch_extension memtag\n"247"stg %[Ptr], [%[Ptr]]\n"248:249: [Ptr] "r"(p)250: "memory");251}252}253#endif254// restore registers that DWARF says were saved255R newRegisters = registers;256257// Typically, the CFA is the stack pointer at the call site in258// the previous frame. However, there are scenarios in which this is not259// true. For example, if we switched to a new stack. In that case, the260// value of the previous SP might be indicated by a CFI directive.261//262// We set the SP here to the CFA, allowing for it to be overridden263// by a CFI directive later on.264newRegisters.setSP(cfa);265266pint_t returnAddress = 0;267constexpr int lastReg = R::lastDwarfRegNum();268static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=269lastReg,270"register range too large");271assert(lastReg >= (int)cieInfo.returnAddressRegister &&272"register range does not contain return address register");273for (int i = 0; i <= lastReg; ++i) {274if (prolog.savedRegisters[i].location !=275CFI_Parser<A>::kRegisterUnused) {276if (registers.validFloatRegister(i))277newRegisters.setFloatRegister(278i, getSavedFloatRegister(addressSpace, registers, cfa,279prolog.savedRegisters[i]));280else if (registers.validVectorRegister(i))281newRegisters.setVectorRegister(282i, getSavedVectorRegister(addressSpace, registers, cfa,283prolog.savedRegisters[i]));284else if (i == (int)cieInfo.returnAddressRegister)285returnAddress = getSavedRegister(addressSpace, registers, cfa,286prolog.savedRegisters[i]);287else if (registers.validRegister(i))288newRegisters.setRegister(289i, getSavedRegister(addressSpace, registers, cfa,290prolog.savedRegisters[i]));291else292return UNW_EBADREG;293} else if (i == (int)cieInfo.returnAddressRegister) {294// Leaf function keeps the return address in register and there is no295// explicit instructions how to restore it.296returnAddress = registers.getRegister(cieInfo.returnAddressRegister);297}298}299300isSignalFrame = cieInfo.isSignalFrame;301302#if defined(_LIBUNWIND_TARGET_AARCH64)303// If the target is aarch64 then the return address may have been signed304// using the v8.3 pointer authentication extensions. The original305// return address needs to be authenticated before the return address is306// restored. autia1716 is used instead of autia as autia1716 assembles307// to a NOP on pre-v8.3a architectures.308if ((R::getArch() == REGISTERS_ARM64) &&309isReturnAddressSigned(addressSpace, registers, cfa, prolog) &&310returnAddress != 0) {311#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)312return UNW_ECROSSRASIGNING;313#else314register unsigned long long x17 __asm("x17") = returnAddress;315register unsigned long long x16 __asm("x16") = cfa;316317// We use the hint versions of the authentication instructions below to318// ensure they're assembled by the compiler even for targets with no319// FEAT_PAuth/FEAT_PAuth_LR support.320if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) {321register unsigned long long x15 __asm("x15") =322prolog.ptrAuthDiversifier;323if (cieInfo.addressesSignedWithBKey) {324asm("hint 0x27\n\t" // pacm325"hint 0xe"326: "+r"(x17)327: "r"(x16), "r"(x15)); // autib1716328} else {329asm("hint 0x27\n\t" // pacm330"hint 0xc"331: "+r"(x17)332: "r"(x16), "r"(x15)); // autia1716333}334} else {335if (cieInfo.addressesSignedWithBKey)336asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716337else338asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716339}340returnAddress = x17;341#endif342}343#endif344345#if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) && \346defined(__ARM_FEATURE_PAUTH)347if ((R::getArch() == REGISTERS_ARM) &&348prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE].value) {349pint_t pac =350getSavedRegister(addressSpace, registers, cfa,351prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE]);352__asm__ __volatile__("autg %0, %1, %2"353:354: "r"(pac), "r"(returnAddress), "r"(cfa)355:);356}357#endif358359#if defined(_LIBUNWIND_TARGET_SPARC)360if (R::getArch() == REGISTERS_SPARC) {361// Skip call site instruction and delay slot362returnAddress += 8;363// Skip unimp instruction if function returns a struct364if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)365returnAddress += 4;366}367#endif368369#if defined(_LIBUNWIND_TARGET_SPARC64)370// Skip call site instruction and delay slot.371if (R::getArch() == REGISTERS_SPARC64)372returnAddress += 8;373#endif374375#if defined(_LIBUNWIND_TARGET_PPC64)376#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)377#define PPC64_ELFV1_R2_OFFSET 40378#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)379#define PPC64_ELFV2_R2_OFFSET 24380// If the instruction at return address is a TOC (r2) restore,381// then r2 was saved and needs to be restored.382// ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,383// while in ELFv1 ABI it is saved at SP + 40.384if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {385pint_t sp = newRegisters.getRegister(UNW_REG_SP);386pint_t r2 = 0;387switch (addressSpace.get32(returnAddress)) {388case PPC64_ELFV1_R2_LOAD_INST_ENCODING:389r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);390break;391case PPC64_ELFV2_R2_LOAD_INST_ENCODING:392r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);393break;394}395if (r2)396newRegisters.setRegister(UNW_PPC64_R2, r2);397}398#endif399400// Return address is address after call site instruction, so setting IP to401// that does simulates a return.402newRegisters.setIP(returnAddress);403404// Simulate the step by replacing the register set with the new ones.405registers = newRegisters;406407return UNW_STEP_SUCCESS;408}409}410return UNW_EBADFRAME;411}412413template <typename A, typename R>414typename A::pint_t415DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,416const R ®isters,417pint_t initialStackValue) {418const bool log = false;419pint_t p = expression;420pint_t expressionEnd = expression + 20; // temp, until len read421pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);422expressionEnd = p + length;423if (log)424fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",425(uint64_t)length);426pint_t stack[100];427pint_t *sp = stack;428*(++sp) = initialStackValue;429430while (p < expressionEnd) {431if (log) {432for (pint_t *t = sp; t > stack; --t) {433fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));434}435}436uint8_t opcode = addressSpace.get8(p++);437sint_t svalue, svalue2;438pint_t value;439uint32_t reg;440switch (opcode) {441case DW_OP_addr:442// push immediate address sized value443value = addressSpace.getP(p);444p += sizeof(pint_t);445*(++sp) = value;446if (log)447fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);448break;449450case DW_OP_deref:451// pop stack, dereference, push result452value = *sp--;453*(++sp) = addressSpace.getP(value);454if (log)455fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);456break;457458case DW_OP_const1u:459// push immediate 1 byte value460value = addressSpace.get8(p);461p += 1;462*(++sp) = value;463if (log)464fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);465break;466467case DW_OP_const1s:468// push immediate 1 byte signed value469svalue = (int8_t) addressSpace.get8(p);470p += 1;471*(++sp) = (pint_t)svalue;472if (log)473fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);474break;475476case DW_OP_const2u:477// push immediate 2 byte value478value = addressSpace.get16(p);479p += 2;480*(++sp) = value;481if (log)482fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);483break;484485case DW_OP_const2s:486// push immediate 2 byte signed value487svalue = (int16_t) addressSpace.get16(p);488p += 2;489*(++sp) = (pint_t)svalue;490if (log)491fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);492break;493494case DW_OP_const4u:495// push immediate 4 byte value496value = addressSpace.get32(p);497p += 4;498*(++sp) = value;499if (log)500fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);501break;502503case DW_OP_const4s:504// push immediate 4 byte signed value505svalue = (int32_t)addressSpace.get32(p);506p += 4;507*(++sp) = (pint_t)svalue;508if (log)509fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);510break;511512case DW_OP_const8u:513// push immediate 8 byte value514value = (pint_t)addressSpace.get64(p);515p += 8;516*(++sp) = value;517if (log)518fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);519break;520521case DW_OP_const8s:522// push immediate 8 byte signed value523value = (pint_t)addressSpace.get64(p);524p += 8;525*(++sp) = value;526if (log)527fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);528break;529530case DW_OP_constu:531// push immediate ULEB128 value532value = (pint_t)addressSpace.getULEB128(p, expressionEnd);533*(++sp) = value;534if (log)535fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);536break;537538case DW_OP_consts:539// push immediate SLEB128 value540svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);541*(++sp) = (pint_t)svalue;542if (log)543fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);544break;545546case DW_OP_dup:547// push top of stack548value = *sp;549*(++sp) = value;550if (log)551fprintf(stderr, "duplicate top of stack\n");552break;553554case DW_OP_drop:555// pop556--sp;557if (log)558fprintf(stderr, "pop top of stack\n");559break;560561case DW_OP_over:562// dup second563value = sp[-1];564*(++sp) = value;565if (log)566fprintf(stderr, "duplicate second in stack\n");567break;568569case DW_OP_pick:570// pick from571reg = addressSpace.get8(p);572p += 1;573value = sp[-(int)reg];574*(++sp) = value;575if (log)576fprintf(stderr, "duplicate %d in stack\n", reg);577break;578579case DW_OP_swap:580// swap top two581value = sp[0];582sp[0] = sp[-1];583sp[-1] = value;584if (log)585fprintf(stderr, "swap top of stack\n");586break;587588case DW_OP_rot:589// rotate top three590value = sp[0];591sp[0] = sp[-1];592sp[-1] = sp[-2];593sp[-2] = value;594if (log)595fprintf(stderr, "rotate top three of stack\n");596break;597598case DW_OP_xderef:599// pop stack, dereference, push result600value = *sp--;601*sp = *((pint_t*)value);602if (log)603fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);604break;605606case DW_OP_abs:607svalue = (sint_t)*sp;608if (svalue < 0)609*sp = (pint_t)(-svalue);610if (log)611fprintf(stderr, "abs\n");612break;613614case DW_OP_and:615value = *sp--;616*sp &= value;617if (log)618fprintf(stderr, "and\n");619break;620621case DW_OP_div:622svalue = (sint_t)(*sp--);623svalue2 = (sint_t)*sp;624*sp = (pint_t)(svalue2 / svalue);625if (log)626fprintf(stderr, "div\n");627break;628629case DW_OP_minus:630value = *sp--;631*sp = *sp - value;632if (log)633fprintf(stderr, "minus\n");634break;635636case DW_OP_mod:637svalue = (sint_t)(*sp--);638svalue2 = (sint_t)*sp;639*sp = (pint_t)(svalue2 % svalue);640if (log)641fprintf(stderr, "module\n");642break;643644case DW_OP_mul:645svalue = (sint_t)(*sp--);646svalue2 = (sint_t)*sp;647*sp = (pint_t)(svalue2 * svalue);648if (log)649fprintf(stderr, "mul\n");650break;651652case DW_OP_neg:653*sp = 0 - *sp;654if (log)655fprintf(stderr, "neg\n");656break;657658case DW_OP_not:659svalue = (sint_t)(*sp);660*sp = (pint_t)(~svalue);661if (log)662fprintf(stderr, "not\n");663break;664665case DW_OP_or:666value = *sp--;667*sp |= value;668if (log)669fprintf(stderr, "or\n");670break;671672case DW_OP_plus:673value = *sp--;674*sp += value;675if (log)676fprintf(stderr, "plus\n");677break;678679case DW_OP_plus_uconst:680// pop stack, add uelb128 constant, push result681*sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));682if (log)683fprintf(stderr, "add constant\n");684break;685686case DW_OP_shl:687value = *sp--;688*sp = *sp << value;689if (log)690fprintf(stderr, "shift left\n");691break;692693case DW_OP_shr:694value = *sp--;695*sp = *sp >> value;696if (log)697fprintf(stderr, "shift left\n");698break;699700case DW_OP_shra:701value = *sp--;702svalue = (sint_t)*sp;703*sp = (pint_t)(svalue >> value);704if (log)705fprintf(stderr, "shift left arithmetic\n");706break;707708case DW_OP_xor:709value = *sp--;710*sp ^= value;711if (log)712fprintf(stderr, "xor\n");713break;714715case DW_OP_skip:716svalue = (int16_t) addressSpace.get16(p);717p += 2;718p = (pint_t)((sint_t)p + svalue);719if (log)720fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);721break;722723case DW_OP_bra:724svalue = (int16_t) addressSpace.get16(p);725p += 2;726if (*sp--)727p = (pint_t)((sint_t)p + svalue);728if (log)729fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);730break;731732case DW_OP_eq:733value = *sp--;734*sp = (*sp == value);735if (log)736fprintf(stderr, "eq\n");737break;738739case DW_OP_ge:740value = *sp--;741*sp = (*sp >= value);742if (log)743fprintf(stderr, "ge\n");744break;745746case DW_OP_gt:747value = *sp--;748*sp = (*sp > value);749if (log)750fprintf(stderr, "gt\n");751break;752753case DW_OP_le:754value = *sp--;755*sp = (*sp <= value);756if (log)757fprintf(stderr, "le\n");758break;759760case DW_OP_lt:761value = *sp--;762*sp = (*sp < value);763if (log)764fprintf(stderr, "lt\n");765break;766767case DW_OP_ne:768value = *sp--;769*sp = (*sp != value);770if (log)771fprintf(stderr, "ne\n");772break;773774case DW_OP_lit0:775case DW_OP_lit1:776case DW_OP_lit2:777case DW_OP_lit3:778case DW_OP_lit4:779case DW_OP_lit5:780case DW_OP_lit6:781case DW_OP_lit7:782case DW_OP_lit8:783case DW_OP_lit9:784case DW_OP_lit10:785case DW_OP_lit11:786case DW_OP_lit12:787case DW_OP_lit13:788case DW_OP_lit14:789case DW_OP_lit15:790case DW_OP_lit16:791case DW_OP_lit17:792case DW_OP_lit18:793case DW_OP_lit19:794case DW_OP_lit20:795case DW_OP_lit21:796case DW_OP_lit22:797case DW_OP_lit23:798case DW_OP_lit24:799case DW_OP_lit25:800case DW_OP_lit26:801case DW_OP_lit27:802case DW_OP_lit28:803case DW_OP_lit29:804case DW_OP_lit30:805case DW_OP_lit31:806value = static_cast<pint_t>(opcode - DW_OP_lit0);807*(++sp) = value;808if (log)809fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);810break;811812case DW_OP_reg0:813case DW_OP_reg1:814case DW_OP_reg2:815case DW_OP_reg3:816case DW_OP_reg4:817case DW_OP_reg5:818case DW_OP_reg6:819case DW_OP_reg7:820case DW_OP_reg8:821case DW_OP_reg9:822case DW_OP_reg10:823case DW_OP_reg11:824case DW_OP_reg12:825case DW_OP_reg13:826case DW_OP_reg14:827case DW_OP_reg15:828case DW_OP_reg16:829case DW_OP_reg17:830case DW_OP_reg18:831case DW_OP_reg19:832case DW_OP_reg20:833case DW_OP_reg21:834case DW_OP_reg22:835case DW_OP_reg23:836case DW_OP_reg24:837case DW_OP_reg25:838case DW_OP_reg26:839case DW_OP_reg27:840case DW_OP_reg28:841case DW_OP_reg29:842case DW_OP_reg30:843case DW_OP_reg31:844reg = static_cast<uint32_t>(opcode - DW_OP_reg0);845*(++sp) = registers.getRegister((int)reg);846if (log)847fprintf(stderr, "push reg %d\n", reg);848break;849850case DW_OP_regx:851reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));852*(++sp) = registers.getRegister((int)reg);853if (log)854fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);855break;856857case DW_OP_breg0:858case DW_OP_breg1:859case DW_OP_breg2:860case DW_OP_breg3:861case DW_OP_breg4:862case DW_OP_breg5:863case DW_OP_breg6:864case DW_OP_breg7:865case DW_OP_breg8:866case DW_OP_breg9:867case DW_OP_breg10:868case DW_OP_breg11:869case DW_OP_breg12:870case DW_OP_breg13:871case DW_OP_breg14:872case DW_OP_breg15:873case DW_OP_breg16:874case DW_OP_breg17:875case DW_OP_breg18:876case DW_OP_breg19:877case DW_OP_breg20:878case DW_OP_breg21:879case DW_OP_breg22:880case DW_OP_breg23:881case DW_OP_breg24:882case DW_OP_breg25:883case DW_OP_breg26:884case DW_OP_breg27:885case DW_OP_breg28:886case DW_OP_breg29:887case DW_OP_breg30:888case DW_OP_breg31:889reg = static_cast<uint32_t>(opcode - DW_OP_breg0);890svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);891svalue += static_cast<sint_t>(registers.getRegister((int)reg));892*(++sp) = (pint_t)(svalue);893if (log)894fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);895break;896897case DW_OP_bregx:898reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));899svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);900svalue += static_cast<sint_t>(registers.getRegister((int)reg));901*(++sp) = (pint_t)(svalue);902if (log)903fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);904break;905906case DW_OP_fbreg:907_LIBUNWIND_ABORT("DW_OP_fbreg not implemented");908break;909910case DW_OP_piece:911_LIBUNWIND_ABORT("DW_OP_piece not implemented");912break;913914case DW_OP_deref_size:915// pop stack, dereference, push result916value = *sp--;917switch (addressSpace.get8(p++)) {918case 1:919value = addressSpace.get8(value);920break;921case 2:922value = addressSpace.get16(value);923break;924case 4:925value = addressSpace.get32(value);926break;927case 8:928value = (pint_t)addressSpace.get64(value);929break;930default:931_LIBUNWIND_ABORT("DW_OP_deref_size with bad size");932}933*(++sp) = value;934if (log)935fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);936break;937938case DW_OP_xderef_size:939case DW_OP_nop:940case DW_OP_push_object_addres:941case DW_OP_call2:942case DW_OP_call4:943case DW_OP_call_ref:944default:945_LIBUNWIND_ABORT("DWARF opcode not implemented");946}947948}949if (log)950fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);951return *sp;952}953954955956} // namespace libunwind957958#endif // __DWARF_INSTRUCTIONS_HPP__959960961