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