1288149Semaste//===-------------------------- DwarfInstructions.hpp ---------------------===// 2288149Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6288149Semaste// 7288149Semaste// 8345018Sdim// Processor specific interpretation of DWARF unwind info. 9288149Semaste// 10288149Semaste//===----------------------------------------------------------------------===// 11288149Semaste 12288149Semaste#ifndef __DWARF_INSTRUCTIONS_HPP__ 13288149Semaste#define __DWARF_INSTRUCTIONS_HPP__ 14288149Semaste 15288149Semaste#include <stdint.h> 16288149Semaste#include <stdio.h> 17288149Semaste#include <stdlib.h> 18288149Semaste 19288149Semaste#include "dwarf2.h" 20288149Semaste#include "Registers.hpp" 21288149Semaste#include "DwarfParser.hpp" 22288149Semaste#include "config.h" 23288149Semaste 24288149Semaste 25288149Semastenamespace libunwind { 26288149Semaste 27288149Semaste 28345018Sdim/// DwarfInstructions maps abtract DWARF unwind instructions to a particular 29288149Semaste/// architecture 30288149Semastetemplate <typename A, typename R> 31288149Semasteclass DwarfInstructions { 32288149Semastepublic: 33288149Semaste typedef typename A::pint_t pint_t; 34288149Semaste typedef typename A::sint_t sint_t; 35288149Semaste 36288149Semaste static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, 37360784Sdim R ®isters, bool &isSignalFrame); 38288149Semaste 39288149Semasteprivate: 40288149Semaste 41288149Semaste enum { 42288149Semaste DW_X86_64_RET_ADDR = 16 43288149Semaste }; 44288149Semaste 45288149Semaste enum { 46288149Semaste DW_X86_RET_ADDR = 8 47288149Semaste }; 48288149Semaste 49288149Semaste typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation; 50288149Semaste typedef typename CFI_Parser<A>::PrologInfo PrologInfo; 51288149Semaste typedef typename CFI_Parser<A>::FDE_Info FDE_Info; 52288149Semaste typedef typename CFI_Parser<A>::CIE_Info CIE_Info; 53288149Semaste 54288149Semaste static pint_t evaluateExpression(pint_t expression, A &addressSpace, 55288149Semaste const R ®isters, 56288149Semaste pint_t initialStackValue); 57288149Semaste static pint_t getSavedRegister(A &addressSpace, const R ®isters, 58288149Semaste pint_t cfa, const RegisterLocation &savedReg); 59288149Semaste static double getSavedFloatRegister(A &addressSpace, const R ®isters, 60288149Semaste pint_t cfa, const RegisterLocation &savedReg); 61288149Semaste static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, 62288149Semaste pint_t cfa, const RegisterLocation &savedReg); 63288149Semaste 64288149Semaste static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, 65288149Semaste const R ®isters) { 66288149Semaste if (prolog.cfaRegister != 0) 67288149Semaste return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + 68288149Semaste prolog.cfaRegisterOffset); 69288149Semaste if (prolog.cfaExpression != 0) 70288149Semaste return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, 71288149Semaste registers, 0); 72288149Semaste assert(0 && "getCFA(): unknown location"); 73288149Semaste __builtin_unreachable(); 74288149Semaste } 75288149Semaste}; 76288149Semaste 77288149Semaste 78288149Semastetemplate <typename A, typename R> 79288149Semastetypename A::pint_t DwarfInstructions<A, R>::getSavedRegister( 80288149Semaste A &addressSpace, const R ®isters, pint_t cfa, 81288149Semaste const RegisterLocation &savedReg) { 82288149Semaste switch (savedReg.location) { 83288149Semaste case CFI_Parser<A>::kRegisterInCFA: 84353358Sdim return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); 85288149Semaste 86288149Semaste case CFI_Parser<A>::kRegisterAtExpression: 87353358Sdim return (pint_t)addressSpace.getRegister(evaluateExpression( 88353358Sdim (pint_t)savedReg.value, addressSpace, registers, cfa)); 89288149Semaste 90288149Semaste case CFI_Parser<A>::kRegisterIsExpression: 91288149Semaste return evaluateExpression((pint_t)savedReg.value, addressSpace, 92288149Semaste registers, cfa); 93288149Semaste 94288149Semaste case CFI_Parser<A>::kRegisterInRegister: 95288149Semaste return registers.getRegister((int)savedReg.value); 96288149Semaste 97288149Semaste case CFI_Parser<A>::kRegisterUnused: 98288149Semaste case CFI_Parser<A>::kRegisterOffsetFromCFA: 99288149Semaste // FIX ME 100288149Semaste break; 101288149Semaste } 102288149Semaste _LIBUNWIND_ABORT("unsupported restore location for register"); 103288149Semaste} 104288149Semaste 105288149Semastetemplate <typename A, typename R> 106288149Semastedouble DwarfInstructions<A, R>::getSavedFloatRegister( 107288149Semaste A &addressSpace, const R ®isters, pint_t cfa, 108288149Semaste const RegisterLocation &savedReg) { 109288149Semaste switch (savedReg.location) { 110288149Semaste case CFI_Parser<A>::kRegisterInCFA: 111288149Semaste return addressSpace.getDouble(cfa + (pint_t)savedReg.value); 112288149Semaste 113288149Semaste case CFI_Parser<A>::kRegisterAtExpression: 114288149Semaste return addressSpace.getDouble( 115288149Semaste evaluateExpression((pint_t)savedReg.value, addressSpace, 116288149Semaste registers, cfa)); 117288149Semaste 118288149Semaste case CFI_Parser<A>::kRegisterIsExpression: 119288149Semaste case CFI_Parser<A>::kRegisterUnused: 120288149Semaste case CFI_Parser<A>::kRegisterOffsetFromCFA: 121288149Semaste case CFI_Parser<A>::kRegisterInRegister: 122288149Semaste // FIX ME 123288149Semaste break; 124288149Semaste } 125288149Semaste _LIBUNWIND_ABORT("unsupported restore location for float register"); 126288149Semaste} 127288149Semaste 128288149Semastetemplate <typename A, typename R> 129288149Semastev128 DwarfInstructions<A, R>::getSavedVectorRegister( 130288149Semaste A &addressSpace, const R ®isters, pint_t cfa, 131288149Semaste const RegisterLocation &savedReg) { 132288149Semaste switch (savedReg.location) { 133288149Semaste case CFI_Parser<A>::kRegisterInCFA: 134288149Semaste return addressSpace.getVector(cfa + (pint_t)savedReg.value); 135288149Semaste 136288149Semaste case CFI_Parser<A>::kRegisterAtExpression: 137288149Semaste return addressSpace.getVector( 138288149Semaste evaluateExpression((pint_t)savedReg.value, addressSpace, 139288149Semaste registers, cfa)); 140288149Semaste 141288149Semaste case CFI_Parser<A>::kRegisterIsExpression: 142288149Semaste case CFI_Parser<A>::kRegisterUnused: 143288149Semaste case CFI_Parser<A>::kRegisterOffsetFromCFA: 144288149Semaste case CFI_Parser<A>::kRegisterInRegister: 145288149Semaste // FIX ME 146288149Semaste break; 147288149Semaste } 148288149Semaste _LIBUNWIND_ABORT("unsupported restore location for vector register"); 149288149Semaste} 150288149Semaste 151288149Semastetemplate <typename A, typename R> 152288149Semasteint DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, 153360784Sdim pint_t fdeStart, R ®isters, 154360784Sdim bool &isSignalFrame) { 155288149Semaste FDE_Info fdeInfo; 156288149Semaste CIE_Info cieInfo; 157288149Semaste if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, 158288149Semaste &cieInfo) == NULL) { 159288149Semaste PrologInfo prolog; 160288149Semaste if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, 161345018Sdim R::getArch(), &prolog)) { 162288149Semaste // get pointer to cfa (architecture specific) 163288149Semaste pint_t cfa = getCFA(addressSpace, prolog, registers); 164288149Semaste 165345018Sdim // restore registers that DWARF says were saved 166288149Semaste R newRegisters = registers; 167288149Semaste pint_t returnAddress = 0; 168288149Semaste const int lastReg = R::lastDwarfRegNum(); 169345018Sdim assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg && 170288149Semaste "register range too large"); 171288149Semaste assert(lastReg >= (int)cieInfo.returnAddressRegister && 172288149Semaste "register range does not contain return address register"); 173288149Semaste for (int i = 0; i <= lastReg; ++i) { 174288149Semaste if (prolog.savedRegisters[i].location != 175288149Semaste CFI_Parser<A>::kRegisterUnused) { 176288149Semaste if (registers.validFloatRegister(i)) 177288149Semaste newRegisters.setFloatRegister( 178288149Semaste i, getSavedFloatRegister(addressSpace, registers, cfa, 179288149Semaste prolog.savedRegisters[i])); 180288149Semaste else if (registers.validVectorRegister(i)) 181288149Semaste newRegisters.setVectorRegister( 182288149Semaste i, getSavedVectorRegister(addressSpace, registers, cfa, 183288149Semaste prolog.savedRegisters[i])); 184288149Semaste else if (i == (int)cieInfo.returnAddressRegister) 185288149Semaste returnAddress = getSavedRegister(addressSpace, registers, cfa, 186288149Semaste prolog.savedRegisters[i]); 187288149Semaste else if (registers.validRegister(i)) 188288149Semaste newRegisters.setRegister( 189288149Semaste i, getSavedRegister(addressSpace, registers, cfa, 190288149Semaste prolog.savedRegisters[i])); 191288149Semaste else 192288149Semaste return UNW_EBADREG; 193288149Semaste } 194288149Semaste } 195288149Semaste 196288149Semaste // By definition, the CFA is the stack pointer at the call site, so 197288149Semaste // restoring SP means setting it to CFA. 198288149Semaste newRegisters.setSP(cfa); 199288149Semaste 200360784Sdim isSignalFrame = cieInfo.isSignalFrame; 201360784Sdim 202345018Sdim#if defined(_LIBUNWIND_TARGET_AARCH64) 203345018Sdim // If the target is aarch64 then the return address may have been signed 204345018Sdim // using the v8.3 pointer authentication extensions. The original 205345018Sdim // return address needs to be authenticated before the return address is 206345018Sdim // restored. autia1716 is used instead of autia as autia1716 assembles 207345018Sdim // to a NOP on pre-v8.3a architectures. 208345018Sdim if ((R::getArch() == REGISTERS_ARM64) && 209345018Sdim prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) { 210345018Sdim#if !defined(_LIBUNWIND_IS_NATIVE_ONLY) 211345018Sdim return UNW_ECROSSRASIGNING; 212345018Sdim#else 213345018Sdim register unsigned long long x17 __asm("x17") = returnAddress; 214345018Sdim register unsigned long long x16 __asm("x16") = cfa; 215345018Sdim 216345018Sdim // These are the autia1716/autib1716 instructions. The hint instructions 217345018Sdim // are used here as gcc does not assemble autia1716/autib1716 for pre 218345018Sdim // armv8.3a targets. 219345018Sdim if (cieInfo.addressesSignedWithBKey) 220345018Sdim asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 221345018Sdim else 222345018Sdim asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 223345018Sdim returnAddress = x17; 224345018Sdim#endif 225345018Sdim } 226345018Sdim#endif 227345018Sdim 228345018Sdim#if defined(_LIBUNWIND_TARGET_SPARC) 229345018Sdim if (R::getArch() == REGISTERS_SPARC) { 230345018Sdim // Skip call site instruction and delay slot 231345018Sdim returnAddress += 8; 232345018Sdim // Skip unimp instruction if function returns a struct 233345018Sdim if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0) 234345018Sdim returnAddress += 4; 235345018Sdim } 236345018Sdim#endif 237345018Sdim 238349793Sdim#if defined(_LIBUNWIND_TARGET_PPC64) 239349793Sdim#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1) 240349793Sdim#define PPC64_ELFV1_R2_OFFSET 40 241349793Sdim#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1) 242349793Sdim#define PPC64_ELFV2_R2_OFFSET 24 243349793Sdim // If the instruction at return address is a TOC (r2) restore, 244349793Sdim // then r2 was saved and needs to be restored. 245349793Sdim // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24, 246349793Sdim // while in ELFv1 ABI it is saved at SP + 40. 247349793Sdim if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) { 248349793Sdim pint_t sp = newRegisters.getRegister(UNW_REG_SP); 249349793Sdim pint_t r2 = 0; 250349793Sdim switch (addressSpace.get32(returnAddress)) { 251349793Sdim case PPC64_ELFV1_R2_LOAD_INST_ENCODING: 252349793Sdim r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET); 253349793Sdim break; 254349793Sdim case PPC64_ELFV2_R2_LOAD_INST_ENCODING: 255349793Sdim r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET); 256349793Sdim break; 257349793Sdim } 258349793Sdim if (r2) 259349793Sdim newRegisters.setRegister(UNW_PPC64_R2, r2); 260349793Sdim } 261349793Sdim#endif 262349793Sdim 263288149Semaste // Return address is address after call site instruction, so setting IP to 264288149Semaste // that does simualates a return. 265288149Semaste newRegisters.setIP(returnAddress); 266288149Semaste 267288149Semaste // Simulate the step by replacing the register set with the new ones. 268288149Semaste registers = newRegisters; 269288149Semaste 270288149Semaste return UNW_STEP_SUCCESS; 271288149Semaste } 272288149Semaste } 273288149Semaste return UNW_EBADFRAME; 274288149Semaste} 275288149Semaste 276288149Semastetemplate <typename A, typename R> 277288149Semastetypename A::pint_t 278288149SemasteDwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, 279288149Semaste const R ®isters, 280288149Semaste pint_t initialStackValue) { 281288149Semaste const bool log = false; 282288149Semaste pint_t p = expression; 283288149Semaste pint_t expressionEnd = expression + 20; // temp, until len read 284288149Semaste pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd); 285288149Semaste expressionEnd = p + length; 286288149Semaste if (log) 287288149Semaste fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n", 288288149Semaste (uint64_t)length); 289288149Semaste pint_t stack[100]; 290288149Semaste pint_t *sp = stack; 291288149Semaste *(++sp) = initialStackValue; 292288149Semaste 293288149Semaste while (p < expressionEnd) { 294288149Semaste if (log) { 295288149Semaste for (pint_t *t = sp; t > stack; --t) { 296288149Semaste fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t)); 297288149Semaste } 298288149Semaste } 299288149Semaste uint8_t opcode = addressSpace.get8(p++); 300288149Semaste sint_t svalue, svalue2; 301288149Semaste pint_t value; 302288149Semaste uint32_t reg; 303288149Semaste switch (opcode) { 304288149Semaste case DW_OP_addr: 305288149Semaste // push immediate address sized value 306288149Semaste value = addressSpace.getP(p); 307288149Semaste p += sizeof(pint_t); 308288149Semaste *(++sp) = value; 309288149Semaste if (log) 310288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 311288149Semaste break; 312288149Semaste 313288149Semaste case DW_OP_deref: 314288149Semaste // pop stack, dereference, push result 315288149Semaste value = *sp--; 316288149Semaste *(++sp) = addressSpace.getP(value); 317288149Semaste if (log) 318288149Semaste fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value); 319288149Semaste break; 320288149Semaste 321288149Semaste case DW_OP_const1u: 322288149Semaste // push immediate 1 byte value 323288149Semaste value = addressSpace.get8(p); 324288149Semaste p += 1; 325288149Semaste *(++sp) = value; 326288149Semaste if (log) 327288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 328288149Semaste break; 329288149Semaste 330288149Semaste case DW_OP_const1s: 331288149Semaste // push immediate 1 byte signed value 332288149Semaste svalue = (int8_t) addressSpace.get8(p); 333288149Semaste p += 1; 334288149Semaste *(++sp) = (pint_t)svalue; 335288149Semaste if (log) 336288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 337288149Semaste break; 338288149Semaste 339288149Semaste case DW_OP_const2u: 340288149Semaste // push immediate 2 byte value 341288149Semaste value = addressSpace.get16(p); 342288149Semaste p += 2; 343288149Semaste *(++sp) = value; 344288149Semaste if (log) 345288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 346288149Semaste break; 347288149Semaste 348288149Semaste case DW_OP_const2s: 349288149Semaste // push immediate 2 byte signed value 350288149Semaste svalue = (int16_t) addressSpace.get16(p); 351288149Semaste p += 2; 352288149Semaste *(++sp) = (pint_t)svalue; 353288149Semaste if (log) 354288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 355288149Semaste break; 356288149Semaste 357288149Semaste case DW_OP_const4u: 358288149Semaste // push immediate 4 byte value 359288149Semaste value = addressSpace.get32(p); 360288149Semaste p += 4; 361288149Semaste *(++sp) = value; 362288149Semaste if (log) 363288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 364288149Semaste break; 365288149Semaste 366288149Semaste case DW_OP_const4s: 367288149Semaste // push immediate 4 byte signed value 368288149Semaste svalue = (int32_t)addressSpace.get32(p); 369288149Semaste p += 4; 370288149Semaste *(++sp) = (pint_t)svalue; 371288149Semaste if (log) 372288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 373288149Semaste break; 374288149Semaste 375288149Semaste case DW_OP_const8u: 376288149Semaste // push immediate 8 byte value 377288149Semaste value = (pint_t)addressSpace.get64(p); 378288149Semaste p += 8; 379288149Semaste *(++sp) = value; 380288149Semaste if (log) 381288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 382288149Semaste break; 383288149Semaste 384288149Semaste case DW_OP_const8s: 385288149Semaste // push immediate 8 byte signed value 386288149Semaste value = (pint_t)addressSpace.get64(p); 387288149Semaste p += 8; 388288149Semaste *(++sp) = value; 389288149Semaste if (log) 390288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 391288149Semaste break; 392288149Semaste 393288149Semaste case DW_OP_constu: 394288149Semaste // push immediate ULEB128 value 395288149Semaste value = (pint_t)addressSpace.getULEB128(p, expressionEnd); 396288149Semaste *(++sp) = value; 397288149Semaste if (log) 398288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value); 399288149Semaste break; 400288149Semaste 401288149Semaste case DW_OP_consts: 402288149Semaste // push immediate SLEB128 value 403288149Semaste svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); 404288149Semaste *(++sp) = (pint_t)svalue; 405288149Semaste if (log) 406288149Semaste fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue); 407288149Semaste break; 408288149Semaste 409288149Semaste case DW_OP_dup: 410288149Semaste // push top of stack 411288149Semaste value = *sp; 412288149Semaste *(++sp) = value; 413288149Semaste if (log) 414288149Semaste fprintf(stderr, "duplicate top of stack\n"); 415288149Semaste break; 416288149Semaste 417288149Semaste case DW_OP_drop: 418288149Semaste // pop 419288149Semaste --sp; 420288149Semaste if (log) 421288149Semaste fprintf(stderr, "pop top of stack\n"); 422288149Semaste break; 423288149Semaste 424288149Semaste case DW_OP_over: 425288149Semaste // dup second 426288149Semaste value = sp[-1]; 427288149Semaste *(++sp) = value; 428288149Semaste if (log) 429288149Semaste fprintf(stderr, "duplicate second in stack\n"); 430288149Semaste break; 431288149Semaste 432288149Semaste case DW_OP_pick: 433288149Semaste // pick from 434288149Semaste reg = addressSpace.get8(p); 435288149Semaste p += 1; 436360784Sdim value = sp[-(int)reg]; 437288149Semaste *(++sp) = value; 438288149Semaste if (log) 439288149Semaste fprintf(stderr, "duplicate %d in stack\n", reg); 440288149Semaste break; 441288149Semaste 442288149Semaste case DW_OP_swap: 443288149Semaste // swap top two 444288149Semaste value = sp[0]; 445288149Semaste sp[0] = sp[-1]; 446288149Semaste sp[-1] = value; 447288149Semaste if (log) 448288149Semaste fprintf(stderr, "swap top of stack\n"); 449288149Semaste break; 450288149Semaste 451288149Semaste case DW_OP_rot: 452288149Semaste // rotate top three 453288149Semaste value = sp[0]; 454288149Semaste sp[0] = sp[-1]; 455288149Semaste sp[-1] = sp[-2]; 456288149Semaste sp[-2] = value; 457288149Semaste if (log) 458288149Semaste fprintf(stderr, "rotate top three of stack\n"); 459288149Semaste break; 460288149Semaste 461288149Semaste case DW_OP_xderef: 462288149Semaste // pop stack, dereference, push result 463288149Semaste value = *sp--; 464288149Semaste *sp = *((pint_t*)value); 465288149Semaste if (log) 466288149Semaste fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value); 467288149Semaste break; 468288149Semaste 469288149Semaste case DW_OP_abs: 470288149Semaste svalue = (sint_t)*sp; 471288149Semaste if (svalue < 0) 472288149Semaste *sp = (pint_t)(-svalue); 473288149Semaste if (log) 474288149Semaste fprintf(stderr, "abs\n"); 475288149Semaste break; 476288149Semaste 477288149Semaste case DW_OP_and: 478288149Semaste value = *sp--; 479288149Semaste *sp &= value; 480288149Semaste if (log) 481288149Semaste fprintf(stderr, "and\n"); 482288149Semaste break; 483288149Semaste 484288149Semaste case DW_OP_div: 485288149Semaste svalue = (sint_t)(*sp--); 486288149Semaste svalue2 = (sint_t)*sp; 487288149Semaste *sp = (pint_t)(svalue2 / svalue); 488288149Semaste if (log) 489288149Semaste fprintf(stderr, "div\n"); 490288149Semaste break; 491288149Semaste 492288149Semaste case DW_OP_minus: 493288149Semaste value = *sp--; 494288149Semaste *sp = *sp - value; 495288149Semaste if (log) 496288149Semaste fprintf(stderr, "minus\n"); 497288149Semaste break; 498288149Semaste 499288149Semaste case DW_OP_mod: 500288149Semaste svalue = (sint_t)(*sp--); 501288149Semaste svalue2 = (sint_t)*sp; 502288149Semaste *sp = (pint_t)(svalue2 % svalue); 503288149Semaste if (log) 504288149Semaste fprintf(stderr, "module\n"); 505288149Semaste break; 506288149Semaste 507288149Semaste case DW_OP_mul: 508288149Semaste svalue = (sint_t)(*sp--); 509288149Semaste svalue2 = (sint_t)*sp; 510288149Semaste *sp = (pint_t)(svalue2 * svalue); 511288149Semaste if (log) 512288149Semaste fprintf(stderr, "mul\n"); 513288149Semaste break; 514288149Semaste 515288149Semaste case DW_OP_neg: 516288149Semaste *sp = 0 - *sp; 517288149Semaste if (log) 518288149Semaste fprintf(stderr, "neg\n"); 519288149Semaste break; 520288149Semaste 521288149Semaste case DW_OP_not: 522288149Semaste svalue = (sint_t)(*sp); 523288149Semaste *sp = (pint_t)(~svalue); 524288149Semaste if (log) 525288149Semaste fprintf(stderr, "not\n"); 526288149Semaste break; 527288149Semaste 528288149Semaste case DW_OP_or: 529288149Semaste value = *sp--; 530288149Semaste *sp |= value; 531288149Semaste if (log) 532288149Semaste fprintf(stderr, "or\n"); 533288149Semaste break; 534288149Semaste 535288149Semaste case DW_OP_plus: 536288149Semaste value = *sp--; 537288149Semaste *sp += value; 538288149Semaste if (log) 539288149Semaste fprintf(stderr, "plus\n"); 540288149Semaste break; 541288149Semaste 542288149Semaste case DW_OP_plus_uconst: 543288149Semaste // pop stack, add uelb128 constant, push result 544345018Sdim *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd)); 545288149Semaste if (log) 546288149Semaste fprintf(stderr, "add constant\n"); 547288149Semaste break; 548288149Semaste 549288149Semaste case DW_OP_shl: 550288149Semaste value = *sp--; 551288149Semaste *sp = *sp << value; 552288149Semaste if (log) 553288149Semaste fprintf(stderr, "shift left\n"); 554288149Semaste break; 555288149Semaste 556288149Semaste case DW_OP_shr: 557288149Semaste value = *sp--; 558288149Semaste *sp = *sp >> value; 559288149Semaste if (log) 560288149Semaste fprintf(stderr, "shift left\n"); 561288149Semaste break; 562288149Semaste 563288149Semaste case DW_OP_shra: 564288149Semaste value = *sp--; 565288149Semaste svalue = (sint_t)*sp; 566288149Semaste *sp = (pint_t)(svalue >> value); 567288149Semaste if (log) 568288149Semaste fprintf(stderr, "shift left arithmetric\n"); 569288149Semaste break; 570288149Semaste 571288149Semaste case DW_OP_xor: 572288149Semaste value = *sp--; 573288149Semaste *sp ^= value; 574288149Semaste if (log) 575288149Semaste fprintf(stderr, "xor\n"); 576288149Semaste break; 577288149Semaste 578288149Semaste case DW_OP_skip: 579288149Semaste svalue = (int16_t) addressSpace.get16(p); 580288149Semaste p += 2; 581288149Semaste p = (pint_t)((sint_t)p + svalue); 582288149Semaste if (log) 583288149Semaste fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue); 584288149Semaste break; 585288149Semaste 586288149Semaste case DW_OP_bra: 587288149Semaste svalue = (int16_t) addressSpace.get16(p); 588288149Semaste p += 2; 589288149Semaste if (*sp--) 590288149Semaste p = (pint_t)((sint_t)p + svalue); 591288149Semaste if (log) 592288149Semaste fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue); 593288149Semaste break; 594288149Semaste 595288149Semaste case DW_OP_eq: 596288149Semaste value = *sp--; 597288149Semaste *sp = (*sp == value); 598288149Semaste if (log) 599288149Semaste fprintf(stderr, "eq\n"); 600288149Semaste break; 601288149Semaste 602288149Semaste case DW_OP_ge: 603288149Semaste value = *sp--; 604288149Semaste *sp = (*sp >= value); 605288149Semaste if (log) 606288149Semaste fprintf(stderr, "ge\n"); 607288149Semaste break; 608288149Semaste 609288149Semaste case DW_OP_gt: 610288149Semaste value = *sp--; 611288149Semaste *sp = (*sp > value); 612288149Semaste if (log) 613288149Semaste fprintf(stderr, "gt\n"); 614288149Semaste break; 615288149Semaste 616288149Semaste case DW_OP_le: 617288149Semaste value = *sp--; 618288149Semaste *sp = (*sp <= value); 619288149Semaste if (log) 620288149Semaste fprintf(stderr, "le\n"); 621288149Semaste break; 622288149Semaste 623288149Semaste case DW_OP_lt: 624288149Semaste value = *sp--; 625288149Semaste *sp = (*sp < value); 626288149Semaste if (log) 627288149Semaste fprintf(stderr, "lt\n"); 628288149Semaste break; 629288149Semaste 630288149Semaste case DW_OP_ne: 631288149Semaste value = *sp--; 632288149Semaste *sp = (*sp != value); 633288149Semaste if (log) 634288149Semaste fprintf(stderr, "ne\n"); 635288149Semaste break; 636288149Semaste 637288149Semaste case DW_OP_lit0: 638288149Semaste case DW_OP_lit1: 639288149Semaste case DW_OP_lit2: 640288149Semaste case DW_OP_lit3: 641288149Semaste case DW_OP_lit4: 642288149Semaste case DW_OP_lit5: 643288149Semaste case DW_OP_lit6: 644288149Semaste case DW_OP_lit7: 645288149Semaste case DW_OP_lit8: 646288149Semaste case DW_OP_lit9: 647288149Semaste case DW_OP_lit10: 648288149Semaste case DW_OP_lit11: 649288149Semaste case DW_OP_lit12: 650288149Semaste case DW_OP_lit13: 651288149Semaste case DW_OP_lit14: 652288149Semaste case DW_OP_lit15: 653288149Semaste case DW_OP_lit16: 654288149Semaste case DW_OP_lit17: 655288149Semaste case DW_OP_lit18: 656288149Semaste case DW_OP_lit19: 657288149Semaste case DW_OP_lit20: 658288149Semaste case DW_OP_lit21: 659288149Semaste case DW_OP_lit22: 660288149Semaste case DW_OP_lit23: 661288149Semaste case DW_OP_lit24: 662288149Semaste case DW_OP_lit25: 663288149Semaste case DW_OP_lit26: 664288149Semaste case DW_OP_lit27: 665288149Semaste case DW_OP_lit28: 666288149Semaste case DW_OP_lit29: 667288149Semaste case DW_OP_lit30: 668288149Semaste case DW_OP_lit31: 669288149Semaste value = static_cast<pint_t>(opcode - DW_OP_lit0); 670288149Semaste *(++sp) = value; 671288149Semaste if (log) 672288149Semaste fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value); 673288149Semaste break; 674288149Semaste 675288149Semaste case DW_OP_reg0: 676288149Semaste case DW_OP_reg1: 677288149Semaste case DW_OP_reg2: 678288149Semaste case DW_OP_reg3: 679288149Semaste case DW_OP_reg4: 680288149Semaste case DW_OP_reg5: 681288149Semaste case DW_OP_reg6: 682288149Semaste case DW_OP_reg7: 683288149Semaste case DW_OP_reg8: 684288149Semaste case DW_OP_reg9: 685288149Semaste case DW_OP_reg10: 686288149Semaste case DW_OP_reg11: 687288149Semaste case DW_OP_reg12: 688288149Semaste case DW_OP_reg13: 689288149Semaste case DW_OP_reg14: 690288149Semaste case DW_OP_reg15: 691288149Semaste case DW_OP_reg16: 692288149Semaste case DW_OP_reg17: 693288149Semaste case DW_OP_reg18: 694288149Semaste case DW_OP_reg19: 695288149Semaste case DW_OP_reg20: 696288149Semaste case DW_OP_reg21: 697288149Semaste case DW_OP_reg22: 698288149Semaste case DW_OP_reg23: 699288149Semaste case DW_OP_reg24: 700288149Semaste case DW_OP_reg25: 701288149Semaste case DW_OP_reg26: 702288149Semaste case DW_OP_reg27: 703288149Semaste case DW_OP_reg28: 704288149Semaste case DW_OP_reg29: 705288149Semaste case DW_OP_reg30: 706288149Semaste case DW_OP_reg31: 707288149Semaste reg = static_cast<uint32_t>(opcode - DW_OP_reg0); 708288149Semaste *(++sp) = registers.getRegister((int)reg); 709288149Semaste if (log) 710288149Semaste fprintf(stderr, "push reg %d\n", reg); 711288149Semaste break; 712288149Semaste 713288149Semaste case DW_OP_regx: 714288149Semaste reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd)); 715288149Semaste *(++sp) = registers.getRegister((int)reg); 716288149Semaste if (log) 717288149Semaste fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); 718288149Semaste break; 719288149Semaste 720288149Semaste case DW_OP_breg0: 721288149Semaste case DW_OP_breg1: 722288149Semaste case DW_OP_breg2: 723288149Semaste case DW_OP_breg3: 724288149Semaste case DW_OP_breg4: 725288149Semaste case DW_OP_breg5: 726288149Semaste case DW_OP_breg6: 727288149Semaste case DW_OP_breg7: 728288149Semaste case DW_OP_breg8: 729288149Semaste case DW_OP_breg9: 730288149Semaste case DW_OP_breg10: 731288149Semaste case DW_OP_breg11: 732288149Semaste case DW_OP_breg12: 733288149Semaste case DW_OP_breg13: 734288149Semaste case DW_OP_breg14: 735288149Semaste case DW_OP_breg15: 736288149Semaste case DW_OP_breg16: 737288149Semaste case DW_OP_breg17: 738288149Semaste case DW_OP_breg18: 739288149Semaste case DW_OP_breg19: 740288149Semaste case DW_OP_breg20: 741288149Semaste case DW_OP_breg21: 742288149Semaste case DW_OP_breg22: 743288149Semaste case DW_OP_breg23: 744288149Semaste case DW_OP_breg24: 745288149Semaste case DW_OP_breg25: 746288149Semaste case DW_OP_breg26: 747288149Semaste case DW_OP_breg27: 748288149Semaste case DW_OP_breg28: 749288149Semaste case DW_OP_breg29: 750288149Semaste case DW_OP_breg30: 751288149Semaste case DW_OP_breg31: 752288149Semaste reg = static_cast<uint32_t>(opcode - DW_OP_breg0); 753288149Semaste svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); 754288149Semaste svalue += static_cast<sint_t>(registers.getRegister((int)reg)); 755288149Semaste *(++sp) = (pint_t)(svalue); 756288149Semaste if (log) 757288149Semaste fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); 758288149Semaste break; 759288149Semaste 760288149Semaste case DW_OP_bregx: 761288149Semaste reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd)); 762288149Semaste svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd); 763288149Semaste svalue += static_cast<sint_t>(registers.getRegister((int)reg)); 764288149Semaste *(++sp) = (pint_t)(svalue); 765288149Semaste if (log) 766288149Semaste fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue); 767288149Semaste break; 768288149Semaste 769288149Semaste case DW_OP_fbreg: 770288149Semaste _LIBUNWIND_ABORT("DW_OP_fbreg not implemented"); 771288149Semaste break; 772288149Semaste 773288149Semaste case DW_OP_piece: 774288149Semaste _LIBUNWIND_ABORT("DW_OP_piece not implemented"); 775288149Semaste break; 776288149Semaste 777288149Semaste case DW_OP_deref_size: 778288149Semaste // pop stack, dereference, push result 779288149Semaste value = *sp--; 780288149Semaste switch (addressSpace.get8(p++)) { 781288149Semaste case 1: 782288149Semaste value = addressSpace.get8(value); 783288149Semaste break; 784288149Semaste case 2: 785288149Semaste value = addressSpace.get16(value); 786288149Semaste break; 787288149Semaste case 4: 788288149Semaste value = addressSpace.get32(value); 789288149Semaste break; 790288149Semaste case 8: 791288149Semaste value = (pint_t)addressSpace.get64(value); 792288149Semaste break; 793288149Semaste default: 794288149Semaste _LIBUNWIND_ABORT("DW_OP_deref_size with bad size"); 795288149Semaste } 796288149Semaste *(++sp) = value; 797288149Semaste if (log) 798288149Semaste fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value); 799288149Semaste break; 800288149Semaste 801288149Semaste case DW_OP_xderef_size: 802288149Semaste case DW_OP_nop: 803288149Semaste case DW_OP_push_object_addres: 804288149Semaste case DW_OP_call2: 805288149Semaste case DW_OP_call4: 806288149Semaste case DW_OP_call_ref: 807288149Semaste default: 808345018Sdim _LIBUNWIND_ABORT("DWARF opcode not implemented"); 809288149Semaste } 810288149Semaste 811288149Semaste } 812288149Semaste if (log) 813288149Semaste fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp); 814288149Semaste return *sp; 815288149Semaste} 816288149Semaste 817288149Semaste 818288149Semaste 819288149Semaste} // namespace libunwind 820288149Semaste 821288149Semaste#endif // __DWARF_INSTRUCTIONS_HPP__ 822