1 //===-------------------------- DwarfInstructions.hpp ---------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //
8 // Processor specific interpretation of DWARF unwind info.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef __DWARF_INSTRUCTIONS_HPP__
13 #define __DWARF_INSTRUCTIONS_HPP__
14
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18
19 #include "dwarf2.h"
20 #include "Registers.hpp"
21 #include "DwarfParser.hpp"
22 #include "config.h"
23
24
25 namespace libunwind {
26
27
28 /// DwarfInstructions maps abtract DWARF unwind instructions to a particular
29 /// architecture
30 template <typename A, typename R>
31 class DwarfInstructions {
32 public:
33 typedef typename A::pint_t pint_t;
34 typedef typename A::sint_t sint_t;
35
36 static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
37 R ®isters);
38
39 private:
40
41 enum {
42 DW_X86_64_RET_ADDR = 16
43 };
44
45 enum {
46 DW_X86_RET_ADDR = 8
47 };
48
49 typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;
50 typedef typename CFI_Parser<A>::PrologInfo PrologInfo;
51 typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
52 typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
53
54 static pint_t evaluateExpression(pint_t expression, A &addressSpace,
55 const R ®isters,
56 pint_t initialStackValue);
57 static pint_t getSavedRegister(A &addressSpace, const R ®isters,
58 pint_t cfa, const RegisterLocation &savedReg);
59 static double getSavedFloatRegister(A &addressSpace, const R ®isters,
60 pint_t cfa, const RegisterLocation &savedReg);
61 static v128 getSavedVectorRegister(A &addressSpace, const R ®isters,
62 pint_t cfa, const RegisterLocation &savedReg);
63
getCFA(A & addressSpace,const PrologInfo & prolog,const R & registers)64 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
65 const R ®isters) {
66 if (prolog.cfaRegister != 0)
67 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
68 prolog.cfaRegisterOffset);
69 if (prolog.cfaExpression != 0)
70 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
71 registers, 0);
72 assert(0 && "getCFA(): unknown location");
73 __builtin_unreachable();
74 }
75 };
76
77
78 template <typename A, typename R>
getSavedRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)79 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
80 A &addressSpace, const R ®isters, pint_t cfa,
81 const RegisterLocation &savedReg) {
82 switch (savedReg.location) {
83 case CFI_Parser<A>::kRegisterInCFA:
84 return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
85
86 case CFI_Parser<A>::kRegisterAtExpression:
87 return (pint_t)addressSpace.getRegister(evaluateExpression(
88 (pint_t)savedReg.value, addressSpace, registers, cfa));
89
90 case CFI_Parser<A>::kRegisterIsExpression:
91 return evaluateExpression((pint_t)savedReg.value, addressSpace,
92 registers, cfa);
93
94 case CFI_Parser<A>::kRegisterInRegister:
95 return registers.getRegister((int)savedReg.value);
96
97 case CFI_Parser<A>::kRegisterUnused:
98 case CFI_Parser<A>::kRegisterOffsetFromCFA:
99 // FIX ME
100 break;
101 }
102 _LIBUNWIND_ABORT("unsupported restore location for register");
103 }
104
105 template <typename A, typename R>
getSavedFloatRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)106 double DwarfInstructions<A, R>::getSavedFloatRegister(
107 A &addressSpace, const R ®isters, pint_t cfa,
108 const RegisterLocation &savedReg) {
109 switch (savedReg.location) {
110 case CFI_Parser<A>::kRegisterInCFA:
111 return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
112
113 case CFI_Parser<A>::kRegisterAtExpression:
114 return addressSpace.getDouble(
115 evaluateExpression((pint_t)savedReg.value, addressSpace,
116 registers, cfa));
117
118 case CFI_Parser<A>::kRegisterIsExpression:
119 case CFI_Parser<A>::kRegisterUnused:
120 case CFI_Parser<A>::kRegisterOffsetFromCFA:
121 case CFI_Parser<A>::kRegisterInRegister:
122 // FIX ME
123 break;
124 }
125 _LIBUNWIND_ABORT("unsupported restore location for float register");
126 }
127
128 template <typename A, typename R>
getSavedVectorRegister(A & addressSpace,const R & registers,pint_t cfa,const RegisterLocation & savedReg)129 v128 DwarfInstructions<A, R>::getSavedVectorRegister(
130 A &addressSpace, const R ®isters, pint_t cfa,
131 const RegisterLocation &savedReg) {
132 switch (savedReg.location) {
133 case CFI_Parser<A>::kRegisterInCFA:
134 return addressSpace.getVector(cfa + (pint_t)savedReg.value);
135
136 case CFI_Parser<A>::kRegisterAtExpression:
137 return addressSpace.getVector(
138 evaluateExpression((pint_t)savedReg.value, addressSpace,
139 registers, cfa));
140
141 case CFI_Parser<A>::kRegisterIsExpression:
142 case CFI_Parser<A>::kRegisterUnused:
143 case CFI_Parser<A>::kRegisterOffsetFromCFA:
144 case CFI_Parser<A>::kRegisterInRegister:
145 // FIX ME
146 break;
147 }
148 _LIBUNWIND_ABORT("unsupported restore location for vector register");
149 }
150
151 template <typename A, typename R>
stepWithDwarf(A & addressSpace,pint_t pc,pint_t fdeStart,R & registers)152 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
153 pint_t fdeStart, R ®isters) {
154 FDE_Info fdeInfo;
155 CIE_Info cieInfo;
156 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
157 &cieInfo) == NULL) {
158 PrologInfo prolog;
159 if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
160 R::getArch(), &prolog)) {
161 // get pointer to cfa (architecture specific)
162 pint_t cfa = getCFA(addressSpace, prolog, registers);
163
164 // restore registers that DWARF says were saved
165 R newRegisters = registers;
166 pint_t returnAddress = 0;
167 const int lastReg = R::lastDwarfRegNum();
168 assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
169 "register range too large");
170 assert(lastReg >= (int)cieInfo.returnAddressRegister &&
171 "register range does not contain return address register");
172 for (int i = 0; i <= lastReg; ++i) {
173 if (prolog.savedRegisters[i].location !=
174 CFI_Parser<A>::kRegisterUnused) {
175 if (registers.validFloatRegister(i))
176 newRegisters.setFloatRegister(
177 i, getSavedFloatRegister(addressSpace, registers, cfa,
178 prolog.savedRegisters[i]));
179 else if (registers.validVectorRegister(i))
180 newRegisters.setVectorRegister(
181 i, getSavedVectorRegister(addressSpace, registers, cfa,
182 prolog.savedRegisters[i]));
183 else if (i == (int)cieInfo.returnAddressRegister)
184 returnAddress = getSavedRegister(addressSpace, registers, cfa,
185 prolog.savedRegisters[i]);
186 else if (registers.validRegister(i))
187 newRegisters.setRegister(
188 i, getSavedRegister(addressSpace, registers, cfa,
189 prolog.savedRegisters[i]));
190 else
191 return UNW_EBADREG;
192 }
193 }
194
195 // By definition, the CFA is the stack pointer at the call site, so
196 // restoring SP means setting it to CFA.
197 newRegisters.setSP(cfa);
198
199 #if defined(_LIBUNWIND_TARGET_AARCH64)
200 // If the target is aarch64 then the return address may have been signed
201 // using the v8.3 pointer authentication extensions. The original
202 // return address needs to be authenticated before the return address is
203 // restored. autia1716 is used instead of autia as autia1716 assembles
204 // to a NOP on pre-v8.3a architectures.
205 if ((R::getArch() == REGISTERS_ARM64) &&
206 prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
207 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
208 return UNW_ECROSSRASIGNING;
209 #else
210 register unsigned long long x17 __asm("x17") = returnAddress;
211 register unsigned long long x16 __asm("x16") = cfa;
212
213 // These are the autia1716/autib1716 instructions. The hint instructions
214 // are used here as gcc does not assemble autia1716/autib1716 for pre
215 // armv8.3a targets.
216 if (cieInfo.addressesSignedWithBKey)
217 asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
218 else
219 asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
220 returnAddress = x17;
221 #endif
222 }
223 #endif
224
225 #if defined(_LIBUNWIND_TARGET_SPARC)
226 if (R::getArch() == REGISTERS_SPARC) {
227 // Skip call site instruction and delay slot
228 returnAddress += 8;
229 // Skip unimp instruction if function returns a struct
230 if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
231 returnAddress += 4;
232 }
233 #endif
234
235 // Return address is address after call site instruction, so setting IP to
236 // that does simualates a return.
237 newRegisters.setIP(returnAddress);
238
239 // Simulate the step by replacing the register set with the new ones.
240 registers = newRegisters;
241
242 return UNW_STEP_SUCCESS;
243 }
244 }
245 return UNW_EBADFRAME;
246 }
247
248 template <typename A, typename R>
249 typename A::pint_t
evaluateExpression(pint_t expression,A & addressSpace,const R & registers,pint_t initialStackValue)250 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
251 const R ®isters,
252 pint_t initialStackValue) {
253 const bool log = false;
254 pint_t p = expression;
255 pint_t expressionEnd = expression + 20; // temp, until len read
256 pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
257 expressionEnd = p + length;
258 if (log)
259 fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
260 (uint64_t)length);
261 pint_t stack[100];
262 pint_t *sp = stack;
263 *(++sp) = initialStackValue;
264
265 while (p < expressionEnd) {
266 if (log) {
267 for (pint_t *t = sp; t > stack; --t) {
268 fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
269 }
270 }
271 uint8_t opcode = addressSpace.get8(p++);
272 sint_t svalue, svalue2;
273 pint_t value;
274 uint32_t reg;
275 switch (opcode) {
276 case DW_OP_addr:
277 // push immediate address sized value
278 value = addressSpace.getP(p);
279 p += sizeof(pint_t);
280 *(++sp) = value;
281 if (log)
282 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
283 break;
284
285 case DW_OP_deref:
286 // pop stack, dereference, push result
287 value = *sp--;
288 *(++sp) = addressSpace.getP(value);
289 if (log)
290 fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
291 break;
292
293 case DW_OP_const1u:
294 // push immediate 1 byte value
295 value = addressSpace.get8(p);
296 p += 1;
297 *(++sp) = value;
298 if (log)
299 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
300 break;
301
302 case DW_OP_const1s:
303 // push immediate 1 byte signed value
304 svalue = (int8_t) addressSpace.get8(p);
305 p += 1;
306 *(++sp) = (pint_t)svalue;
307 if (log)
308 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
309 break;
310
311 case DW_OP_const2u:
312 // push immediate 2 byte value
313 value = addressSpace.get16(p);
314 p += 2;
315 *(++sp) = value;
316 if (log)
317 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
318 break;
319
320 case DW_OP_const2s:
321 // push immediate 2 byte signed value
322 svalue = (int16_t) addressSpace.get16(p);
323 p += 2;
324 *(++sp) = (pint_t)svalue;
325 if (log)
326 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
327 break;
328
329 case DW_OP_const4u:
330 // push immediate 4 byte value
331 value = addressSpace.get32(p);
332 p += 4;
333 *(++sp) = value;
334 if (log)
335 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
336 break;
337
338 case DW_OP_const4s:
339 // push immediate 4 byte signed value
340 svalue = (int32_t)addressSpace.get32(p);
341 p += 4;
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_const8u:
348 // push immediate 8 byte value
349 value = (pint_t)addressSpace.get64(p);
350 p += 8;
351 *(++sp) = value;
352 if (log)
353 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
354 break;
355
356 case DW_OP_const8s:
357 // push immediate 8 byte signed value
358 value = (pint_t)addressSpace.get64(p);
359 p += 8;
360 *(++sp) = value;
361 if (log)
362 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
363 break;
364
365 case DW_OP_constu:
366 // push immediate ULEB128 value
367 value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
368 *(++sp) = value;
369 if (log)
370 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
371 break;
372
373 case DW_OP_consts:
374 // push immediate SLEB128 value
375 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
376 *(++sp) = (pint_t)svalue;
377 if (log)
378 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
379 break;
380
381 case DW_OP_dup:
382 // push top of stack
383 value = *sp;
384 *(++sp) = value;
385 if (log)
386 fprintf(stderr, "duplicate top of stack\n");
387 break;
388
389 case DW_OP_drop:
390 // pop
391 --sp;
392 if (log)
393 fprintf(stderr, "pop top of stack\n");
394 break;
395
396 case DW_OP_over:
397 // dup second
398 value = sp[-1];
399 *(++sp) = value;
400 if (log)
401 fprintf(stderr, "duplicate second in stack\n");
402 break;
403
404 case DW_OP_pick:
405 // pick from
406 reg = addressSpace.get8(p);
407 p += 1;
408 value = sp[-reg];
409 *(++sp) = value;
410 if (log)
411 fprintf(stderr, "duplicate %d in stack\n", reg);
412 break;
413
414 case DW_OP_swap:
415 // swap top two
416 value = sp[0];
417 sp[0] = sp[-1];
418 sp[-1] = value;
419 if (log)
420 fprintf(stderr, "swap top of stack\n");
421 break;
422
423 case DW_OP_rot:
424 // rotate top three
425 value = sp[0];
426 sp[0] = sp[-1];
427 sp[-1] = sp[-2];
428 sp[-2] = value;
429 if (log)
430 fprintf(stderr, "rotate top three of stack\n");
431 break;
432
433 case DW_OP_xderef:
434 // pop stack, dereference, push result
435 value = *sp--;
436 *sp = *((pint_t*)value);
437 if (log)
438 fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
439 break;
440
441 case DW_OP_abs:
442 svalue = (sint_t)*sp;
443 if (svalue < 0)
444 *sp = (pint_t)(-svalue);
445 if (log)
446 fprintf(stderr, "abs\n");
447 break;
448
449 case DW_OP_and:
450 value = *sp--;
451 *sp &= value;
452 if (log)
453 fprintf(stderr, "and\n");
454 break;
455
456 case DW_OP_div:
457 svalue = (sint_t)(*sp--);
458 svalue2 = (sint_t)*sp;
459 *sp = (pint_t)(svalue2 / svalue);
460 if (log)
461 fprintf(stderr, "div\n");
462 break;
463
464 case DW_OP_minus:
465 value = *sp--;
466 *sp = *sp - value;
467 if (log)
468 fprintf(stderr, "minus\n");
469 break;
470
471 case DW_OP_mod:
472 svalue = (sint_t)(*sp--);
473 svalue2 = (sint_t)*sp;
474 *sp = (pint_t)(svalue2 % svalue);
475 if (log)
476 fprintf(stderr, "module\n");
477 break;
478
479 case DW_OP_mul:
480 svalue = (sint_t)(*sp--);
481 svalue2 = (sint_t)*sp;
482 *sp = (pint_t)(svalue2 * svalue);
483 if (log)
484 fprintf(stderr, "mul\n");
485 break;
486
487 case DW_OP_neg:
488 *sp = 0 - *sp;
489 if (log)
490 fprintf(stderr, "neg\n");
491 break;
492
493 case DW_OP_not:
494 svalue = (sint_t)(*sp);
495 *sp = (pint_t)(~svalue);
496 if (log)
497 fprintf(stderr, "not\n");
498 break;
499
500 case DW_OP_or:
501 value = *sp--;
502 *sp |= value;
503 if (log)
504 fprintf(stderr, "or\n");
505 break;
506
507 case DW_OP_plus:
508 value = *sp--;
509 *sp += value;
510 if (log)
511 fprintf(stderr, "plus\n");
512 break;
513
514 case DW_OP_plus_uconst:
515 // pop stack, add uelb128 constant, push result
516 *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
517 if (log)
518 fprintf(stderr, "add constant\n");
519 break;
520
521 case DW_OP_shl:
522 value = *sp--;
523 *sp = *sp << value;
524 if (log)
525 fprintf(stderr, "shift left\n");
526 break;
527
528 case DW_OP_shr:
529 value = *sp--;
530 *sp = *sp >> value;
531 if (log)
532 fprintf(stderr, "shift left\n");
533 break;
534
535 case DW_OP_shra:
536 value = *sp--;
537 svalue = (sint_t)*sp;
538 *sp = (pint_t)(svalue >> value);
539 if (log)
540 fprintf(stderr, "shift left arithmetric\n");
541 break;
542
543 case DW_OP_xor:
544 value = *sp--;
545 *sp ^= value;
546 if (log)
547 fprintf(stderr, "xor\n");
548 break;
549
550 case DW_OP_skip:
551 svalue = (int16_t) addressSpace.get16(p);
552 p += 2;
553 p = (pint_t)((sint_t)p + svalue);
554 if (log)
555 fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
556 break;
557
558 case DW_OP_bra:
559 svalue = (int16_t) addressSpace.get16(p);
560 p += 2;
561 if (*sp--)
562 p = (pint_t)((sint_t)p + svalue);
563 if (log)
564 fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
565 break;
566
567 case DW_OP_eq:
568 value = *sp--;
569 *sp = (*sp == value);
570 if (log)
571 fprintf(stderr, "eq\n");
572 break;
573
574 case DW_OP_ge:
575 value = *sp--;
576 *sp = (*sp >= value);
577 if (log)
578 fprintf(stderr, "ge\n");
579 break;
580
581 case DW_OP_gt:
582 value = *sp--;
583 *sp = (*sp > value);
584 if (log)
585 fprintf(stderr, "gt\n");
586 break;
587
588 case DW_OP_le:
589 value = *sp--;
590 *sp = (*sp <= value);
591 if (log)
592 fprintf(stderr, "le\n");
593 break;
594
595 case DW_OP_lt:
596 value = *sp--;
597 *sp = (*sp < value);
598 if (log)
599 fprintf(stderr, "lt\n");
600 break;
601
602 case DW_OP_ne:
603 value = *sp--;
604 *sp = (*sp != value);
605 if (log)
606 fprintf(stderr, "ne\n");
607 break;
608
609 case DW_OP_lit0:
610 case DW_OP_lit1:
611 case DW_OP_lit2:
612 case DW_OP_lit3:
613 case DW_OP_lit4:
614 case DW_OP_lit5:
615 case DW_OP_lit6:
616 case DW_OP_lit7:
617 case DW_OP_lit8:
618 case DW_OP_lit9:
619 case DW_OP_lit10:
620 case DW_OP_lit11:
621 case DW_OP_lit12:
622 case DW_OP_lit13:
623 case DW_OP_lit14:
624 case DW_OP_lit15:
625 case DW_OP_lit16:
626 case DW_OP_lit17:
627 case DW_OP_lit18:
628 case DW_OP_lit19:
629 case DW_OP_lit20:
630 case DW_OP_lit21:
631 case DW_OP_lit22:
632 case DW_OP_lit23:
633 case DW_OP_lit24:
634 case DW_OP_lit25:
635 case DW_OP_lit26:
636 case DW_OP_lit27:
637 case DW_OP_lit28:
638 case DW_OP_lit29:
639 case DW_OP_lit30:
640 case DW_OP_lit31:
641 value = static_cast<pint_t>(opcode - DW_OP_lit0);
642 *(++sp) = value;
643 if (log)
644 fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
645 break;
646
647 case DW_OP_reg0:
648 case DW_OP_reg1:
649 case DW_OP_reg2:
650 case DW_OP_reg3:
651 case DW_OP_reg4:
652 case DW_OP_reg5:
653 case DW_OP_reg6:
654 case DW_OP_reg7:
655 case DW_OP_reg8:
656 case DW_OP_reg9:
657 case DW_OP_reg10:
658 case DW_OP_reg11:
659 case DW_OP_reg12:
660 case DW_OP_reg13:
661 case DW_OP_reg14:
662 case DW_OP_reg15:
663 case DW_OP_reg16:
664 case DW_OP_reg17:
665 case DW_OP_reg18:
666 case DW_OP_reg19:
667 case DW_OP_reg20:
668 case DW_OP_reg21:
669 case DW_OP_reg22:
670 case DW_OP_reg23:
671 case DW_OP_reg24:
672 case DW_OP_reg25:
673 case DW_OP_reg26:
674 case DW_OP_reg27:
675 case DW_OP_reg28:
676 case DW_OP_reg29:
677 case DW_OP_reg30:
678 case DW_OP_reg31:
679 reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
680 *(++sp) = registers.getRegister((int)reg);
681 if (log)
682 fprintf(stderr, "push reg %d\n", reg);
683 break;
684
685 case DW_OP_regx:
686 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
687 *(++sp) = registers.getRegister((int)reg);
688 if (log)
689 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
690 break;
691
692 case DW_OP_breg0:
693 case DW_OP_breg1:
694 case DW_OP_breg2:
695 case DW_OP_breg3:
696 case DW_OP_breg4:
697 case DW_OP_breg5:
698 case DW_OP_breg6:
699 case DW_OP_breg7:
700 case DW_OP_breg8:
701 case DW_OP_breg9:
702 case DW_OP_breg10:
703 case DW_OP_breg11:
704 case DW_OP_breg12:
705 case DW_OP_breg13:
706 case DW_OP_breg14:
707 case DW_OP_breg15:
708 case DW_OP_breg16:
709 case DW_OP_breg17:
710 case DW_OP_breg18:
711 case DW_OP_breg19:
712 case DW_OP_breg20:
713 case DW_OP_breg21:
714 case DW_OP_breg22:
715 case DW_OP_breg23:
716 case DW_OP_breg24:
717 case DW_OP_breg25:
718 case DW_OP_breg26:
719 case DW_OP_breg27:
720 case DW_OP_breg28:
721 case DW_OP_breg29:
722 case DW_OP_breg30:
723 case DW_OP_breg31:
724 reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
725 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
726 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
727 *(++sp) = (pint_t)(svalue);
728 if (log)
729 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
730 break;
731
732 case DW_OP_bregx:
733 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
734 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
735 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
736 *(++sp) = (pint_t)(svalue);
737 if (log)
738 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
739 break;
740
741 case DW_OP_fbreg:
742 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
743 break;
744
745 case DW_OP_piece:
746 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
747 break;
748
749 case DW_OP_deref_size:
750 // pop stack, dereference, push result
751 value = *sp--;
752 switch (addressSpace.get8(p++)) {
753 case 1:
754 value = addressSpace.get8(value);
755 break;
756 case 2:
757 value = addressSpace.get16(value);
758 break;
759 case 4:
760 value = addressSpace.get32(value);
761 break;
762 case 8:
763 value = (pint_t)addressSpace.get64(value);
764 break;
765 default:
766 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
767 }
768 *(++sp) = value;
769 if (log)
770 fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
771 break;
772
773 case DW_OP_xderef_size:
774 case DW_OP_nop:
775 case DW_OP_push_object_addres:
776 case DW_OP_call2:
777 case DW_OP_call4:
778 case DW_OP_call_ref:
779 default:
780 _LIBUNWIND_ABORT("DWARF opcode not implemented");
781 }
782
783 }
784 if (log)
785 fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
786 return *sp;
787 }
788
789
790
791 } // namespace libunwind
792
793 #endif // __DWARF_INSTRUCTIONS_HPP__
794