1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8//  Processor specific interpretation of DWARF unwind info.
9//
10//===----------------------------------------------------------------------===//
11
12#ifndef __DWARF_INSTRUCTIONS_HPP__
13#define __DWARF_INSTRUCTIONS_HPP__
14
15#include <stdint.h>
16#include <stdio.h>
17#include <stdlib.h>
18
19#include "DwarfParser.hpp"
20#include "Registers.hpp"
21#include "config.h"
22#include "dwarf2.h"
23#include "libunwind_ext.h"
24
25
26namespace libunwind {
27
28
29/// DwarfInstructions maps abstract DWARF unwind instructions to a particular
30/// architecture
31template <typename A, typename R>
32class DwarfInstructions {
33public:
34  typedef typename A::pint_t pint_t;
35  typedef typename A::sint_t sint_t;
36
37  static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
38                           R &registers, bool &isSignalFrame, bool stage2);
39
40private:
41
42  enum {
43    DW_X86_64_RET_ADDR = 16
44  };
45
46  enum {
47    DW_X86_RET_ADDR = 8
48  };
49
50  typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
51  typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
52  typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
53  typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
54
55  static pint_t evaluateExpression(pint_t expression, A &addressSpace,
56                                   const R &registers,
57                                   pint_t initialStackValue);
58  static pint_t getSavedRegister(A &addressSpace, const R &registers,
59                                 pint_t cfa, const RegisterLocation &savedReg);
60  static double getSavedFloatRegister(A &addressSpace, const R &registers,
61                                  pint_t cfa, const RegisterLocation &savedReg);
62  static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
63                                  pint_t cfa, const RegisterLocation &savedReg);
64
65  static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
66                       const R &registers) {
67    if (prolog.cfaRegister != 0)
68      return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
69             prolog.cfaRegisterOffset);
70    if (prolog.cfaExpression != 0)
71      return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
72                                registers, 0);
73    assert(0 && "getCFA(): unknown location");
74    __builtin_unreachable();
75  }
76#if defined(_LIBUNWIND_TARGET_AARCH64)
77  static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa,
78                               PrologInfo &prolog);
79#endif
80};
81
82template <typename R>
83auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {
84  return r.getWCookie();
85}
86template <typename R> uint64_t getSparcWCookie(const R &, long) {
87  return 0;
88}
89
90template <typename A, typename R>
91typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
92    A &addressSpace, const R &registers, pint_t cfa,
93    const RegisterLocation &savedReg) {
94  switch (savedReg.location) {
95  case CFI_Parser<A>::kRegisterInCFA:
96    return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
97
98  case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific
99    return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^
100           getSparcWCookie(registers, 0));
101
102  case CFI_Parser<A>::kRegisterAtExpression:
103    return (pint_t)addressSpace.getRegister(evaluateExpression(
104        (pint_t)savedReg.value, addressSpace, registers, cfa));
105
106  case CFI_Parser<A>::kRegisterIsExpression:
107    return evaluateExpression((pint_t)savedReg.value, addressSpace,
108                              registers, cfa);
109
110  case CFI_Parser<A>::kRegisterInRegister:
111    return registers.getRegister((int)savedReg.value);
112  case CFI_Parser<A>::kRegisterUndefined:
113    return 0;
114  case CFI_Parser<A>::kRegisterUnused:
115  case CFI_Parser<A>::kRegisterOffsetFromCFA:
116    // FIX ME
117    break;
118  }
119  _LIBUNWIND_ABORT("unsupported restore location for register");
120}
121
122template <typename A, typename R>
123double DwarfInstructions<A, R>::getSavedFloatRegister(
124    A &addressSpace, const R &registers, pint_t cfa,
125    const RegisterLocation &savedReg) {
126  switch (savedReg.location) {
127  case CFI_Parser<A>::kRegisterInCFA:
128    return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
129
130  case CFI_Parser<A>::kRegisterAtExpression:
131    return addressSpace.getDouble(
132        evaluateExpression((pint_t)savedReg.value, addressSpace,
133                            registers, cfa));
134  case CFI_Parser<A>::kRegisterUndefined:
135    return 0.0;
136  case CFI_Parser<A>::kRegisterInRegister:
137#ifndef _LIBUNWIND_TARGET_ARM
138    return registers.getFloatRegister((int)savedReg.value);
139#endif
140  case CFI_Parser<A>::kRegisterIsExpression:
141  case CFI_Parser<A>::kRegisterUnused:
142  case CFI_Parser<A>::kRegisterOffsetFromCFA:
143  case CFI_Parser<A>::kRegisterInCFADecrypt:
144    // FIX ME
145    break;
146  }
147  _LIBUNWIND_ABORT("unsupported restore location for float register");
148}
149
150template <typename A, typename R>
151v128 DwarfInstructions<A, R>::getSavedVectorRegister(
152    A &addressSpace, const R &registers, pint_t cfa,
153    const RegisterLocation &savedReg) {
154  switch (savedReg.location) {
155  case CFI_Parser<A>::kRegisterInCFA:
156    return addressSpace.getVector(cfa + (pint_t)savedReg.value);
157
158  case CFI_Parser<A>::kRegisterAtExpression:
159    return addressSpace.getVector(
160        evaluateExpression((pint_t)savedReg.value, addressSpace,
161                            registers, cfa));
162
163  case CFI_Parser<A>::kRegisterIsExpression:
164  case CFI_Parser<A>::kRegisterUnused:
165  case CFI_Parser<A>::kRegisterUndefined:
166  case CFI_Parser<A>::kRegisterOffsetFromCFA:
167  case CFI_Parser<A>::kRegisterInRegister:
168  case CFI_Parser<A>::kRegisterInCFADecrypt:
169    // FIX ME
170    break;
171  }
172  _LIBUNWIND_ABORT("unsupported restore location for vector register");
173}
174#if defined(_LIBUNWIND_TARGET_AARCH64)
175template <typename A, typename R>
176bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
177                                               pint_t cfa, PrologInfo &prolog) {
178  pint_t raSignState;
179  auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
180  if (regloc.location == CFI_Parser<A>::kRegisterUnused)
181    raSignState = static_cast<pint_t>(regloc.value);
182  else
183    raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
184
185  // Only bit[0] is meaningful.
186  return raSignState & 0x01;
187}
188#endif
189
190template <typename A, typename R>
191int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
192                                           pint_t fdeStart, R &registers,
193                                           bool &isSignalFrame, bool stage2) {
194  FDE_Info fdeInfo;
195  CIE_Info cieInfo;
196  if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
197                               &cieInfo) == NULL) {
198    PrologInfo prolog;
199    if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
200                                            R::getArch(), &prolog)) {
201      // get pointer to cfa (architecture specific)
202      pint_t cfa = getCFA(addressSpace, prolog, registers);
203
204      (void)stage2;
205      // __unw_step_stage2 is not used for cross unwinding, so we use
206      // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are
207      // building for AArch64 natively.
208#if defined(__aarch64__)
209      if (stage2 && cieInfo.mteTaggedFrame) {
210        pint_t sp = registers.getSP();
211        pint_t p = sp;
212        // AArch64 doesn't require the value of SP to be 16-byte aligned at
213        // all times, only at memory accesses and public interfaces [1]. Thus,
214        // a signal could arrive at a point where SP is not aligned properly.
215        // In that case, the kernel fixes up [2] the signal frame, but we
216        // still have a misaligned SP in the previous frame. If that signal
217        // handler caused stack unwinding, we would have an unaligned SP.
218        // We do not need to fix up the CFA, as that is the SP at a "public
219        // interface".
220        // [1]:
221        // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack
222        // [2]:
223        // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718
224        p &= ~0xfULL;
225        // CFA is the bottom of the current stack frame.
226        for (; p < cfa; p += 16) {
227          __asm__ __volatile__(".arch armv8.5-a\n"
228                               ".arch_extension memtag\n"
229                               "stg %[Ptr], [%[Ptr]]\n"
230                               :
231                               : [Ptr] "r"(p)
232                               : "memory");
233        }
234      }
235#endif
236      // restore registers that DWARF says were saved
237      R newRegisters = registers;
238
239      // Typically, the CFA is the stack pointer at the call site in
240      // the previous frame. However, there are scenarios in which this is not
241      // true. For example, if we switched to a new stack. In that case, the
242      // value of the previous SP might be indicated by a CFI directive.
243      //
244      // We set the SP here to the CFA, allowing for it to be overridden
245      // by a CFI directive later on.
246      newRegisters.setSP(cfa);
247
248      pint_t returnAddress = 0;
249      constexpr int lastReg = R::lastDwarfRegNum();
250      static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=
251                        lastReg,
252                    "register range too large");
253      assert(lastReg >= (int)cieInfo.returnAddressRegister &&
254             "register range does not contain return address register");
255      for (int i = 0; i <= lastReg; ++i) {
256        if (prolog.savedRegisters[i].location !=
257            CFI_Parser<A>::kRegisterUnused) {
258          if (registers.validFloatRegister(i))
259            newRegisters.setFloatRegister(
260                i, getSavedFloatRegister(addressSpace, registers, cfa,
261                                         prolog.savedRegisters[i]));
262          else if (registers.validVectorRegister(i))
263            newRegisters.setVectorRegister(
264                i, getSavedVectorRegister(addressSpace, registers, cfa,
265                                          prolog.savedRegisters[i]));
266          else if (i == (int)cieInfo.returnAddressRegister)
267            returnAddress = getSavedRegister(addressSpace, registers, cfa,
268                                             prolog.savedRegisters[i]);
269          else if (registers.validRegister(i))
270            newRegisters.setRegister(
271                i, getSavedRegister(addressSpace, registers, cfa,
272                                    prolog.savedRegisters[i]));
273          else
274            return UNW_EBADREG;
275        } else if (i == (int)cieInfo.returnAddressRegister) {
276            // Leaf function keeps the return address in register and there is no
277            // explicit instructions how to restore it.
278            returnAddress = registers.getRegister(cieInfo.returnAddressRegister);
279        }
280      }
281
282      isSignalFrame = cieInfo.isSignalFrame;
283
284#if defined(_LIBUNWIND_TARGET_AARCH64)
285      // If the target is aarch64 then the return address may have been signed
286      // using the v8.3 pointer authentication extensions. The original
287      // return address needs to be authenticated before the return address is
288      // restored. autia1716 is used instead of autia as autia1716 assembles
289      // to a NOP on pre-v8.3a architectures.
290      if ((R::getArch() == REGISTERS_ARM64) &&
291          getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) &&
292          returnAddress != 0) {
293#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
294        return UNW_ECROSSRASIGNING;
295#else
296        register unsigned long long x17 __asm("x17") = returnAddress;
297        register unsigned long long x16 __asm("x16") = cfa;
298
299        // These are the autia1716/autib1716 instructions. The hint instructions
300        // are used here as gcc does not assemble autia1716/autib1716 for pre
301        // armv8.3a targets.
302        if (cieInfo.addressesSignedWithBKey)
303          asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
304        else
305          asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
306        returnAddress = x17;
307#endif
308      }
309#endif
310
311#if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) &&    \
312    defined(__ARM_FEATURE_PAUTH)
313      if ((R::getArch() == REGISTERS_ARM) &&
314          prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE].value) {
315        pint_t pac =
316            getSavedRegister(addressSpace, registers, cfa,
317                             prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE]);
318        __asm__ __volatile__("autg %0, %1, %2"
319                             :
320                             : "r"(pac), "r"(returnAddress), "r"(cfa)
321                             :);
322      }
323#endif
324
325#if defined(_LIBUNWIND_TARGET_SPARC)
326      if (R::getArch() == REGISTERS_SPARC) {
327        // Skip call site instruction and delay slot
328        returnAddress += 8;
329        // Skip unimp instruction if function returns a struct
330        if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
331          returnAddress += 4;
332      }
333#endif
334
335#if defined(_LIBUNWIND_TARGET_SPARC64)
336      // Skip call site instruction and delay slot.
337      if (R::getArch() == REGISTERS_SPARC64)
338        returnAddress += 8;
339#endif
340
341#if defined(_LIBUNWIND_TARGET_PPC64)
342#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
343#define PPC64_ELFV1_R2_OFFSET 40
344#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
345#define PPC64_ELFV2_R2_OFFSET 24
346      // If the instruction at return address is a TOC (r2) restore,
347      // then r2 was saved and needs to be restored.
348      // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
349      // while in ELFv1 ABI it is saved at SP + 40.
350      if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) {
351        pint_t sp = newRegisters.getRegister(UNW_REG_SP);
352        pint_t r2 = 0;
353        switch (addressSpace.get32(returnAddress)) {
354        case PPC64_ELFV1_R2_LOAD_INST_ENCODING:
355          r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET);
356          break;
357        case PPC64_ELFV2_R2_LOAD_INST_ENCODING:
358          r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET);
359          break;
360        }
361        if (r2)
362          newRegisters.setRegister(UNW_PPC64_R2, r2);
363      }
364#endif
365
366      // Return address is address after call site instruction, so setting IP to
367      // that does simulates a return.
368      newRegisters.setIP(returnAddress);
369
370      // Simulate the step by replacing the register set with the new ones.
371      registers = newRegisters;
372
373      return UNW_STEP_SUCCESS;
374    }
375  }
376  return UNW_EBADFRAME;
377}
378
379template <typename A, typename R>
380typename A::pint_t
381DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
382                                            const R &registers,
383                                            pint_t initialStackValue) {
384  const bool log = false;
385  pint_t p = expression;
386  pint_t expressionEnd = expression + 20; // temp, until len read
387  pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
388  expressionEnd = p + length;
389  if (log)
390    fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
391            (uint64_t)length);
392  pint_t stack[100];
393  pint_t *sp = stack;
394  *(++sp) = initialStackValue;
395
396  while (p < expressionEnd) {
397    if (log) {
398      for (pint_t *t = sp; t > stack; --t) {
399        fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
400      }
401    }
402    uint8_t opcode = addressSpace.get8(p++);
403    sint_t svalue, svalue2;
404    pint_t value;
405    uint32_t reg;
406    switch (opcode) {
407    case DW_OP_addr:
408      // push immediate address sized value
409      value = addressSpace.getP(p);
410      p += sizeof(pint_t);
411      *(++sp) = value;
412      if (log)
413        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
414      break;
415
416    case DW_OP_deref:
417      // pop stack, dereference, push result
418      value = *sp--;
419      *(++sp) = addressSpace.getP(value);
420      if (log)
421        fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
422      break;
423
424    case DW_OP_const1u:
425      // push immediate 1 byte value
426      value = addressSpace.get8(p);
427      p += 1;
428      *(++sp) = value;
429      if (log)
430        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
431      break;
432
433    case DW_OP_const1s:
434      // push immediate 1 byte signed value
435      svalue = (int8_t) addressSpace.get8(p);
436      p += 1;
437      *(++sp) = (pint_t)svalue;
438      if (log)
439        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
440      break;
441
442    case DW_OP_const2u:
443      // push immediate 2 byte value
444      value = addressSpace.get16(p);
445      p += 2;
446      *(++sp) = value;
447      if (log)
448        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
449      break;
450
451    case DW_OP_const2s:
452      // push immediate 2 byte signed value
453      svalue = (int16_t) addressSpace.get16(p);
454      p += 2;
455      *(++sp) = (pint_t)svalue;
456      if (log)
457        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
458      break;
459
460    case DW_OP_const4u:
461      // push immediate 4 byte value
462      value = addressSpace.get32(p);
463      p += 4;
464      *(++sp) = value;
465      if (log)
466        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
467      break;
468
469    case DW_OP_const4s:
470      // push immediate 4 byte signed value
471      svalue = (int32_t)addressSpace.get32(p);
472      p += 4;
473      *(++sp) = (pint_t)svalue;
474      if (log)
475        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
476      break;
477
478    case DW_OP_const8u:
479      // push immediate 8 byte value
480      value = (pint_t)addressSpace.get64(p);
481      p += 8;
482      *(++sp) = value;
483      if (log)
484        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
485      break;
486
487    case DW_OP_const8s:
488      // push immediate 8 byte signed value
489      value = (pint_t)addressSpace.get64(p);
490      p += 8;
491      *(++sp) = value;
492      if (log)
493        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
494      break;
495
496    case DW_OP_constu:
497      // push immediate ULEB128 value
498      value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
499      *(++sp) = value;
500      if (log)
501        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
502      break;
503
504    case DW_OP_consts:
505      // push immediate SLEB128 value
506      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
507      *(++sp) = (pint_t)svalue;
508      if (log)
509        fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
510      break;
511
512    case DW_OP_dup:
513      // push top of stack
514      value = *sp;
515      *(++sp) = value;
516      if (log)
517        fprintf(stderr, "duplicate top of stack\n");
518      break;
519
520    case DW_OP_drop:
521      // pop
522      --sp;
523      if (log)
524        fprintf(stderr, "pop top of stack\n");
525      break;
526
527    case DW_OP_over:
528      // dup second
529      value = sp[-1];
530      *(++sp) = value;
531      if (log)
532        fprintf(stderr, "duplicate second in stack\n");
533      break;
534
535    case DW_OP_pick:
536      // pick from
537      reg = addressSpace.get8(p);
538      p += 1;
539      value = sp[-(int)reg];
540      *(++sp) = value;
541      if (log)
542        fprintf(stderr, "duplicate %d in stack\n", reg);
543      break;
544
545    case DW_OP_swap:
546      // swap top two
547      value = sp[0];
548      sp[0] = sp[-1];
549      sp[-1] = value;
550      if (log)
551        fprintf(stderr, "swap top of stack\n");
552      break;
553
554    case DW_OP_rot:
555      // rotate top three
556      value = sp[0];
557      sp[0] = sp[-1];
558      sp[-1] = sp[-2];
559      sp[-2] = value;
560      if (log)
561        fprintf(stderr, "rotate top three of stack\n");
562      break;
563
564    case DW_OP_xderef:
565      // pop stack, dereference, push result
566      value = *sp--;
567      *sp = *((pint_t*)value);
568      if (log)
569        fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
570      break;
571
572    case DW_OP_abs:
573      svalue = (sint_t)*sp;
574      if (svalue < 0)
575        *sp = (pint_t)(-svalue);
576      if (log)
577        fprintf(stderr, "abs\n");
578      break;
579
580    case DW_OP_and:
581      value = *sp--;
582      *sp &= value;
583      if (log)
584        fprintf(stderr, "and\n");
585      break;
586
587    case DW_OP_div:
588      svalue = (sint_t)(*sp--);
589      svalue2 = (sint_t)*sp;
590      *sp = (pint_t)(svalue2 / svalue);
591      if (log)
592        fprintf(stderr, "div\n");
593      break;
594
595    case DW_OP_minus:
596      value = *sp--;
597      *sp = *sp - value;
598      if (log)
599        fprintf(stderr, "minus\n");
600      break;
601
602    case DW_OP_mod:
603      svalue = (sint_t)(*sp--);
604      svalue2 = (sint_t)*sp;
605      *sp = (pint_t)(svalue2 % svalue);
606      if (log)
607        fprintf(stderr, "module\n");
608      break;
609
610    case DW_OP_mul:
611      svalue = (sint_t)(*sp--);
612      svalue2 = (sint_t)*sp;
613      *sp = (pint_t)(svalue2 * svalue);
614      if (log)
615        fprintf(stderr, "mul\n");
616      break;
617
618    case DW_OP_neg:
619      *sp = 0 - *sp;
620      if (log)
621        fprintf(stderr, "neg\n");
622      break;
623
624    case DW_OP_not:
625      svalue = (sint_t)(*sp);
626      *sp = (pint_t)(~svalue);
627      if (log)
628        fprintf(stderr, "not\n");
629      break;
630
631    case DW_OP_or:
632      value = *sp--;
633      *sp |= value;
634      if (log)
635        fprintf(stderr, "or\n");
636      break;
637
638    case DW_OP_plus:
639      value = *sp--;
640      *sp += value;
641      if (log)
642        fprintf(stderr, "plus\n");
643      break;
644
645    case DW_OP_plus_uconst:
646      // pop stack, add uelb128 constant, push result
647      *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
648      if (log)
649        fprintf(stderr, "add constant\n");
650      break;
651
652    case DW_OP_shl:
653      value = *sp--;
654      *sp = *sp << value;
655      if (log)
656        fprintf(stderr, "shift left\n");
657      break;
658
659    case DW_OP_shr:
660      value = *sp--;
661      *sp = *sp >> value;
662      if (log)
663        fprintf(stderr, "shift left\n");
664      break;
665
666    case DW_OP_shra:
667      value = *sp--;
668      svalue = (sint_t)*sp;
669      *sp = (pint_t)(svalue >> value);
670      if (log)
671        fprintf(stderr, "shift left arithmetic\n");
672      break;
673
674    case DW_OP_xor:
675      value = *sp--;
676      *sp ^= value;
677      if (log)
678        fprintf(stderr, "xor\n");
679      break;
680
681    case DW_OP_skip:
682      svalue = (int16_t) addressSpace.get16(p);
683      p += 2;
684      p = (pint_t)((sint_t)p + svalue);
685      if (log)
686        fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
687      break;
688
689    case DW_OP_bra:
690      svalue = (int16_t) addressSpace.get16(p);
691      p += 2;
692      if (*sp--)
693        p = (pint_t)((sint_t)p + svalue);
694      if (log)
695        fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
696      break;
697
698    case DW_OP_eq:
699      value = *sp--;
700      *sp = (*sp == value);
701      if (log)
702        fprintf(stderr, "eq\n");
703      break;
704
705    case DW_OP_ge:
706      value = *sp--;
707      *sp = (*sp >= value);
708      if (log)
709        fprintf(stderr, "ge\n");
710      break;
711
712    case DW_OP_gt:
713      value = *sp--;
714      *sp = (*sp > value);
715      if (log)
716        fprintf(stderr, "gt\n");
717      break;
718
719    case DW_OP_le:
720      value = *sp--;
721      *sp = (*sp <= value);
722      if (log)
723        fprintf(stderr, "le\n");
724      break;
725
726    case DW_OP_lt:
727      value = *sp--;
728      *sp = (*sp < value);
729      if (log)
730        fprintf(stderr, "lt\n");
731      break;
732
733    case DW_OP_ne:
734      value = *sp--;
735      *sp = (*sp != value);
736      if (log)
737        fprintf(stderr, "ne\n");
738      break;
739
740    case DW_OP_lit0:
741    case DW_OP_lit1:
742    case DW_OP_lit2:
743    case DW_OP_lit3:
744    case DW_OP_lit4:
745    case DW_OP_lit5:
746    case DW_OP_lit6:
747    case DW_OP_lit7:
748    case DW_OP_lit8:
749    case DW_OP_lit9:
750    case DW_OP_lit10:
751    case DW_OP_lit11:
752    case DW_OP_lit12:
753    case DW_OP_lit13:
754    case DW_OP_lit14:
755    case DW_OP_lit15:
756    case DW_OP_lit16:
757    case DW_OP_lit17:
758    case DW_OP_lit18:
759    case DW_OP_lit19:
760    case DW_OP_lit20:
761    case DW_OP_lit21:
762    case DW_OP_lit22:
763    case DW_OP_lit23:
764    case DW_OP_lit24:
765    case DW_OP_lit25:
766    case DW_OP_lit26:
767    case DW_OP_lit27:
768    case DW_OP_lit28:
769    case DW_OP_lit29:
770    case DW_OP_lit30:
771    case DW_OP_lit31:
772      value = static_cast<pint_t>(opcode - DW_OP_lit0);
773      *(++sp) = value;
774      if (log)
775        fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
776      break;
777
778    case DW_OP_reg0:
779    case DW_OP_reg1:
780    case DW_OP_reg2:
781    case DW_OP_reg3:
782    case DW_OP_reg4:
783    case DW_OP_reg5:
784    case DW_OP_reg6:
785    case DW_OP_reg7:
786    case DW_OP_reg8:
787    case DW_OP_reg9:
788    case DW_OP_reg10:
789    case DW_OP_reg11:
790    case DW_OP_reg12:
791    case DW_OP_reg13:
792    case DW_OP_reg14:
793    case DW_OP_reg15:
794    case DW_OP_reg16:
795    case DW_OP_reg17:
796    case DW_OP_reg18:
797    case DW_OP_reg19:
798    case DW_OP_reg20:
799    case DW_OP_reg21:
800    case DW_OP_reg22:
801    case DW_OP_reg23:
802    case DW_OP_reg24:
803    case DW_OP_reg25:
804    case DW_OP_reg26:
805    case DW_OP_reg27:
806    case DW_OP_reg28:
807    case DW_OP_reg29:
808    case DW_OP_reg30:
809    case DW_OP_reg31:
810      reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
811      *(++sp) = registers.getRegister((int)reg);
812      if (log)
813        fprintf(stderr, "push reg %d\n", reg);
814      break;
815
816    case DW_OP_regx:
817      reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
818      *(++sp) = registers.getRegister((int)reg);
819      if (log)
820        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
821      break;
822
823    case DW_OP_breg0:
824    case DW_OP_breg1:
825    case DW_OP_breg2:
826    case DW_OP_breg3:
827    case DW_OP_breg4:
828    case DW_OP_breg5:
829    case DW_OP_breg6:
830    case DW_OP_breg7:
831    case DW_OP_breg8:
832    case DW_OP_breg9:
833    case DW_OP_breg10:
834    case DW_OP_breg11:
835    case DW_OP_breg12:
836    case DW_OP_breg13:
837    case DW_OP_breg14:
838    case DW_OP_breg15:
839    case DW_OP_breg16:
840    case DW_OP_breg17:
841    case DW_OP_breg18:
842    case DW_OP_breg19:
843    case DW_OP_breg20:
844    case DW_OP_breg21:
845    case DW_OP_breg22:
846    case DW_OP_breg23:
847    case DW_OP_breg24:
848    case DW_OP_breg25:
849    case DW_OP_breg26:
850    case DW_OP_breg27:
851    case DW_OP_breg28:
852    case DW_OP_breg29:
853    case DW_OP_breg30:
854    case DW_OP_breg31:
855      reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
856      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
857      svalue += static_cast<sint_t>(registers.getRegister((int)reg));
858      *(++sp) = (pint_t)(svalue);
859      if (log)
860        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
861      break;
862
863    case DW_OP_bregx:
864      reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
865      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
866      svalue += static_cast<sint_t>(registers.getRegister((int)reg));
867      *(++sp) = (pint_t)(svalue);
868      if (log)
869        fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
870      break;
871
872    case DW_OP_fbreg:
873      _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
874      break;
875
876    case DW_OP_piece:
877      _LIBUNWIND_ABORT("DW_OP_piece not implemented");
878      break;
879
880    case DW_OP_deref_size:
881      // pop stack, dereference, push result
882      value = *sp--;
883      switch (addressSpace.get8(p++)) {
884      case 1:
885        value = addressSpace.get8(value);
886        break;
887      case 2:
888        value = addressSpace.get16(value);
889        break;
890      case 4:
891        value = addressSpace.get32(value);
892        break;
893      case 8:
894        value = (pint_t)addressSpace.get64(value);
895        break;
896      default:
897        _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
898      }
899      *(++sp) = value;
900      if (log)
901        fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
902      break;
903
904    case DW_OP_xderef_size:
905    case DW_OP_nop:
906    case DW_OP_push_object_addres:
907    case DW_OP_call2:
908    case DW_OP_call4:
909    case DW_OP_call_ref:
910    default:
911      _LIBUNWIND_ABORT("DWARF opcode not implemented");
912    }
913
914  }
915  if (log)
916    fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
917  return *sp;
918}
919
920
921
922} // namespace libunwind
923
924#endif // __DWARF_INSTRUCTIONS_HPP__
925