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