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