1 //===-------------------------- DwarfInstructions.hpp ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //
9 //  Processor specific interpretation of dwarf unwind info.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef __DWARF_INSTRUCTIONS_HPP__
14 #define __DWARF_INSTRUCTIONS_HPP__
15 
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 
20 #include "dwarf2.h"
21 #include "AddressSpace.hpp"
22 #include "Registers.hpp"
23 #include "DwarfParser.hpp"
24 #include "config.h"
25 
26 
27 namespace libunwind {
28 
29 
30 /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
31 /// architecture
32 template <typename A, typename R>
33 class DwarfInstructions {
34 public:
35   typedef typename A::pint_t pint_t;
36   typedef typename A::sint_t sint_t;
37 
38   static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
39                            R &registers);
40 
41 private:
42 
43   enum {
44     DW_X86_64_RET_ADDR = 16
45   };
46 
47   enum {
48     DW_X86_RET_ADDR = 8
49   };
50 
51   typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
52   typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
53   typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
54   typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
55 
56   static pint_t evaluateExpression(pint_t expression, A &addressSpace,
57                                    const R &registers,
58                                    pint_t initialStackValue);
59   static pint_t getSavedRegister(A &addressSpace, const R &registers,
60                                  pint_t cfa, const RegisterLocation &savedReg);
61   static double getSavedFloatRegister(A &addressSpace, const R &registers,
62                                   pint_t cfa, const RegisterLocation &savedReg);
63   static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
64                                   pint_t cfa, const RegisterLocation &savedReg);
65 
getCFA(A & addressSpace,const PrologInfo & prolog,const R & registers)66   static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
67                        const R &registers) {
68     if (prolog.cfaRegister != 0)
69       return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
70              prolog.cfaRegisterOffset);
71     if (prolog.cfaExpression != 0)
72       return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
73                                 registers, 0);
74     assert(0 && "getCFA(): unknown location");
75     __builtin_unreachable();
76   }
77 };
78 
79 
80 template <typename A, typename R>
getSavedRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)81 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
82     A &addressSpace, const R &registers, pint_t cfa,
83     const RegisterLocation &savedReg) {
84   switch (savedReg.location) {
85   case CFI_Parser<A>::kRegisterInCFA:
86     return addressSpace.getP(cfa + (pint_t)savedReg.value);
87 
88   case CFI_Parser<A>::kRegisterAtExpression:
89     return addressSpace.getP(
90         evaluateExpression((pint_t)savedReg.value, addressSpace,
91                             registers, cfa));
92 
93   case CFI_Parser<A>::kRegisterIsExpression:
94     return evaluateExpression((pint_t)savedReg.value, addressSpace,
95                               registers, cfa);
96 
97   case CFI_Parser<A>::kRegisterInRegister:
98     return registers.getRegister((int)savedReg.value);
99 
100   case CFI_Parser<A>::kRegisterUnused:
101   case CFI_Parser<A>::kRegisterOffsetFromCFA:
102     // FIX ME
103     break;
104   }
105   _LIBUNWIND_ABORT("unsupported restore location for register");
106 }
107 
108 template <typename A, typename R>
getSavedFloatRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)109 double DwarfInstructions<A, R>::getSavedFloatRegister(
110     A &addressSpace, const R &registers, pint_t cfa,
111     const RegisterLocation &savedReg) {
112   switch (savedReg.location) {
113   case CFI_Parser<A>::kRegisterInCFA:
114     return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
115 
116   case CFI_Parser<A>::kRegisterAtExpression:
117     return addressSpace.getDouble(
118         evaluateExpression((pint_t)savedReg.value, addressSpace,
119                             registers, cfa));
120 
121   case CFI_Parser<A>::kRegisterIsExpression:
122   case CFI_Parser<A>::kRegisterUnused:
123   case CFI_Parser<A>::kRegisterOffsetFromCFA:
124   case CFI_Parser<A>::kRegisterInRegister:
125     // FIX ME
126     break;
127   }
128   _LIBUNWIND_ABORT("unsupported restore location for float register");
129 }
130 
131 template <typename A, typename R>
getSavedVectorRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)132 v128 DwarfInstructions<A, R>::getSavedVectorRegister(
133     A &addressSpace, const R &registers, pint_t cfa,
134     const RegisterLocation &savedReg) {
135   switch (savedReg.location) {
136   case CFI_Parser<A>::kRegisterInCFA:
137     return addressSpace.getVector(cfa + (pint_t)savedReg.value);
138 
139   case CFI_Parser<A>::kRegisterAtExpression:
140     return addressSpace.getVector(
141         evaluateExpression((pint_t)savedReg.value, addressSpace,
142                             registers, cfa));
143 
144   case CFI_Parser<A>::kRegisterIsExpression:
145   case CFI_Parser<A>::kRegisterUnused:
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)155 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
156                                            pint_t fdeStart, R &registers) {
157   FDE_Info fdeInfo;
158   CIE_Info cieInfo;
159   if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart,
160                                                   &fdeInfo, &cieInfo) == NULL) {
161     PrologInfo prolog;
162     if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
163                                                                      &prolog)) {
164       // get pointer to cfa (architecture specific)
165       pint_t cfa = getCFA(addressSpace, prolog, registers);
166 
167        // restore registers that dwarf says were saved
168       R newRegisters = registers;
169       pint_t returnAddress = 0;
170       const int lastReg = R::lastDwarfRegNum();
171       assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg
172                                                 && "register range too large");
173       assert(lastReg <= (int)cieInfo.returnAddressRegister
174                  && "register range does not contain return address register");
175       for (int i = 0; i <= lastReg; ++i) {
176          if (prolog.savedRegisters[i].location !=
177              CFI_Parser<A>::kRegisterUnused) {
178            if (registers.validFloatRegister(i))
179             newRegisters.setFloatRegister(
180                 i, getSavedFloatRegister(addressSpace, registers, cfa,
181                                          prolog.savedRegisters[i]));
182           else if (registers.validVectorRegister(i))
183             newRegisters.setVectorRegister(
184                 i, getSavedVectorRegister(addressSpace, registers, cfa,
185                                           prolog.savedRegisters[i]));
186           else if (i == (int)cieInfo.returnAddressRegister)
187             returnAddress = getSavedRegister(addressSpace, registers, cfa,
188                                              prolog.savedRegisters[i]);
189           else if (registers.validRegister(i))
190             newRegisters.setRegister(
191                 i, getSavedRegister(addressSpace, registers, cfa,
192                                     prolog.savedRegisters[i]));
193           else
194             return UNW_EBADREG;
195         }
196       }
197 
198       // By definition, the CFA is the stack pointer at the call site, so
199       // restoring SP means setting it to CFA.
200       newRegisters.setSP(cfa);
201 
202       // Return address is address after call site instruction, so setting IP to
203       // that does simualates a return.
204       newRegisters.setIP(returnAddress);
205 
206       // Simulate the step by replacing the register set with the new ones.
207       registers = newRegisters;
208 
209       return UNW_STEP_SUCCESS;
210     }
211   }
212   return UNW_EBADFRAME;
213 }
214 
215 template <typename A, typename R>
216 typename A::pint_t
evaluateExpression(pint_t expression,A & addressSpace,const R & registers,pint_t initialStackValue)217 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
218                                             const R &registers,
219                                             pint_t initialStackValue) {
220   const bool log = false;
221   pint_t p = expression;
222   pint_t expressionEnd = expression + 20; // temp, until len read
223   pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
224   expressionEnd = p + length;
225   if (log)
226     fprintf(stderr, "evaluateExpression(): length=%llu\n", (uint64_t)length);
227   pint_t stack[100];
228   pint_t *sp = stack;
229   *(++sp) = initialStackValue;
230 
231   while (p < expressionEnd) {
232     if (log) {
233       for (pint_t *t = sp; t > stack; --t) {
234         fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
235       }
236     }
237     uint8_t opcode = addressSpace.get8(p++);
238     sint_t svalue, svalue2;
239     pint_t value;
240     uint32_t reg;
241     switch (opcode) {
242     case DW_OP_addr:
243       // push immediate address sized value
244       value = addressSpace.getP(p);
245       p += sizeof(pint_t);
246       *(++sp) = value;
247       if (log)
248         fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
249       break;
250 
251     case DW_OP_deref:
252       // pop stack, dereference, push result
253       value = *sp--;
254       *(++sp) = addressSpace.getP(value);
255       if (log)
256         fprintf(stderr, "dereference 0x%llX\n", (uint64_t) value);
257       break;
258 
259     case DW_OP_const1u:
260       // push immediate 1 byte value
261       value = addressSpace.get8(p);
262       p += 1;
263       *(++sp) = value;
264       if (log)
265         fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
266       break;
267 
268     case DW_OP_const1s:
269       // push immediate 1 byte signed value
270       svalue = (int8_t) addressSpace.get8(p);
271       p += 1;
272       *(++sp) = (pint_t)svalue;
273       if (log)
274         fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
275       break;
276 
277     case DW_OP_const2u:
278       // push immediate 2 byte value
279       value = addressSpace.get16(p);
280       p += 2;
281       *(++sp) = value;
282       if (log)
283         fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
284       break;
285 
286     case DW_OP_const2s:
287       // push immediate 2 byte signed value
288       svalue = (int16_t) addressSpace.get16(p);
289       p += 2;
290       *(++sp) = (pint_t)svalue;
291       if (log)
292         fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
293       break;
294 
295     case DW_OP_const4u:
296       // push immediate 4 byte value
297       value = addressSpace.get32(p);
298       p += 4;
299       *(++sp) = value;
300       if (log)
301         fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
302       break;
303 
304     case DW_OP_const4s:
305       // push immediate 4 byte signed value
306       svalue = (int32_t)addressSpace.get32(p);
307       p += 4;
308       *(++sp) = (pint_t)svalue;
309       if (log)
310         fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
311       break;
312 
313     case DW_OP_const8u:
314       // push immediate 8 byte value
315       value = (pint_t)addressSpace.get64(p);
316       p += 8;
317       *(++sp) = value;
318       if (log)
319         fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
320       break;
321 
322     case DW_OP_const8s:
323       // push immediate 8 byte signed value
324       value = (pint_t)addressSpace.get64(p);
325       p += 8;
326       *(++sp) = value;
327       if (log)
328         fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
329       break;
330 
331     case DW_OP_constu:
332       // push immediate ULEB128 value
333       value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
334       *(++sp) = value;
335       if (log)
336         fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
337       break;
338 
339     case DW_OP_consts:
340       // push immediate SLEB128 value
341       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
342       *(++sp) = (pint_t)svalue;
343       if (log)
344         fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
345       break;
346 
347     case DW_OP_dup:
348       // push top of stack
349       value = *sp;
350       *(++sp) = value;
351       if (log)
352         fprintf(stderr, "duplicate top of stack\n");
353       break;
354 
355     case DW_OP_drop:
356       // pop
357       --sp;
358       if (log)
359         fprintf(stderr, "pop top of stack\n");
360       break;
361 
362     case DW_OP_over:
363       // dup second
364       value = sp[-1];
365       *(++sp) = value;
366       if (log)
367         fprintf(stderr, "duplicate second in stack\n");
368       break;
369 
370     case DW_OP_pick:
371       // pick from
372       reg = addressSpace.get8(p);
373       p += 1;
374       value = sp[-reg];
375       *(++sp) = value;
376       if (log)
377         fprintf(stderr, "duplicate %d in stack\n", reg);
378       break;
379 
380     case DW_OP_swap:
381       // swap top two
382       value = sp[0];
383       sp[0] = sp[-1];
384       sp[-1] = value;
385       if (log)
386         fprintf(stderr, "swap top of stack\n");
387       break;
388 
389     case DW_OP_rot:
390       // rotate top three
391       value = sp[0];
392       sp[0] = sp[-1];
393       sp[-1] = sp[-2];
394       sp[-2] = value;
395       if (log)
396         fprintf(stderr, "rotate top three of stack\n");
397       break;
398 
399     case DW_OP_xderef:
400       // pop stack, dereference, push result
401       value = *sp--;
402       *sp = *((pint_t*)value);
403       if (log)
404         fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t) value);
405       break;
406 
407     case DW_OP_abs:
408       svalue = (sint_t)*sp;
409       if (svalue < 0)
410         *sp = (pint_t)(-svalue);
411       if (log)
412         fprintf(stderr, "abs\n");
413       break;
414 
415     case DW_OP_and:
416       value = *sp--;
417       *sp &= value;
418       if (log)
419         fprintf(stderr, "and\n");
420       break;
421 
422     case DW_OP_div:
423       svalue = (sint_t)(*sp--);
424       svalue2 = (sint_t)*sp;
425       *sp = (pint_t)(svalue2 / svalue);
426       if (log)
427         fprintf(stderr, "div\n");
428       break;
429 
430     case DW_OP_minus:
431       value = *sp--;
432       *sp = *sp - value;
433       if (log)
434         fprintf(stderr, "minus\n");
435       break;
436 
437     case DW_OP_mod:
438       svalue = (sint_t)(*sp--);
439       svalue2 = (sint_t)*sp;
440       *sp = (pint_t)(svalue2 % svalue);
441       if (log)
442         fprintf(stderr, "module\n");
443       break;
444 
445     case DW_OP_mul:
446       svalue = (sint_t)(*sp--);
447       svalue2 = (sint_t)*sp;
448       *sp = (pint_t)(svalue2 * svalue);
449       if (log)
450         fprintf(stderr, "mul\n");
451       break;
452 
453     case DW_OP_neg:
454       *sp = 0 - *sp;
455       if (log)
456         fprintf(stderr, "neg\n");
457       break;
458 
459     case DW_OP_not:
460       svalue = (sint_t)(*sp);
461       *sp = (pint_t)(~svalue);
462       if (log)
463         fprintf(stderr, "not\n");
464       break;
465 
466     case DW_OP_or:
467       value = *sp--;
468       *sp |= value;
469       if (log)
470         fprintf(stderr, "or\n");
471       break;
472 
473     case DW_OP_plus:
474       value = *sp--;
475       *sp += value;
476       if (log)
477         fprintf(stderr, "plus\n");
478       break;
479 
480     case DW_OP_plus_uconst:
481       // pop stack, add uelb128 constant, push result
482       *sp += addressSpace.getULEB128(p, expressionEnd);
483       if (log)
484         fprintf(stderr, "add constant\n");
485       break;
486 
487     case DW_OP_shl:
488       value = *sp--;
489       *sp = *sp << value;
490       if (log)
491         fprintf(stderr, "shift left\n");
492       break;
493 
494     case DW_OP_shr:
495       value = *sp--;
496       *sp = *sp >> value;
497       if (log)
498         fprintf(stderr, "shift left\n");
499       break;
500 
501     case DW_OP_shra:
502       value = *sp--;
503       svalue = (sint_t)*sp;
504       *sp = (pint_t)(svalue >> value);
505       if (log)
506         fprintf(stderr, "shift left arithmetric\n");
507       break;
508 
509     case DW_OP_xor:
510       value = *sp--;
511       *sp ^= value;
512       if (log)
513         fprintf(stderr, "xor\n");
514       break;
515 
516     case DW_OP_skip:
517       svalue = (int16_t) addressSpace.get16(p);
518       p += 2;
519       p = (pint_t)((sint_t)p + svalue);
520       if (log)
521         fprintf(stderr, "skip %lld\n", (uint64_t) svalue);
522       break;
523 
524     case DW_OP_bra:
525       svalue = (int16_t) addressSpace.get16(p);
526       p += 2;
527       if (*sp--)
528         p = (pint_t)((sint_t)p + svalue);
529       if (log)
530         fprintf(stderr, "bra %lld\n", (uint64_t) svalue);
531       break;
532 
533     case DW_OP_eq:
534       value = *sp--;
535       *sp = (*sp == value);
536       if (log)
537         fprintf(stderr, "eq\n");
538       break;
539 
540     case DW_OP_ge:
541       value = *sp--;
542       *sp = (*sp >= value);
543       if (log)
544         fprintf(stderr, "ge\n");
545       break;
546 
547     case DW_OP_gt:
548       value = *sp--;
549       *sp = (*sp > value);
550       if (log)
551         fprintf(stderr, "gt\n");
552       break;
553 
554     case DW_OP_le:
555       value = *sp--;
556       *sp = (*sp <= value);
557       if (log)
558         fprintf(stderr, "le\n");
559       break;
560 
561     case DW_OP_lt:
562       value = *sp--;
563       *sp = (*sp < value);
564       if (log)
565         fprintf(stderr, "lt\n");
566       break;
567 
568     case DW_OP_ne:
569       value = *sp--;
570       *sp = (*sp != value);
571       if (log)
572         fprintf(stderr, "ne\n");
573       break;
574 
575     case DW_OP_lit0:
576     case DW_OP_lit1:
577     case DW_OP_lit2:
578     case DW_OP_lit3:
579     case DW_OP_lit4:
580     case DW_OP_lit5:
581     case DW_OP_lit6:
582     case DW_OP_lit7:
583     case DW_OP_lit8:
584     case DW_OP_lit9:
585     case DW_OP_lit10:
586     case DW_OP_lit11:
587     case DW_OP_lit12:
588     case DW_OP_lit13:
589     case DW_OP_lit14:
590     case DW_OP_lit15:
591     case DW_OP_lit16:
592     case DW_OP_lit17:
593     case DW_OP_lit18:
594     case DW_OP_lit19:
595     case DW_OP_lit20:
596     case DW_OP_lit21:
597     case DW_OP_lit22:
598     case DW_OP_lit23:
599     case DW_OP_lit24:
600     case DW_OP_lit25:
601     case DW_OP_lit26:
602     case DW_OP_lit27:
603     case DW_OP_lit28:
604     case DW_OP_lit29:
605     case DW_OP_lit30:
606     case DW_OP_lit31:
607       value = opcode - DW_OP_lit0;
608       *(++sp) = value;
609       if (log)
610         fprintf(stderr, "push literal 0x%llX\n", (uint64_t) value);
611       break;
612 
613     case DW_OP_reg0:
614     case DW_OP_reg1:
615     case DW_OP_reg2:
616     case DW_OP_reg3:
617     case DW_OP_reg4:
618     case DW_OP_reg5:
619     case DW_OP_reg6:
620     case DW_OP_reg7:
621     case DW_OP_reg8:
622     case DW_OP_reg9:
623     case DW_OP_reg10:
624     case DW_OP_reg11:
625     case DW_OP_reg12:
626     case DW_OP_reg13:
627     case DW_OP_reg14:
628     case DW_OP_reg15:
629     case DW_OP_reg16:
630     case DW_OP_reg17:
631     case DW_OP_reg18:
632     case DW_OP_reg19:
633     case DW_OP_reg20:
634     case DW_OP_reg21:
635     case DW_OP_reg22:
636     case DW_OP_reg23:
637     case DW_OP_reg24:
638     case DW_OP_reg25:
639     case DW_OP_reg26:
640     case DW_OP_reg27:
641     case DW_OP_reg28:
642     case DW_OP_reg29:
643     case DW_OP_reg30:
644     case DW_OP_reg31:
645       reg = opcode - DW_OP_reg0;
646       *(++sp) = registers.getRegister((int)reg);
647       if (log)
648         fprintf(stderr, "push reg %d\n", reg);
649       break;
650 
651     case DW_OP_regx:
652       reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
653       *(++sp) = registers.getRegister((int)reg);
654       if (log)
655         fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
656       break;
657 
658     case DW_OP_breg0:
659     case DW_OP_breg1:
660     case DW_OP_breg2:
661     case DW_OP_breg3:
662     case DW_OP_breg4:
663     case DW_OP_breg5:
664     case DW_OP_breg6:
665     case DW_OP_breg7:
666     case DW_OP_breg8:
667     case DW_OP_breg9:
668     case DW_OP_breg10:
669     case DW_OP_breg11:
670     case DW_OP_breg12:
671     case DW_OP_breg13:
672     case DW_OP_breg14:
673     case DW_OP_breg15:
674     case DW_OP_breg16:
675     case DW_OP_breg17:
676     case DW_OP_breg18:
677     case DW_OP_breg19:
678     case DW_OP_breg20:
679     case DW_OP_breg21:
680     case DW_OP_breg22:
681     case DW_OP_breg23:
682     case DW_OP_breg24:
683     case DW_OP_breg25:
684     case DW_OP_breg26:
685     case DW_OP_breg27:
686     case DW_OP_breg28:
687     case DW_OP_breg29:
688     case DW_OP_breg30:
689     case DW_OP_breg31:
690       reg = opcode - DW_OP_breg0;
691       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
692       svalue += registers.getRegister((int)reg);
693       *(++sp) = (pint_t)(svalue);
694       if (log)
695         fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
696       break;
697 
698     case DW_OP_bregx:
699       reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
700       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
701       svalue += registers.getRegister((int)reg);
702       *(++sp) = (pint_t)(svalue);
703       if (log)
704         fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
705       break;
706 
707     case DW_OP_fbreg:
708       _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
709       break;
710 
711     case DW_OP_piece:
712       _LIBUNWIND_ABORT("DW_OP_piece not implemented");
713       break;
714 
715     case DW_OP_deref_size:
716       // pop stack, dereference, push result
717       value = *sp--;
718       switch (addressSpace.get8(p++)) {
719       case 1:
720         value = addressSpace.get8(value);
721         break;
722       case 2:
723         value = addressSpace.get16(value);
724         break;
725       case 4:
726         value = addressSpace.get32(value);
727         break;
728       case 8:
729         value = (pint_t)addressSpace.get64(value);
730         break;
731       default:
732         _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
733       }
734       *(++sp) = value;
735       if (log)
736         fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t) value);
737       break;
738 
739     case DW_OP_xderef_size:
740     case DW_OP_nop:
741     case DW_OP_push_object_addres:
742     case DW_OP_call2:
743     case DW_OP_call4:
744     case DW_OP_call_ref:
745     default:
746       _LIBUNWIND_ABORT("dwarf opcode not implemented");
747     }
748 
749   }
750   if (log)
751     fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t) * sp);
752   return *sp;
753 }
754 
755 
756 
757 } // namespace libunwind
758 
759 #endif // __DWARF_INSTRUCTIONS_HPP__
760