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, &fdeInfo,
160                                &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=%" PRIu64 "\n",
227             (uint64_t)length);
228   pint_t stack[100];
229   pint_t *sp = stack;
230   *(++sp) = initialStackValue;
231 
232   while (p < expressionEnd) {
233     if (log) {
234       for (pint_t *t = sp; t > stack; --t) {
235         fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
236       }
237     }
238     uint8_t opcode = addressSpace.get8(p++);
239     sint_t svalue, svalue2;
240     pint_t value;
241     uint32_t reg;
242     switch (opcode) {
243     case DW_OP_addr:
244       // push immediate address sized value
245       value = addressSpace.getP(p);
246       p += sizeof(pint_t);
247       *(++sp) = value;
248       if (log)
249         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
250       break;
251 
252     case DW_OP_deref:
253       // pop stack, dereference, push result
254       value = *sp--;
255       *(++sp) = addressSpace.getP(value);
256       if (log)
257         fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
258       break;
259 
260     case DW_OP_const1u:
261       // push immediate 1 byte value
262       value = addressSpace.get8(p);
263       p += 1;
264       *(++sp) = value;
265       if (log)
266         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
267       break;
268 
269     case DW_OP_const1s:
270       // push immediate 1 byte signed value
271       svalue = (int8_t) addressSpace.get8(p);
272       p += 1;
273       *(++sp) = (pint_t)svalue;
274       if (log)
275         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
276       break;
277 
278     case DW_OP_const2u:
279       // push immediate 2 byte value
280       value = addressSpace.get16(p);
281       p += 2;
282       *(++sp) = value;
283       if (log)
284         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
285       break;
286 
287     case DW_OP_const2s:
288       // push immediate 2 byte signed value
289       svalue = (int16_t) addressSpace.get16(p);
290       p += 2;
291       *(++sp) = (pint_t)svalue;
292       if (log)
293         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
294       break;
295 
296     case DW_OP_const4u:
297       // push immediate 4 byte value
298       value = addressSpace.get32(p);
299       p += 4;
300       *(++sp) = value;
301       if (log)
302         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
303       break;
304 
305     case DW_OP_const4s:
306       // push immediate 4 byte signed value
307       svalue = (int32_t)addressSpace.get32(p);
308       p += 4;
309       *(++sp) = (pint_t)svalue;
310       if (log)
311         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
312       break;
313 
314     case DW_OP_const8u:
315       // push immediate 8 byte value
316       value = (pint_t)addressSpace.get64(p);
317       p += 8;
318       *(++sp) = value;
319       if (log)
320         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
321       break;
322 
323     case DW_OP_const8s:
324       // push immediate 8 byte signed value
325       value = (pint_t)addressSpace.get64(p);
326       p += 8;
327       *(++sp) = value;
328       if (log)
329         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
330       break;
331 
332     case DW_OP_constu:
333       // push immediate ULEB128 value
334       value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
335       *(++sp) = value;
336       if (log)
337         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
338       break;
339 
340     case DW_OP_consts:
341       // push immediate SLEB128 value
342       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
343       *(++sp) = (pint_t)svalue;
344       if (log)
345         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
346       break;
347 
348     case DW_OP_dup:
349       // push top of stack
350       value = *sp;
351       *(++sp) = value;
352       if (log)
353         fprintf(stderr, "duplicate top of stack\n");
354       break;
355 
356     case DW_OP_drop:
357       // pop
358       --sp;
359       if (log)
360         fprintf(stderr, "pop top of stack\n");
361       break;
362 
363     case DW_OP_over:
364       // dup second
365       value = sp[-1];
366       *(++sp) = value;
367       if (log)
368         fprintf(stderr, "duplicate second in stack\n");
369       break;
370 
371     case DW_OP_pick:
372       // pick from
373       reg = addressSpace.get8(p);
374       p += 1;
375       value = sp[-reg];
376       *(++sp) = value;
377       if (log)
378         fprintf(stderr, "duplicate %d in stack\n", reg);
379       break;
380 
381     case DW_OP_swap:
382       // swap top two
383       value = sp[0];
384       sp[0] = sp[-1];
385       sp[-1] = value;
386       if (log)
387         fprintf(stderr, "swap top of stack\n");
388       break;
389 
390     case DW_OP_rot:
391       // rotate top three
392       value = sp[0];
393       sp[0] = sp[-1];
394       sp[-1] = sp[-2];
395       sp[-2] = value;
396       if (log)
397         fprintf(stderr, "rotate top three of stack\n");
398       break;
399 
400     case DW_OP_xderef:
401       // pop stack, dereference, push result
402       value = *sp--;
403       *sp = *((pint_t*)value);
404       if (log)
405         fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
406       break;
407 
408     case DW_OP_abs:
409       svalue = (sint_t)*sp;
410       if (svalue < 0)
411         *sp = (pint_t)(-svalue);
412       if (log)
413         fprintf(stderr, "abs\n");
414       break;
415 
416     case DW_OP_and:
417       value = *sp--;
418       *sp &= value;
419       if (log)
420         fprintf(stderr, "and\n");
421       break;
422 
423     case DW_OP_div:
424       svalue = (sint_t)(*sp--);
425       svalue2 = (sint_t)*sp;
426       *sp = (pint_t)(svalue2 / svalue);
427       if (log)
428         fprintf(stderr, "div\n");
429       break;
430 
431     case DW_OP_minus:
432       value = *sp--;
433       *sp = *sp - value;
434       if (log)
435         fprintf(stderr, "minus\n");
436       break;
437 
438     case DW_OP_mod:
439       svalue = (sint_t)(*sp--);
440       svalue2 = (sint_t)*sp;
441       *sp = (pint_t)(svalue2 % svalue);
442       if (log)
443         fprintf(stderr, "module\n");
444       break;
445 
446     case DW_OP_mul:
447       svalue = (sint_t)(*sp--);
448       svalue2 = (sint_t)*sp;
449       *sp = (pint_t)(svalue2 * svalue);
450       if (log)
451         fprintf(stderr, "mul\n");
452       break;
453 
454     case DW_OP_neg:
455       *sp = 0 - *sp;
456       if (log)
457         fprintf(stderr, "neg\n");
458       break;
459 
460     case DW_OP_not:
461       svalue = (sint_t)(*sp);
462       *sp = (pint_t)(~svalue);
463       if (log)
464         fprintf(stderr, "not\n");
465       break;
466 
467     case DW_OP_or:
468       value = *sp--;
469       *sp |= value;
470       if (log)
471         fprintf(stderr, "or\n");
472       break;
473 
474     case DW_OP_plus:
475       value = *sp--;
476       *sp += value;
477       if (log)
478         fprintf(stderr, "plus\n");
479       break;
480 
481     case DW_OP_plus_uconst:
482       // pop stack, add uelb128 constant, push result
483       *sp += addressSpace.getULEB128(p, expressionEnd);
484       if (log)
485         fprintf(stderr, "add constant\n");
486       break;
487 
488     case DW_OP_shl:
489       value = *sp--;
490       *sp = *sp << value;
491       if (log)
492         fprintf(stderr, "shift left\n");
493       break;
494 
495     case DW_OP_shr:
496       value = *sp--;
497       *sp = *sp >> value;
498       if (log)
499         fprintf(stderr, "shift left\n");
500       break;
501 
502     case DW_OP_shra:
503       value = *sp--;
504       svalue = (sint_t)*sp;
505       *sp = (pint_t)(svalue >> value);
506       if (log)
507         fprintf(stderr, "shift left arithmetric\n");
508       break;
509 
510     case DW_OP_xor:
511       value = *sp--;
512       *sp ^= value;
513       if (log)
514         fprintf(stderr, "xor\n");
515       break;
516 
517     case DW_OP_skip:
518       svalue = (int16_t) addressSpace.get16(p);
519       p += 2;
520       p = (pint_t)((sint_t)p + svalue);
521       if (log)
522         fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
523       break;
524 
525     case DW_OP_bra:
526       svalue = (int16_t) addressSpace.get16(p);
527       p += 2;
528       if (*sp--)
529         p = (pint_t)((sint_t)p + svalue);
530       if (log)
531         fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
532       break;
533 
534     case DW_OP_eq:
535       value = *sp--;
536       *sp = (*sp == value);
537       if (log)
538         fprintf(stderr, "eq\n");
539       break;
540 
541     case DW_OP_ge:
542       value = *sp--;
543       *sp = (*sp >= value);
544       if (log)
545         fprintf(stderr, "ge\n");
546       break;
547 
548     case DW_OP_gt:
549       value = *sp--;
550       *sp = (*sp > value);
551       if (log)
552         fprintf(stderr, "gt\n");
553       break;
554 
555     case DW_OP_le:
556       value = *sp--;
557       *sp = (*sp <= value);
558       if (log)
559         fprintf(stderr, "le\n");
560       break;
561 
562     case DW_OP_lt:
563       value = *sp--;
564       *sp = (*sp < value);
565       if (log)
566         fprintf(stderr, "lt\n");
567       break;
568 
569     case DW_OP_ne:
570       value = *sp--;
571       *sp = (*sp != value);
572       if (log)
573         fprintf(stderr, "ne\n");
574       break;
575 
576     case DW_OP_lit0:
577     case DW_OP_lit1:
578     case DW_OP_lit2:
579     case DW_OP_lit3:
580     case DW_OP_lit4:
581     case DW_OP_lit5:
582     case DW_OP_lit6:
583     case DW_OP_lit7:
584     case DW_OP_lit8:
585     case DW_OP_lit9:
586     case DW_OP_lit10:
587     case DW_OP_lit11:
588     case DW_OP_lit12:
589     case DW_OP_lit13:
590     case DW_OP_lit14:
591     case DW_OP_lit15:
592     case DW_OP_lit16:
593     case DW_OP_lit17:
594     case DW_OP_lit18:
595     case DW_OP_lit19:
596     case DW_OP_lit20:
597     case DW_OP_lit21:
598     case DW_OP_lit22:
599     case DW_OP_lit23:
600     case DW_OP_lit24:
601     case DW_OP_lit25:
602     case DW_OP_lit26:
603     case DW_OP_lit27:
604     case DW_OP_lit28:
605     case DW_OP_lit29:
606     case DW_OP_lit30:
607     case DW_OP_lit31:
608       value = static_cast<pint_t>(opcode - DW_OP_lit0);
609       *(++sp) = value;
610       if (log)
611         fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
612       break;
613 
614     case DW_OP_reg0:
615     case DW_OP_reg1:
616     case DW_OP_reg2:
617     case DW_OP_reg3:
618     case DW_OP_reg4:
619     case DW_OP_reg5:
620     case DW_OP_reg6:
621     case DW_OP_reg7:
622     case DW_OP_reg8:
623     case DW_OP_reg9:
624     case DW_OP_reg10:
625     case DW_OP_reg11:
626     case DW_OP_reg12:
627     case DW_OP_reg13:
628     case DW_OP_reg14:
629     case DW_OP_reg15:
630     case DW_OP_reg16:
631     case DW_OP_reg17:
632     case DW_OP_reg18:
633     case DW_OP_reg19:
634     case DW_OP_reg20:
635     case DW_OP_reg21:
636     case DW_OP_reg22:
637     case DW_OP_reg23:
638     case DW_OP_reg24:
639     case DW_OP_reg25:
640     case DW_OP_reg26:
641     case DW_OP_reg27:
642     case DW_OP_reg28:
643     case DW_OP_reg29:
644     case DW_OP_reg30:
645     case DW_OP_reg31:
646       reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
647       *(++sp) = registers.getRegister((int)reg);
648       if (log)
649         fprintf(stderr, "push reg %d\n", reg);
650       break;
651 
652     case DW_OP_regx:
653       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
654       *(++sp) = registers.getRegister((int)reg);
655       if (log)
656         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
657       break;
658 
659     case DW_OP_breg0:
660     case DW_OP_breg1:
661     case DW_OP_breg2:
662     case DW_OP_breg3:
663     case DW_OP_breg4:
664     case DW_OP_breg5:
665     case DW_OP_breg6:
666     case DW_OP_breg7:
667     case DW_OP_breg8:
668     case DW_OP_breg9:
669     case DW_OP_breg10:
670     case DW_OP_breg11:
671     case DW_OP_breg12:
672     case DW_OP_breg13:
673     case DW_OP_breg14:
674     case DW_OP_breg15:
675     case DW_OP_breg16:
676     case DW_OP_breg17:
677     case DW_OP_breg18:
678     case DW_OP_breg19:
679     case DW_OP_breg20:
680     case DW_OP_breg21:
681     case DW_OP_breg22:
682     case DW_OP_breg23:
683     case DW_OP_breg24:
684     case DW_OP_breg25:
685     case DW_OP_breg26:
686     case DW_OP_breg27:
687     case DW_OP_breg28:
688     case DW_OP_breg29:
689     case DW_OP_breg30:
690     case DW_OP_breg31:
691       reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
692       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
693       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
694       *(++sp) = (pint_t)(svalue);
695       if (log)
696         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
697       break;
698 
699     case DW_OP_bregx:
700       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
701       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
702       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
703       *(++sp) = (pint_t)(svalue);
704       if (log)
705         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
706       break;
707 
708     case DW_OP_fbreg:
709       _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
710       break;
711 
712     case DW_OP_piece:
713       _LIBUNWIND_ABORT("DW_OP_piece not implemented");
714       break;
715 
716     case DW_OP_deref_size:
717       // pop stack, dereference, push result
718       value = *sp--;
719       switch (addressSpace.get8(p++)) {
720       case 1:
721         value = addressSpace.get8(value);
722         break;
723       case 2:
724         value = addressSpace.get16(value);
725         break;
726       case 4:
727         value = addressSpace.get32(value);
728         break;
729       case 8:
730         value = (pint_t)addressSpace.get64(value);
731         break;
732       default:
733         _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
734       }
735       *(++sp) = value;
736       if (log)
737         fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
738       break;
739 
740     case DW_OP_xderef_size:
741     case DW_OP_nop:
742     case DW_OP_push_object_addres:
743     case DW_OP_call2:
744     case DW_OP_call4:
745     case DW_OP_call_ref:
746     default:
747       _LIBUNWIND_ABORT("dwarf opcode not implemented");
748     }
749 
750   }
751   if (log)
752     fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
753   return *sp;
754 }
755 
756 
757 
758 } // namespace libunwind
759 
760 #endif // __DWARF_INSTRUCTIONS_HPP__
761