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