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 ®isters);
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 ®isters,
58 pint_t initialStackValue);
59 static pint_t getSavedRegister(A &addressSpace, const R ®isters,
60 pint_t cfa, const RegisterLocation &savedReg);
61 static double getSavedFloatRegister(A &addressSpace, const R ®isters,
62 pint_t cfa, const RegisterLocation &savedReg);
63 static v128 getSavedVectorRegister(A &addressSpace, const R ®isters,
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 ®isters) {
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 ®isters, 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 ®isters, 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 ®isters, 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 ®isters) {
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 ®isters,
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