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