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