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