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 getRA_SIGN_STATE(A
&addressSpace
, R registers
, pint_t cfa
,
83 auto getSparcWCookie(const R
&r
, int) -> decltype(r
.getWCookie()) {
84 return r
.getWCookie();
86 template <typename R
> uint64_t getSparcWCookie(const R
&, long) {
90 template <typename A
, typename R
>
91 typename
A::pint_t DwarfInstructions
<A
, R
>::getSavedRegister(
92 A
&addressSpace
, const R
®isters
, pint_t cfa
,
93 const RegisterLocation
&savedReg
) {
94 switch (savedReg
.location
) {
95 case CFI_Parser
<A
>::kRegisterInCFA
:
96 return (pint_t
)addressSpace
.getRegister(cfa
+ (pint_t
)savedReg
.value
);
98 case CFI_Parser
<A
>::kRegisterInCFADecrypt
: // sparc64 specific
99 return (pint_t
)(addressSpace
.getP(cfa
+ (pint_t
)savedReg
.value
) ^
100 getSparcWCookie(registers
, 0));
102 case CFI_Parser
<A
>::kRegisterAtExpression
:
103 return (pint_t
)addressSpace
.getRegister(evaluateExpression(
104 (pint_t
)savedReg
.value
, addressSpace
, registers
, cfa
));
106 case CFI_Parser
<A
>::kRegisterIsExpression
:
107 return evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
110 case CFI_Parser
<A
>::kRegisterInRegister
:
111 return registers
.getRegister((int)savedReg
.value
);
112 case CFI_Parser
<A
>::kRegisterUndefined
:
114 case CFI_Parser
<A
>::kRegisterUnused
:
115 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
119 _LIBUNWIND_ABORT("unsupported restore location for register");
122 template <typename A
, typename R
>
123 double DwarfInstructions
<A
, R
>::getSavedFloatRegister(
124 A
&addressSpace
, const R
®isters
, pint_t cfa
,
125 const RegisterLocation
&savedReg
) {
126 switch (savedReg
.location
) {
127 case CFI_Parser
<A
>::kRegisterInCFA
:
128 return addressSpace
.getDouble(cfa
+ (pint_t
)savedReg
.value
);
130 case CFI_Parser
<A
>::kRegisterAtExpression
:
131 return addressSpace
.getDouble(
132 evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
134 case CFI_Parser
<A
>::kRegisterUndefined
:
136 case CFI_Parser
<A
>::kRegisterInRegister
:
137 #ifndef _LIBUNWIND_TARGET_ARM
138 return registers
.getFloatRegister((int)savedReg
.value
);
140 case CFI_Parser
<A
>::kRegisterIsExpression
:
141 case CFI_Parser
<A
>::kRegisterUnused
:
142 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
143 case CFI_Parser
<A
>::kRegisterInCFADecrypt
:
147 _LIBUNWIND_ABORT("unsupported restore location for float register");
150 template <typename A
, typename R
>
151 v128 DwarfInstructions
<A
, R
>::getSavedVectorRegister(
152 A
&addressSpace
, const R
®isters
, pint_t cfa
,
153 const RegisterLocation
&savedReg
) {
154 switch (savedReg
.location
) {
155 case CFI_Parser
<A
>::kRegisterInCFA
:
156 return addressSpace
.getVector(cfa
+ (pint_t
)savedReg
.value
);
158 case CFI_Parser
<A
>::kRegisterAtExpression
:
159 return addressSpace
.getVector(
160 evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
163 case CFI_Parser
<A
>::kRegisterIsExpression
:
164 case CFI_Parser
<A
>::kRegisterUnused
:
165 case CFI_Parser
<A
>::kRegisterUndefined
:
166 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
167 case CFI_Parser
<A
>::kRegisterInRegister
:
168 case CFI_Parser
<A
>::kRegisterInCFADecrypt
:
172 _LIBUNWIND_ABORT("unsupported restore location for vector register");
174 #if defined(_LIBUNWIND_TARGET_AARCH64)
175 template <typename A
, typename R
>
176 bool DwarfInstructions
<A
, R
>::getRA_SIGN_STATE(A
&addressSpace
, R registers
,
177 pint_t cfa
, PrologInfo
&prolog
) {
179 auto regloc
= prolog
.savedRegisters
[UNW_AARCH64_RA_SIGN_STATE
];
180 if (regloc
.location
== CFI_Parser
<A
>::kRegisterUnused
)
181 raSignState
= static_cast<pint_t
>(regloc
.value
);
183 raSignState
= getSavedRegister(addressSpace
, registers
, cfa
, regloc
);
185 // Only bit[0] is meaningful.
186 return raSignState
& 0x01;
190 template <typename A
, typename R
>
191 int DwarfInstructions
<A
, R
>::stepWithDwarf(A
&addressSpace
, pint_t pc
,
192 pint_t fdeStart
, R
®isters
,
193 bool &isSignalFrame
, bool stage2
) {
196 if (CFI_Parser
<A
>::decodeFDE(addressSpace
, fdeStart
, &fdeInfo
,
199 if (CFI_Parser
<A
>::parseFDEInstructions(addressSpace
, fdeInfo
, cieInfo
, pc
,
200 R::getArch(), &prolog
)) {
201 // get pointer to cfa (architecture specific)
202 pint_t cfa
= getCFA(addressSpace
, prolog
, registers
);
205 // __unw_step_stage2 is not used for cross unwinding, so we use
206 // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are
207 // building for AArch64 natively.
208 #if defined(__aarch64__)
209 if (stage2
&& cieInfo
.mteTaggedFrame
) {
210 pint_t sp
= registers
.getSP();
212 // AArch64 doesn't require the value of SP to be 16-byte aligned at
213 // all times, only at memory accesses and public interfaces [1]. Thus,
214 // a signal could arrive at a point where SP is not aligned properly.
215 // In that case, the kernel fixes up [2] the signal frame, but we
216 // still have a misaligned SP in the previous frame. If that signal
217 // handler caused stack unwinding, we would have an unaligned SP.
218 // We do not need to fix up the CFA, as that is the SP at a "public
221 // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack
223 // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718
225 // CFA is the bottom of the current stack frame.
226 for (; p
< cfa
; p
+= 16) {
227 __asm__
__volatile__(".arch armv8.5-a\n"
228 ".arch_extension memtag\n"
229 "stg %[Ptr], [%[Ptr]]\n"
236 // restore registers that DWARF says were saved
237 R newRegisters
= registers
;
239 // Typically, the CFA is the stack pointer at the call site in
240 // the previous frame. However, there are scenarios in which this is not
241 // true. For example, if we switched to a new stack. In that case, the
242 // value of the previous SP might be indicated by a CFI directive.
244 // We set the SP here to the CFA, allowing for it to be overridden
245 // by a CFI directive later on.
246 newRegisters
.setSP(cfa
);
248 pint_t returnAddress
= 0;
249 constexpr int lastReg
= R::lastDwarfRegNum();
250 static_assert(static_cast<int>(CFI_Parser
<A
>::kMaxRegisterNumber
) >=
252 "register range too large");
253 assert(lastReg
>= (int)cieInfo
.returnAddressRegister
&&
254 "register range does not contain return address register");
255 for (int i
= 0; i
<= lastReg
; ++i
) {
256 if (prolog
.savedRegisters
[i
].location
!=
257 CFI_Parser
<A
>::kRegisterUnused
) {
258 if (registers
.validFloatRegister(i
))
259 newRegisters
.setFloatRegister(
260 i
, getSavedFloatRegister(addressSpace
, registers
, cfa
,
261 prolog
.savedRegisters
[i
]));
262 else if (registers
.validVectorRegister(i
))
263 newRegisters
.setVectorRegister(
264 i
, getSavedVectorRegister(addressSpace
, registers
, cfa
,
265 prolog
.savedRegisters
[i
]));
266 else if (i
== (int)cieInfo
.returnAddressRegister
)
267 returnAddress
= getSavedRegister(addressSpace
, registers
, cfa
,
268 prolog
.savedRegisters
[i
]);
269 else if (registers
.validRegister(i
))
270 newRegisters
.setRegister(
271 i
, getSavedRegister(addressSpace
, registers
, cfa
,
272 prolog
.savedRegisters
[i
]));
275 } else if (i
== (int)cieInfo
.returnAddressRegister
) {
276 // Leaf function keeps the return address in register and there is no
277 // explicit instructions how to restore it.
278 returnAddress
= registers
.getRegister(cieInfo
.returnAddressRegister
);
282 isSignalFrame
= cieInfo
.isSignalFrame
;
284 #if defined(_LIBUNWIND_TARGET_AARCH64)
285 // If the target is aarch64 then the return address may have been signed
286 // using the v8.3 pointer authentication extensions. The original
287 // return address needs to be authenticated before the return address is
288 // restored. autia1716 is used instead of autia as autia1716 assembles
289 // to a NOP on pre-v8.3a architectures.
290 if ((R::getArch() == REGISTERS_ARM64
) &&
291 getRA_SIGN_STATE(addressSpace
, registers
, cfa
, prolog
) &&
292 returnAddress
!= 0) {
293 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
294 return UNW_ECROSSRASIGNING
;
296 register unsigned long long x17
__asm("x17") = returnAddress
;
297 register unsigned long long x16
__asm("x16") = cfa
;
299 // These are the autia1716/autib1716 instructions. The hint instructions
300 // are used here as gcc does not assemble autia1716/autib1716 for pre
302 if (cieInfo
.addressesSignedWithBKey
)
303 asm("hint 0xe" : "+r"(x17
) : "r"(x16
)); // autib1716
305 asm("hint 0xc" : "+r"(x17
) : "r"(x16
)); // autia1716
311 #if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) && \
312 defined(__ARM_FEATURE_PAUTH)
313 if ((R::getArch() == REGISTERS_ARM
) &&
314 prolog
.savedRegisters
[UNW_ARM_RA_AUTH_CODE
].value
) {
316 getSavedRegister(addressSpace
, registers
, cfa
,
317 prolog
.savedRegisters
[UNW_ARM_RA_AUTH_CODE
]);
318 __asm__
__volatile__("autg %0, %1, %2"
320 : "r"(pac
), "r"(returnAddress
), "r"(cfa
)
325 #if defined(_LIBUNWIND_TARGET_SPARC)
326 if (R::getArch() == REGISTERS_SPARC
) {
327 // Skip call site instruction and delay slot
329 // Skip unimp instruction if function returns a struct
330 if ((addressSpace
.get32(returnAddress
) & 0xC1C00000) == 0)
335 #if defined(_LIBUNWIND_TARGET_SPARC64)
336 // Skip call site instruction and delay slot.
337 if (R::getArch() == REGISTERS_SPARC64
)
341 #if defined(_LIBUNWIND_TARGET_PPC64)
342 #define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
343 #define PPC64_ELFV1_R2_OFFSET 40
344 #define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
345 #define PPC64_ELFV2_R2_OFFSET 24
346 // If the instruction at return address is a TOC (r2) restore,
347 // then r2 was saved and needs to be restored.
348 // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
349 // while in ELFv1 ABI it is saved at SP + 40.
350 if (R::getArch() == REGISTERS_PPC64
&& returnAddress
!= 0) {
351 pint_t sp
= newRegisters
.getRegister(UNW_REG_SP
);
353 switch (addressSpace
.get32(returnAddress
)) {
354 case PPC64_ELFV1_R2_LOAD_INST_ENCODING
:
355 r2
= addressSpace
.get64(sp
+ PPC64_ELFV1_R2_OFFSET
);
357 case PPC64_ELFV2_R2_LOAD_INST_ENCODING
:
358 r2
= addressSpace
.get64(sp
+ PPC64_ELFV2_R2_OFFSET
);
362 newRegisters
.setRegister(UNW_PPC64_R2
, r2
);
366 // Return address is address after call site instruction, so setting IP to
367 // that does simulates a return.
368 newRegisters
.setIP(returnAddress
);
370 // Simulate the step by replacing the register set with the new ones.
371 registers
= newRegisters
;
373 return UNW_STEP_SUCCESS
;
376 return UNW_EBADFRAME
;
379 template <typename A
, typename R
>
381 DwarfInstructions
<A
, R
>::evaluateExpression(pint_t expression
, A
&addressSpace
,
383 pint_t initialStackValue
) {
384 const bool log
= false;
385 pint_t p
= expression
;
386 pint_t expressionEnd
= expression
+ 20; // temp, until len read
387 pint_t length
= (pint_t
)addressSpace
.getULEB128(p
, expressionEnd
);
388 expressionEnd
= p
+ length
;
390 fprintf(stderr
, "evaluateExpression(): length=%" PRIu64
"\n",
394 *(++sp
) = initialStackValue
;
396 while (p
< expressionEnd
) {
398 for (pint_t
*t
= sp
; t
> stack
; --t
) {
399 fprintf(stderr
, "sp[] = 0x%" PRIx64
"\n", (uint64_t)(*t
));
402 uint8_t opcode
= addressSpace
.get8(p
++);
403 sint_t svalue
, svalue2
;
408 // push immediate address sized value
409 value
= addressSpace
.getP(p
);
413 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
417 // pop stack, dereference, push result
419 *(++sp
) = addressSpace
.getP(value
);
421 fprintf(stderr
, "dereference 0x%" PRIx64
"\n", (uint64_t)value
);
425 // push immediate 1 byte value
426 value
= addressSpace
.get8(p
);
430 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
434 // push immediate 1 byte signed value
435 svalue
= (int8_t) addressSpace
.get8(p
);
437 *(++sp
) = (pint_t
)svalue
;
439 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
443 // push immediate 2 byte value
444 value
= addressSpace
.get16(p
);
448 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
452 // push immediate 2 byte signed value
453 svalue
= (int16_t) addressSpace
.get16(p
);
455 *(++sp
) = (pint_t
)svalue
;
457 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
461 // push immediate 4 byte value
462 value
= addressSpace
.get32(p
);
466 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
470 // push immediate 4 byte signed value
471 svalue
= (int32_t)addressSpace
.get32(p
);
473 *(++sp
) = (pint_t
)svalue
;
475 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
479 // push immediate 8 byte value
480 value
= (pint_t
)addressSpace
.get64(p
);
484 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
488 // push immediate 8 byte signed value
489 value
= (pint_t
)addressSpace
.get64(p
);
493 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
497 // push immediate ULEB128 value
498 value
= (pint_t
)addressSpace
.getULEB128(p
, expressionEnd
);
501 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
505 // push immediate SLEB128 value
506 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
507 *(++sp
) = (pint_t
)svalue
;
509 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
517 fprintf(stderr
, "duplicate top of stack\n");
524 fprintf(stderr
, "pop top of stack\n");
532 fprintf(stderr
, "duplicate second in stack\n");
537 reg
= addressSpace
.get8(p
);
539 value
= sp
[-(int)reg
];
542 fprintf(stderr
, "duplicate %d in stack\n", reg
);
551 fprintf(stderr
, "swap top of stack\n");
561 fprintf(stderr
, "rotate top three of stack\n");
565 // pop stack, dereference, push result
567 *sp
= *((pint_t
*)value
);
569 fprintf(stderr
, "x-dereference 0x%" PRIx64
"\n", (uint64_t)value
);
573 svalue
= (sint_t
)*sp
;
575 *sp
= (pint_t
)(-svalue
);
577 fprintf(stderr
, "abs\n");
584 fprintf(stderr
, "and\n");
588 svalue
= (sint_t
)(*sp
--);
589 svalue2
= (sint_t
)*sp
;
590 *sp
= (pint_t
)(svalue2
/ svalue
);
592 fprintf(stderr
, "div\n");
599 fprintf(stderr
, "minus\n");
603 svalue
= (sint_t
)(*sp
--);
604 svalue2
= (sint_t
)*sp
;
605 *sp
= (pint_t
)(svalue2
% svalue
);
607 fprintf(stderr
, "module\n");
611 svalue
= (sint_t
)(*sp
--);
612 svalue2
= (sint_t
)*sp
;
613 *sp
= (pint_t
)(svalue2
* svalue
);
615 fprintf(stderr
, "mul\n");
621 fprintf(stderr
, "neg\n");
625 svalue
= (sint_t
)(*sp
);
626 *sp
= (pint_t
)(~svalue
);
628 fprintf(stderr
, "not\n");
635 fprintf(stderr
, "or\n");
642 fprintf(stderr
, "plus\n");
645 case DW_OP_plus_uconst
:
646 // pop stack, add uelb128 constant, push result
647 *sp
+= static_cast<pint_t
>(addressSpace
.getULEB128(p
, expressionEnd
));
649 fprintf(stderr
, "add constant\n");
656 fprintf(stderr
, "shift left\n");
663 fprintf(stderr
, "shift left\n");
668 svalue
= (sint_t
)*sp
;
669 *sp
= (pint_t
)(svalue
>> value
);
671 fprintf(stderr
, "shift left arithmetic\n");
678 fprintf(stderr
, "xor\n");
682 svalue
= (int16_t) addressSpace
.get16(p
);
684 p
= (pint_t
)((sint_t
)p
+ svalue
);
686 fprintf(stderr
, "skip %" PRIu64
"\n", (uint64_t)svalue
);
690 svalue
= (int16_t) addressSpace
.get16(p
);
693 p
= (pint_t
)((sint_t
)p
+ svalue
);
695 fprintf(stderr
, "bra %" PRIu64
"\n", (uint64_t)svalue
);
700 *sp
= (*sp
== value
);
702 fprintf(stderr
, "eq\n");
707 *sp
= (*sp
>= value
);
709 fprintf(stderr
, "ge\n");
716 fprintf(stderr
, "gt\n");
721 *sp
= (*sp
<= value
);
723 fprintf(stderr
, "le\n");
730 fprintf(stderr
, "lt\n");
735 *sp
= (*sp
!= value
);
737 fprintf(stderr
, "ne\n");
772 value
= static_cast<pint_t
>(opcode
- DW_OP_lit0
);
775 fprintf(stderr
, "push literal 0x%" PRIx64
"\n", (uint64_t)value
);
810 reg
= static_cast<uint32_t>(opcode
- DW_OP_reg0
);
811 *(++sp
) = registers
.getRegister((int)reg
);
813 fprintf(stderr
, "push reg %d\n", reg
);
817 reg
= static_cast<uint32_t>(addressSpace
.getULEB128(p
, expressionEnd
));
818 *(++sp
) = registers
.getRegister((int)reg
);
820 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
855 reg
= static_cast<uint32_t>(opcode
- DW_OP_breg0
);
856 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
857 svalue
+= static_cast<sint_t
>(registers
.getRegister((int)reg
));
858 *(++sp
) = (pint_t
)(svalue
);
860 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
864 reg
= static_cast<uint32_t>(addressSpace
.getULEB128(p
, expressionEnd
));
865 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
866 svalue
+= static_cast<sint_t
>(registers
.getRegister((int)reg
));
867 *(++sp
) = (pint_t
)(svalue
);
869 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
873 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
877 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
880 case DW_OP_deref_size
:
881 // pop stack, dereference, push result
883 switch (addressSpace
.get8(p
++)) {
885 value
= addressSpace
.get8(value
);
888 value
= addressSpace
.get16(value
);
891 value
= addressSpace
.get32(value
);
894 value
= (pint_t
)addressSpace
.get64(value
);
897 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
901 fprintf(stderr
, "sized dereference 0x%" PRIx64
"\n", (uint64_t)value
);
904 case DW_OP_xderef_size
:
906 case DW_OP_push_object_addres
:
911 _LIBUNWIND_ABORT("DWARF opcode not implemented");
916 fprintf(stderr
, "expression evaluates to 0x%" PRIx64
"\n", (uint64_t)*sp
);
922 } // namespace libunwind
924 #endif // __DWARF_INSTRUCTIONS_HPP__