• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Registers.hpp"
22 #include "DwarfParser.hpp"
23 #include "config.h"
24 
25 
26 namespace libunwind {
27 
28 
29 /// DwarfInstructions maps abtract 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);
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 
getCFA(A & addressSpace,const PrologInfo & prolog,const R & registers)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 };
77 
78 
79 template <typename A, typename R>
getSavedRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)80 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
81     A &addressSpace, const R &registers, pint_t cfa,
82     const RegisterLocation &savedReg) {
83   switch (savedReg.location) {
84   case CFI_Parser<A>::kRegisterInCFA:
85     return addressSpace.getP(cfa + (pint_t)savedReg.value);
86 
87   case CFI_Parser<A>::kRegisterAtExpression:
88     return addressSpace.getP(
89         evaluateExpression((pint_t)savedReg.value, addressSpace,
90                             registers, cfa));
91 
92   case CFI_Parser<A>::kRegisterIsExpression:
93     return evaluateExpression((pint_t)savedReg.value, addressSpace,
94                               registers, cfa);
95 
96   case CFI_Parser<A>::kRegisterInRegister:
97     return registers.getRegister((int)savedReg.value);
98 
99   case CFI_Parser<A>::kRegisterUnused:
100   case CFI_Parser<A>::kRegisterOffsetFromCFA:
101     // FIX ME
102     break;
103   }
104   _LIBUNWIND_ABORT("unsupported restore location for register");
105 }
106 
107 template <typename A, typename R>
getSavedFloatRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)108 double DwarfInstructions<A, R>::getSavedFloatRegister(
109     A &addressSpace, const R &registers, pint_t cfa,
110     const RegisterLocation &savedReg) {
111   switch (savedReg.location) {
112   case CFI_Parser<A>::kRegisterInCFA:
113     return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
114 
115   case CFI_Parser<A>::kRegisterAtExpression:
116     return addressSpace.getDouble(
117         evaluateExpression((pint_t)savedReg.value, addressSpace,
118                             registers, cfa));
119 
120   case CFI_Parser<A>::kRegisterIsExpression:
121   case CFI_Parser<A>::kRegisterUnused:
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>::kRegisterOffsetFromCFA:
146   case CFI_Parser<A>::kRegisterInRegister:
147     // FIX ME
148     break;
149   }
150   _LIBUNWIND_ABORT("unsupported restore location for vector register");
151 }
152 
153 template <typename A, typename R>
stepWithDwarf(A & addressSpace,pint_t pc,pint_t fdeStart,R & registers)154 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
155                                            pint_t fdeStart, R &registers) {
156   FDE_Info fdeInfo;
157   CIE_Info cieInfo;
158   if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
159                                &cieInfo) == NULL) {
160     PrologInfo prolog;
161     if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
162                                             &prolog)) {
163       // get pointer to cfa (architecture specific)
164       pint_t cfa = getCFA(addressSpace, prolog, registers);
165 
166        // restore registers that DWARF says were saved
167       R newRegisters = registers;
168       pint_t returnAddress = 0;
169       const int lastReg = R::lastDwarfRegNum();
170       assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg &&
171              "register range too large");
172       assert(lastReg >= (int)cieInfo.returnAddressRegister &&
173              "register range does not contain return address register");
174       for (int i = 0; i <= lastReg; ++i) {
175         if (prolog.savedRegisters[i].location !=
176             CFI_Parser<A>::kRegisterUnused) {
177           if (registers.validFloatRegister(i))
178             newRegisters.setFloatRegister(
179                 i, getSavedFloatRegister(addressSpace, registers, cfa,
180                                          prolog.savedRegisters[i]));
181           else if (registers.validVectorRegister(i))
182             newRegisters.setVectorRegister(
183                 i, getSavedVectorRegister(addressSpace, registers, cfa,
184                                           prolog.savedRegisters[i]));
185           else if (i == (int)cieInfo.returnAddressRegister)
186             returnAddress = getSavedRegister(addressSpace, registers, cfa,
187                                              prolog.savedRegisters[i]);
188           else if (registers.validRegister(i))
189             newRegisters.setRegister(
190                 i, getSavedRegister(addressSpace, registers, cfa,
191                                     prolog.savedRegisters[i]));
192           else
193             return UNW_EBADREG;
194         }
195       }
196 
197       // By definition, the CFA is the stack pointer at the call site, so
198       // restoring SP means setting it to CFA.
199       newRegisters.setSP(cfa);
200 
201       // Return address is address after call site instruction, so setting IP to
202       // that does simualates a return.
203       newRegisters.setIP(returnAddress);
204 
205       // Simulate the step by replacing the register set with the new ones.
206       registers = newRegisters;
207 
208       return UNW_STEP_SUCCESS;
209     }
210   }
211   return UNW_EBADFRAME;
212 }
213 
214 template <typename A, typename R>
215 typename A::pint_t
evaluateExpression(pint_t expression,A & addressSpace,const R & registers,pint_t initialStackValue)216 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
217                                             const R &registers,
218                                             pint_t initialStackValue) {
219   const bool log = false;
220   pint_t p = expression;
221   pint_t expressionEnd = expression + 20; // temp, until len read
222   pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
223   expressionEnd = p + length;
224   if (log)
225     fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
226             (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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\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 += static_cast<pint_t>(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 %" PRIu64 "\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 %" PRIu64 "\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 = static_cast<pint_t>(opcode - DW_OP_lit0);
608       *(++sp) = value;
609       if (log)
610         fprintf(stderr, "push literal 0x%" PRIx64 "\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 = static_cast<uint32_t>(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 = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
653       *(++sp) = registers.getRegister((int)reg);
654       if (log)
655         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\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 = static_cast<uint32_t>(opcode - DW_OP_breg0);
691       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
692       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
693       *(++sp) = (pint_t)(svalue);
694       if (log)
695         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
696       break;
697 
698     case DW_OP_bregx:
699       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
700       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
701       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
702       *(++sp) = (pint_t)(svalue);
703       if (log)
704         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\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%" PRIx64 "\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%" PRIx64 "\n", (uint64_t)*sp);
752   return *sp;
753 }
754 
755 
756 
757 } // namespace libunwind
758 
759 #endif // __DWARF_INSTRUCTIONS_HPP__
760