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, &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 ®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=%" 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