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
26namespace libunwind {
27
28
29/// DwarfInstructions maps abtract DWARF unwind instructions to a particular
30/// architecture
31template <typename A, typename R>
32class DwarfInstructions {
33public:
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
40private:
41
42  enum {
43    DW_X86_64_RET_ADDR = 16
44  };
45
46  enum {
47    DW_X86_RET_ADDR = 8
48  };
49
50  typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
51  typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
52  typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
53  typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
54
55  static pint_t evaluateExpression(pint_t expression, A &addressSpace,
56                                   const R &registers,
57                                   pint_t initialStackValue);
58  static pint_t getSavedRegister(A &addressSpace, const R &registers,
59                                 pint_t cfa, const RegisterLocation &savedReg);
60  static double getSavedFloatRegister(A &addressSpace, const R &registers,
61                                  pint_t cfa, const RegisterLocation &savedReg);
62  static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
63                                  pint_t cfa, const RegisterLocation &savedReg);
64
65  static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
66                       const R &registers) {
67    if (prolog.cfaRegister != 0)
68      return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
69             prolog.cfaRegisterOffset);
70    if (prolog.cfaExpression != 0)
71      return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
72                                registers, 0);
73    assert(0 && "getCFA(): unknown location");
74    __builtin_unreachable();
75  }
76};
77
78
79template <typename A, typename R>
80typename 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
107template <typename A, typename R>
108double 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
130template <typename A, typename R>
131v128 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
153template <typename A, typename R>
154int 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(static_cast<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
214template <typename A, typename R>
215typename A::pint_t
216DwarfInstructions<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