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