1 //===----------------------------------------------------------------------===//
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
8 // Processor specific interpretation of DWARF unwind info.
10 //===----------------------------------------------------------------------===//
12 #ifndef __DWARF_INSTRUCTIONS_HPP__
13 #define __DWARF_INSTRUCTIONS_HPP__
19 #include "DwarfParser.hpp"
20 #include "Registers.hpp"
23 #include "libunwind_ext.h"
29 /// DwarfInstructions maps abstract DWARF unwind instructions to a particular
31 template <typename A
, typename R
>
32 class DwarfInstructions
{
34 typedef typename
A::pint_t pint_t
;
35 typedef typename
A::sint_t sint_t
;
37 static int stepWithDwarf(A
&addressSpace
, pint_t pc
, pint_t fdeStart
,
38 R
®isters
, bool &isSignalFrame
, bool stage2
);
43 DW_X86_64_RET_ADDR
= 16
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
;
55 static pint_t
evaluateExpression(pint_t expression
, A
&addressSpace
,
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
);
65 static pint_t
getCFA(A
&addressSpace
, const PrologInfo
&prolog
,
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
,
73 assert(0 && "getCFA(): unknown location");
74 __builtin_unreachable();
76 #if defined(_LIBUNWIND_TARGET_AARCH64)
77 static bool isReturnAddressSigned(A
&addressSpace
, R registers
, pint_t cfa
,
79 static bool isReturnAddressSignedWithPC(A
&addressSpace
, R registers
,
80 pint_t cfa
, PrologInfo
&prolog
);
85 auto getSparcWCookie(const R
&r
, int) -> decltype(r
.getWCookie()) {
86 return r
.getWCookie();
88 template <typename R
> uint64_t getSparcWCookie(const R
&, long) {
92 template <typename A
, typename R
>
93 typename
A::pint_t DwarfInstructions
<A
, R
>::getSavedRegister(
94 A
&addressSpace
, const R
®isters
, pint_t cfa
,
95 const RegisterLocation
&savedReg
) {
96 switch (savedReg
.location
) {
97 case CFI_Parser
<A
>::kRegisterInCFA
:
98 return (pint_t
)addressSpace
.getRegister(cfa
+ (pint_t
)savedReg
.value
);
100 case CFI_Parser
<A
>::kRegisterInCFADecrypt
: // sparc64 specific
101 return (pint_t
)(addressSpace
.getP(cfa
+ (pint_t
)savedReg
.value
) ^
102 getSparcWCookie(registers
, 0));
104 case CFI_Parser
<A
>::kRegisterAtExpression
:
105 return (pint_t
)addressSpace
.getRegister(evaluateExpression(
106 (pint_t
)savedReg
.value
, addressSpace
, registers
, cfa
));
108 case CFI_Parser
<A
>::kRegisterIsExpression
:
109 return evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
112 case CFI_Parser
<A
>::kRegisterInRegister
:
113 return registers
.getRegister((int)savedReg
.value
);
114 case CFI_Parser
<A
>::kRegisterUndefined
:
116 case CFI_Parser
<A
>::kRegisterUnused
:
117 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
121 _LIBUNWIND_ABORT("unsupported restore location for register");
124 template <typename A
, typename R
>
125 double DwarfInstructions
<A
, R
>::getSavedFloatRegister(
126 A
&addressSpace
, const R
®isters
, pint_t cfa
,
127 const RegisterLocation
&savedReg
) {
128 switch (savedReg
.location
) {
129 case CFI_Parser
<A
>::kRegisterInCFA
:
130 return addressSpace
.getDouble(cfa
+ (pint_t
)savedReg
.value
);
132 case CFI_Parser
<A
>::kRegisterAtExpression
:
133 return addressSpace
.getDouble(
134 evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
136 case CFI_Parser
<A
>::kRegisterUndefined
:
138 case CFI_Parser
<A
>::kRegisterInRegister
:
139 #ifndef _LIBUNWIND_TARGET_ARM
140 return registers
.getFloatRegister((int)savedReg
.value
);
142 case CFI_Parser
<A
>::kRegisterIsExpression
:
143 case CFI_Parser
<A
>::kRegisterUnused
:
144 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
145 case CFI_Parser
<A
>::kRegisterInCFADecrypt
:
149 _LIBUNWIND_ABORT("unsupported restore location for float register");
152 template <typename A
, typename R
>
153 v128 DwarfInstructions
<A
, R
>::getSavedVectorRegister(
154 A
&addressSpace
, const R
®isters
, pint_t cfa
,
155 const RegisterLocation
&savedReg
) {
156 switch (savedReg
.location
) {
157 case CFI_Parser
<A
>::kRegisterInCFA
:
158 return addressSpace
.getVector(cfa
+ (pint_t
)savedReg
.value
);
160 case CFI_Parser
<A
>::kRegisterAtExpression
:
161 return addressSpace
.getVector(
162 evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
165 case CFI_Parser
<A
>::kRegisterIsExpression
:
166 case CFI_Parser
<A
>::kRegisterUnused
:
167 case CFI_Parser
<A
>::kRegisterUndefined
:
168 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
169 case CFI_Parser
<A
>::kRegisterInRegister
:
170 case CFI_Parser
<A
>::kRegisterInCFADecrypt
:
174 _LIBUNWIND_ABORT("unsupported restore location for vector register");
176 #if defined(_LIBUNWIND_TARGET_AARCH64)
177 template <typename A
, typename R
>
178 bool DwarfInstructions
<A
, R
>::isReturnAddressSigned(A
&addressSpace
,
179 R registers
, pint_t cfa
,
180 PrologInfo
&prolog
) {
182 auto regloc
= prolog
.savedRegisters
[UNW_AARCH64_RA_SIGN_STATE
];
183 if (regloc
.location
== CFI_Parser
<A
>::kRegisterUnused
)
184 raSignState
= static_cast<pint_t
>(regloc
.value
);
186 raSignState
= getSavedRegister(addressSpace
, registers
, cfa
, regloc
);
188 // Only bit[0] is meaningful.
189 return raSignState
& 0x01;
192 template <typename A
, typename R
>
193 bool DwarfInstructions
<A
, R
>::isReturnAddressSignedWithPC(A
&addressSpace
,
196 PrologInfo
&prolog
) {
198 auto regloc
= prolog
.savedRegisters
[UNW_AARCH64_RA_SIGN_STATE
];
199 if (regloc
.location
== CFI_Parser
<A
>::kRegisterUnused
)
200 raSignState
= static_cast<pint_t
>(regloc
.value
);
202 raSignState
= getSavedRegister(addressSpace
, registers
, cfa
, regloc
);
204 // Only bit[1] is meaningful.
205 return raSignState
& 0x02;
209 template <typename A
, typename R
>
210 int DwarfInstructions
<A
, R
>::stepWithDwarf(A
&addressSpace
, pint_t pc
,
211 pint_t fdeStart
, R
®isters
,
212 bool &isSignalFrame
, bool stage2
) {
215 if (CFI_Parser
<A
>::decodeFDE(addressSpace
, fdeStart
, &fdeInfo
,
218 if (CFI_Parser
<A
>::parseFDEInstructions(addressSpace
, fdeInfo
, cieInfo
, pc
,
219 R::getArch(), &prolog
)) {
220 // get pointer to cfa (architecture specific)
221 pint_t cfa
= getCFA(addressSpace
, prolog
, registers
);
224 // __unw_step_stage2 is not used for cross unwinding, so we use
225 // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are
226 // building for AArch64 natively.
227 #if defined(__aarch64__)
228 if (stage2
&& cieInfo
.mteTaggedFrame
) {
229 pint_t sp
= registers
.getSP();
231 // AArch64 doesn't require the value of SP to be 16-byte aligned at
232 // all times, only at memory accesses and public interfaces [1]. Thus,
233 // a signal could arrive at a point where SP is not aligned properly.
234 // In that case, the kernel fixes up [2] the signal frame, but we
235 // still have a misaligned SP in the previous frame. If that signal
236 // handler caused stack unwinding, we would have an unaligned SP.
237 // We do not need to fix up the CFA, as that is the SP at a "public
240 // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack
242 // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718
244 // CFA is the bottom of the current stack frame.
245 for (; p
< cfa
; p
+= 16) {
246 __asm__
__volatile__(".arch armv8.5-a\n"
247 ".arch_extension memtag\n"
248 "stg %[Ptr], [%[Ptr]]\n"
255 // restore registers that DWARF says were saved
256 R newRegisters
= registers
;
258 // Typically, the CFA is the stack pointer at the call site in
259 // the previous frame. However, there are scenarios in which this is not
260 // true. For example, if we switched to a new stack. In that case, the
261 // value of the previous SP might be indicated by a CFI directive.
263 // We set the SP here to the CFA, allowing for it to be overridden
264 // by a CFI directive later on.
265 newRegisters
.setSP(cfa
);
267 pint_t returnAddress
= 0;
268 constexpr int lastReg
= R::lastDwarfRegNum();
269 static_assert(static_cast<int>(CFI_Parser
<A
>::kMaxRegisterNumber
) >=
271 "register range too large");
272 assert(lastReg
>= (int)cieInfo
.returnAddressRegister
&&
273 "register range does not contain return address register");
274 for (int i
= 0; i
<= lastReg
; ++i
) {
275 if (prolog
.savedRegisters
[i
].location
!=
276 CFI_Parser
<A
>::kRegisterUnused
) {
277 if (registers
.validFloatRegister(i
))
278 newRegisters
.setFloatRegister(
279 i
, getSavedFloatRegister(addressSpace
, registers
, cfa
,
280 prolog
.savedRegisters
[i
]));
281 else if (registers
.validVectorRegister(i
))
282 newRegisters
.setVectorRegister(
283 i
, getSavedVectorRegister(addressSpace
, registers
, cfa
,
284 prolog
.savedRegisters
[i
]));
285 else if (i
== (int)cieInfo
.returnAddressRegister
)
286 returnAddress
= getSavedRegister(addressSpace
, registers
, cfa
,
287 prolog
.savedRegisters
[i
]);
288 else if (registers
.validRegister(i
))
289 newRegisters
.setRegister(
290 i
, getSavedRegister(addressSpace
, registers
, cfa
,
291 prolog
.savedRegisters
[i
]));
294 } else if (i
== (int)cieInfo
.returnAddressRegister
) {
295 // Leaf function keeps the return address in register and there is no
296 // explicit instructions how to restore it.
297 returnAddress
= registers
.getRegister(cieInfo
.returnAddressRegister
);
301 isSignalFrame
= cieInfo
.isSignalFrame
;
303 #if defined(_LIBUNWIND_TARGET_AARCH64)
304 // If the target is aarch64 then the return address may have been signed
305 // using the v8.3 pointer authentication extensions. The original
306 // return address needs to be authenticated before the return address is
307 // restored. autia1716 is used instead of autia as autia1716 assembles
308 // to a NOP on pre-v8.3a architectures.
309 if ((R::getArch() == REGISTERS_ARM64
) &&
310 isReturnAddressSigned(addressSpace
, registers
, cfa
, prolog
) &&
311 returnAddress
!= 0) {
312 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
313 return UNW_ECROSSRASIGNING
;
315 register unsigned long long x17
__asm("x17") = returnAddress
;
316 register unsigned long long x16
__asm("x16") = cfa
;
318 // We use the hint versions of the authentication instructions below to
319 // ensure they're assembled by the compiler even for targets with no
320 // FEAT_PAuth/FEAT_PAuth_LR support.
321 if (isReturnAddressSignedWithPC(addressSpace
, registers
, cfa
, prolog
)) {
322 register unsigned long long x15
__asm("x15") =
323 prolog
.ptrAuthDiversifier
;
324 if (cieInfo
.addressesSignedWithBKey
) {
325 asm("hint 0x27\n\t" // pacm
328 : "r"(x16
), "r"(x15
)); // autib1716
330 asm("hint 0x27\n\t" // pacm
333 : "r"(x16
), "r"(x15
)); // autia1716
336 if (cieInfo
.addressesSignedWithBKey
)
337 asm("hint 0xe" : "+r"(x17
) : "r"(x16
)); // autib1716
339 asm("hint 0xc" : "+r"(x17
) : "r"(x16
)); // autia1716
346 #if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) && \
347 defined(__ARM_FEATURE_PAUTH)
348 if ((R::getArch() == REGISTERS_ARM
) &&
349 prolog
.savedRegisters
[UNW_ARM_RA_AUTH_CODE
].value
) {
351 getSavedRegister(addressSpace
, registers
, cfa
,
352 prolog
.savedRegisters
[UNW_ARM_RA_AUTH_CODE
]);
353 __asm__
__volatile__("autg %0, %1, %2"
355 : "r"(pac
), "r"(returnAddress
), "r"(cfa
)
360 #if defined(_LIBUNWIND_TARGET_SPARC)
361 if (R::getArch() == REGISTERS_SPARC
) {
362 // Skip call site instruction and delay slot
364 // Skip unimp instruction if function returns a struct
365 if ((addressSpace
.get32(returnAddress
) & 0xC1C00000) == 0)
370 #if defined(_LIBUNWIND_TARGET_SPARC64)
371 // Skip call site instruction and delay slot.
372 if (R::getArch() == REGISTERS_SPARC64
)
376 #if defined(_LIBUNWIND_TARGET_PPC64)
377 #define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
378 #define PPC64_ELFV1_R2_OFFSET 40
379 #define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
380 #define PPC64_ELFV2_R2_OFFSET 24
381 // If the instruction at return address is a TOC (r2) restore,
382 // then r2 was saved and needs to be restored.
383 // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
384 // while in ELFv1 ABI it is saved at SP + 40.
385 if (R::getArch() == REGISTERS_PPC64
&& returnAddress
!= 0) {
386 pint_t sp
= newRegisters
.getRegister(UNW_REG_SP
);
388 switch (addressSpace
.get32(returnAddress
)) {
389 case PPC64_ELFV1_R2_LOAD_INST_ENCODING
:
390 r2
= addressSpace
.get64(sp
+ PPC64_ELFV1_R2_OFFSET
);
392 case PPC64_ELFV2_R2_LOAD_INST_ENCODING
:
393 r2
= addressSpace
.get64(sp
+ PPC64_ELFV2_R2_OFFSET
);
397 newRegisters
.setRegister(UNW_PPC64_R2
, r2
);
401 // Return address is address after call site instruction, so setting IP to
402 // that does simulates a return.
403 newRegisters
.setIP(returnAddress
);
405 // Simulate the step by replacing the register set with the new ones.
406 registers
= newRegisters
;
408 return UNW_STEP_SUCCESS
;
411 return UNW_EBADFRAME
;
414 template <typename A
, typename R
>
416 DwarfInstructions
<A
, R
>::evaluateExpression(pint_t expression
, A
&addressSpace
,
418 pint_t initialStackValue
) {
419 const bool log
= false;
420 pint_t p
= expression
;
421 pint_t expressionEnd
= expression
+ 20; // temp, until len read
422 pint_t length
= (pint_t
)addressSpace
.getULEB128(p
, expressionEnd
);
423 expressionEnd
= p
+ length
;
425 fprintf(stderr
, "evaluateExpression(): length=%" PRIu64
"\n",
429 *(++sp
) = initialStackValue
;
431 while (p
< expressionEnd
) {
433 for (pint_t
*t
= sp
; t
> stack
; --t
) {
434 fprintf(stderr
, "sp[] = 0x%" PRIx64
"\n", (uint64_t)(*t
));
437 uint8_t opcode
= addressSpace
.get8(p
++);
438 sint_t svalue
, svalue2
;
443 // push immediate address sized value
444 value
= addressSpace
.getP(p
);
448 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
452 // pop stack, dereference, push result
454 *(++sp
) = addressSpace
.getP(value
);
456 fprintf(stderr
, "dereference 0x%" PRIx64
"\n", (uint64_t)value
);
460 // push immediate 1 byte value
461 value
= addressSpace
.get8(p
);
465 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
469 // push immediate 1 byte signed value
470 svalue
= (int8_t) addressSpace
.get8(p
);
472 *(++sp
) = (pint_t
)svalue
;
474 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
478 // push immediate 2 byte value
479 value
= addressSpace
.get16(p
);
483 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
487 // push immediate 2 byte signed value
488 svalue
= (int16_t) addressSpace
.get16(p
);
490 *(++sp
) = (pint_t
)svalue
;
492 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
496 // push immediate 4 byte value
497 value
= addressSpace
.get32(p
);
501 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
505 // push immediate 4 byte signed value
506 svalue
= (int32_t)addressSpace
.get32(p
);
508 *(++sp
) = (pint_t
)svalue
;
510 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
514 // push immediate 8 byte value
515 value
= (pint_t
)addressSpace
.get64(p
);
519 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
523 // push immediate 8 byte signed value
524 value
= (pint_t
)addressSpace
.get64(p
);
528 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
532 // push immediate ULEB128 value
533 value
= (pint_t
)addressSpace
.getULEB128(p
, expressionEnd
);
536 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
540 // push immediate SLEB128 value
541 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
542 *(++sp
) = (pint_t
)svalue
;
544 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
552 fprintf(stderr
, "duplicate top of stack\n");
559 fprintf(stderr
, "pop top of stack\n");
567 fprintf(stderr
, "duplicate second in stack\n");
572 reg
= addressSpace
.get8(p
);
574 value
= sp
[-(int)reg
];
577 fprintf(stderr
, "duplicate %d in stack\n", reg
);
586 fprintf(stderr
, "swap top of stack\n");
596 fprintf(stderr
, "rotate top three of stack\n");
600 // pop stack, dereference, push result
602 *sp
= *((pint_t
*)value
);
604 fprintf(stderr
, "x-dereference 0x%" PRIx64
"\n", (uint64_t)value
);
608 svalue
= (sint_t
)*sp
;
610 *sp
= (pint_t
)(-svalue
);
612 fprintf(stderr
, "abs\n");
619 fprintf(stderr
, "and\n");
623 svalue
= (sint_t
)(*sp
--);
624 svalue2
= (sint_t
)*sp
;
625 *sp
= (pint_t
)(svalue2
/ svalue
);
627 fprintf(stderr
, "div\n");
634 fprintf(stderr
, "minus\n");
638 svalue
= (sint_t
)(*sp
--);
639 svalue2
= (sint_t
)*sp
;
640 *sp
= (pint_t
)(svalue2
% svalue
);
642 fprintf(stderr
, "module\n");
646 svalue
= (sint_t
)(*sp
--);
647 svalue2
= (sint_t
)*sp
;
648 *sp
= (pint_t
)(svalue2
* svalue
);
650 fprintf(stderr
, "mul\n");
656 fprintf(stderr
, "neg\n");
660 svalue
= (sint_t
)(*sp
);
661 *sp
= (pint_t
)(~svalue
);
663 fprintf(stderr
, "not\n");
670 fprintf(stderr
, "or\n");
677 fprintf(stderr
, "plus\n");
680 case DW_OP_plus_uconst
:
681 // pop stack, add uelb128 constant, push result
682 *sp
+= static_cast<pint_t
>(addressSpace
.getULEB128(p
, expressionEnd
));
684 fprintf(stderr
, "add constant\n");
691 fprintf(stderr
, "shift left\n");
698 fprintf(stderr
, "shift left\n");
703 svalue
= (sint_t
)*sp
;
704 *sp
= (pint_t
)(svalue
>> value
);
706 fprintf(stderr
, "shift left arithmetic\n");
713 fprintf(stderr
, "xor\n");
717 svalue
= (int16_t) addressSpace
.get16(p
);
719 p
= (pint_t
)((sint_t
)p
+ svalue
);
721 fprintf(stderr
, "skip %" PRIu64
"\n", (uint64_t)svalue
);
725 svalue
= (int16_t) addressSpace
.get16(p
);
728 p
= (pint_t
)((sint_t
)p
+ svalue
);
730 fprintf(stderr
, "bra %" PRIu64
"\n", (uint64_t)svalue
);
735 *sp
= (*sp
== value
);
737 fprintf(stderr
, "eq\n");
742 *sp
= (*sp
>= value
);
744 fprintf(stderr
, "ge\n");
751 fprintf(stderr
, "gt\n");
756 *sp
= (*sp
<= value
);
758 fprintf(stderr
, "le\n");
765 fprintf(stderr
, "lt\n");
770 *sp
= (*sp
!= value
);
772 fprintf(stderr
, "ne\n");
807 value
= static_cast<pint_t
>(opcode
- DW_OP_lit0
);
810 fprintf(stderr
, "push literal 0x%" PRIx64
"\n", (uint64_t)value
);
845 reg
= static_cast<uint32_t>(opcode
- DW_OP_reg0
);
846 *(++sp
) = registers
.getRegister((int)reg
);
848 fprintf(stderr
, "push reg %d\n", reg
);
852 reg
= static_cast<uint32_t>(addressSpace
.getULEB128(p
, expressionEnd
));
853 *(++sp
) = registers
.getRegister((int)reg
);
855 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
890 reg
= static_cast<uint32_t>(opcode
- DW_OP_breg0
);
891 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
892 svalue
+= static_cast<sint_t
>(registers
.getRegister((int)reg
));
893 *(++sp
) = (pint_t
)(svalue
);
895 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
899 reg
= static_cast<uint32_t>(addressSpace
.getULEB128(p
, expressionEnd
));
900 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
901 svalue
+= static_cast<sint_t
>(registers
.getRegister((int)reg
));
902 *(++sp
) = (pint_t
)(svalue
);
904 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
908 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
912 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
915 case DW_OP_deref_size
:
916 // pop stack, dereference, push result
918 switch (addressSpace
.get8(p
++)) {
920 value
= addressSpace
.get8(value
);
923 value
= addressSpace
.get16(value
);
926 value
= addressSpace
.get32(value
);
929 value
= (pint_t
)addressSpace
.get64(value
);
932 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
936 fprintf(stderr
, "sized dereference 0x%" PRIx64
"\n", (uint64_t)value
);
939 case DW_OP_xderef_size
:
941 case DW_OP_push_object_addres
:
946 _LIBUNWIND_ABORT("DWARF opcode not implemented");
951 fprintf(stderr
, "expression evaluates to 0x%" PRIx64
"\n", (uint64_t)*sp
);
957 } // namespace libunwind
959 #endif // __DWARF_INSTRUCTIONS_HPP__