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