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 &registers, 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 &registers,
56288149Semaste                                   pint_t initialStackValue);
57288149Semaste  static pint_t getSavedRegister(A &addressSpace, const R &registers,
58288149Semaste                                 pint_t cfa, const RegisterLocation &savedReg);
59288149Semaste  static double getSavedFloatRegister(A &addressSpace, const R &registers,
60288149Semaste                                  pint_t cfa, const RegisterLocation &savedReg);
61288149Semaste  static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
62288149Semaste                                  pint_t cfa, const RegisterLocation &savedReg);
63288149Semaste
64288149Semaste  static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
65288149Semaste                       const R &registers) {
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 &registers, 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 &registers, 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 &registers, 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 &registers,
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 &registers,
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