1 //===-------------------------- DwarfInstructions.hpp ---------------------===//
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__
20 #include "Registers.hpp"
21 #include "DwarfParser.hpp"
28 /// DwarfInstructions maps abtract DWARF unwind instructions to a particular
30 template <typename A
, typename R
>
31 class DwarfInstructions
{
33 typedef typename
A::pint_t pint_t
;
34 typedef typename
A::sint_t sint_t
;
36 static int stepWithDwarf(A
&addressSpace
, pint_t pc
, pint_t fdeStart
,
37 R
®isters
, bool &isSignalFrame
);
42 DW_X86_64_RET_ADDR
= 16
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
;
54 static pint_t
evaluateExpression(pint_t expression
, A
&addressSpace
,
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
);
64 static pint_t
getCFA(A
&addressSpace
, const PrologInfo
&prolog
,
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
,
72 assert(0 && "getCFA(): unknown location");
73 __builtin_unreachable();
78 template <typename A
, typename R
>
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
);
86 case CFI_Parser
<A
>::kRegisterAtExpression
:
87 return (pint_t
)addressSpace
.getRegister(evaluateExpression(
88 (pint_t
)savedReg
.value
, addressSpace
, registers
, cfa
));
90 case CFI_Parser
<A
>::kRegisterIsExpression
:
91 return evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
94 case CFI_Parser
<A
>::kRegisterInRegister
:
95 return registers
.getRegister((int)savedReg
.value
);
97 case CFI_Parser
<A
>::kRegisterUnused
:
98 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
102 _LIBUNWIND_ABORT("unsupported restore location for register");
105 template <typename A
, typename R
>
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
);
113 case CFI_Parser
<A
>::kRegisterAtExpression
:
114 return addressSpace
.getDouble(
115 evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
118 case CFI_Parser
<A
>::kRegisterIsExpression
:
119 case CFI_Parser
<A
>::kRegisterUnused
:
120 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
121 case CFI_Parser
<A
>::kRegisterInRegister
:
125 _LIBUNWIND_ABORT("unsupported restore location for float register");
128 template <typename A
, typename R
>
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
);
136 case CFI_Parser
<A
>::kRegisterAtExpression
:
137 return addressSpace
.getVector(
138 evaluateExpression((pint_t
)savedReg
.value
, addressSpace
,
141 case CFI_Parser
<A
>::kRegisterIsExpression
:
142 case CFI_Parser
<A
>::kRegisterUnused
:
143 case CFI_Parser
<A
>::kRegisterOffsetFromCFA
:
144 case CFI_Parser
<A
>::kRegisterInRegister
:
148 _LIBUNWIND_ABORT("unsupported restore location for vector register");
151 template <typename A
, typename R
>
152 int DwarfInstructions
<A
, R
>::stepWithDwarf(A
&addressSpace
, pint_t pc
,
153 pint_t fdeStart
, R
®isters
,
154 bool &isSignalFrame
) {
157 if (CFI_Parser
<A
>::decodeFDE(addressSpace
, fdeStart
, &fdeInfo
,
160 if (CFI_Parser
<A
>::parseFDEInstructions(addressSpace
, fdeInfo
, cieInfo
, pc
,
161 R::getArch(), &prolog
)) {
162 // get pointer to cfa (architecture specific)
163 pint_t cfa
= getCFA(addressSpace
, prolog
, registers
);
165 // restore registers that DWARF says were saved
166 R newRegisters
= registers
;
167 pint_t returnAddress
= 0;
168 const int lastReg
= R::lastDwarfRegNum();
169 assert(static_cast<int>(CFI_Parser
<A
>::kMaxRegisterNumber
) >= lastReg
&&
170 "register range too large");
171 assert(lastReg
>= (int)cieInfo
.returnAddressRegister
&&
172 "register range does not contain return address register");
173 for (int i
= 0; i
<= lastReg
; ++i
) {
174 if (prolog
.savedRegisters
[i
].location
!=
175 CFI_Parser
<A
>::kRegisterUnused
) {
176 if (registers
.validFloatRegister(i
))
177 newRegisters
.setFloatRegister(
178 i
, getSavedFloatRegister(addressSpace
, registers
, cfa
,
179 prolog
.savedRegisters
[i
]));
180 else if (registers
.validVectorRegister(i
))
181 newRegisters
.setVectorRegister(
182 i
, getSavedVectorRegister(addressSpace
, registers
, cfa
,
183 prolog
.savedRegisters
[i
]));
184 else if (i
== (int)cieInfo
.returnAddressRegister
)
185 returnAddress
= getSavedRegister(addressSpace
, registers
, cfa
,
186 prolog
.savedRegisters
[i
]);
187 else if (registers
.validRegister(i
))
188 newRegisters
.setRegister(
189 i
, getSavedRegister(addressSpace
, registers
, cfa
,
190 prolog
.savedRegisters
[i
]));
196 // By definition, the CFA is the stack pointer at the call site, so
197 // restoring SP means setting it to CFA.
198 newRegisters
.setSP(cfa
);
200 isSignalFrame
= cieInfo
.isSignalFrame
;
202 #if defined(_LIBUNWIND_TARGET_AARCH64)
203 // If the target is aarch64 then the return address may have been signed
204 // using the v8.3 pointer authentication extensions. The original
205 // return address needs to be authenticated before the return address is
206 // restored. autia1716 is used instead of autia as autia1716 assembles
207 // to a NOP on pre-v8.3a architectures.
208 if ((R::getArch() == REGISTERS_ARM64
) &&
209 prolog
.savedRegisters
[UNW_ARM64_RA_SIGN_STATE
].value
) {
210 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
211 return UNW_ECROSSRASIGNING
;
213 register unsigned long long x17
__asm("x17") = returnAddress
;
214 register unsigned long long x16
__asm("x16") = cfa
;
216 // These are the autia1716/autib1716 instructions. The hint instructions
217 // are used here as gcc does not assemble autia1716/autib1716 for pre
219 if (cieInfo
.addressesSignedWithBKey
)
220 asm("hint 0xe" : "+r"(x17
) : "r"(x16
)); // autib1716
222 asm("hint 0xc" : "+r"(x17
) : "r"(x16
)); // autia1716
228 #if defined(_LIBUNWIND_TARGET_SPARC)
229 if (R::getArch() == REGISTERS_SPARC
) {
230 // Skip call site instruction and delay slot
232 // Skip unimp instruction if function returns a struct
233 if ((addressSpace
.get32(returnAddress
) & 0xC1C00000) == 0)
238 #if defined(_LIBUNWIND_TARGET_PPC64)
239 #define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
240 #define PPC64_ELFV1_R2_OFFSET 40
241 #define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1)
242 #define PPC64_ELFV2_R2_OFFSET 24
243 // If the instruction at return address is a TOC (r2) restore,
244 // then r2 was saved and needs to be restored.
245 // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24,
246 // while in ELFv1 ABI it is saved at SP + 40.
247 if (R::getArch() == REGISTERS_PPC64
&& returnAddress
!= 0) {
248 pint_t sp
= newRegisters
.getRegister(UNW_REG_SP
);
250 switch (addressSpace
.get32(returnAddress
)) {
251 case PPC64_ELFV1_R2_LOAD_INST_ENCODING
:
252 r2
= addressSpace
.get64(sp
+ PPC64_ELFV1_R2_OFFSET
);
254 case PPC64_ELFV2_R2_LOAD_INST_ENCODING
:
255 r2
= addressSpace
.get64(sp
+ PPC64_ELFV2_R2_OFFSET
);
259 newRegisters
.setRegister(UNW_PPC64_R2
, r2
);
263 // Return address is address after call site instruction, so setting IP to
264 // that does simualates a return.
265 newRegisters
.setIP(returnAddress
);
267 // Simulate the step by replacing the register set with the new ones.
268 registers
= newRegisters
;
270 return UNW_STEP_SUCCESS
;
273 return UNW_EBADFRAME
;
276 template <typename A
, typename R
>
278 DwarfInstructions
<A
, R
>::evaluateExpression(pint_t expression
, A
&addressSpace
,
280 pint_t initialStackValue
) {
281 const bool log
= false;
282 pint_t p
= expression
;
283 pint_t expressionEnd
= expression
+ 20; // temp, until len read
284 pint_t length
= (pint_t
)addressSpace
.getULEB128(p
, expressionEnd
);
285 expressionEnd
= p
+ length
;
287 fprintf(stderr
, "evaluateExpression(): length=%" PRIu64
"\n",
291 *(++sp
) = initialStackValue
;
293 while (p
< expressionEnd
) {
295 for (pint_t
*t
= sp
; t
> stack
; --t
) {
296 fprintf(stderr
, "sp[] = 0x%" PRIx64
"\n", (uint64_t)(*t
));
299 uint8_t opcode
= addressSpace
.get8(p
++);
300 sint_t svalue
, svalue2
;
305 // push immediate address sized value
306 value
= addressSpace
.getP(p
);
310 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
314 // pop stack, dereference, push result
316 *(++sp
) = addressSpace
.getP(value
);
318 fprintf(stderr
, "dereference 0x%" PRIx64
"\n", (uint64_t)value
);
322 // push immediate 1 byte value
323 value
= addressSpace
.get8(p
);
327 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
331 // push immediate 1 byte signed value
332 svalue
= (int8_t) addressSpace
.get8(p
);
334 *(++sp
) = (pint_t
)svalue
;
336 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
340 // push immediate 2 byte value
341 value
= addressSpace
.get16(p
);
345 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
349 // push immediate 2 byte signed value
350 svalue
= (int16_t) addressSpace
.get16(p
);
352 *(++sp
) = (pint_t
)svalue
;
354 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
358 // push immediate 4 byte value
359 value
= addressSpace
.get32(p
);
363 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
367 // push immediate 4 byte signed value
368 svalue
= (int32_t)addressSpace
.get32(p
);
370 *(++sp
) = (pint_t
)svalue
;
372 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
376 // push immediate 8 byte value
377 value
= (pint_t
)addressSpace
.get64(p
);
381 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
385 // push immediate 8 byte signed value
386 value
= (pint_t
)addressSpace
.get64(p
);
390 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
394 // push immediate ULEB128 value
395 value
= (pint_t
)addressSpace
.getULEB128(p
, expressionEnd
);
398 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)value
);
402 // push immediate SLEB128 value
403 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
404 *(++sp
) = (pint_t
)svalue
;
406 fprintf(stderr
, "push 0x%" PRIx64
"\n", (uint64_t)svalue
);
414 fprintf(stderr
, "duplicate top of stack\n");
421 fprintf(stderr
, "pop top of stack\n");
429 fprintf(stderr
, "duplicate second in stack\n");
434 reg
= addressSpace
.get8(p
);
436 value
= sp
[-(int)reg
];
439 fprintf(stderr
, "duplicate %d in stack\n", reg
);
448 fprintf(stderr
, "swap top of stack\n");
458 fprintf(stderr
, "rotate top three of stack\n");
462 // pop stack, dereference, push result
464 *sp
= *((pint_t
*)value
);
466 fprintf(stderr
, "x-dereference 0x%" PRIx64
"\n", (uint64_t)value
);
470 svalue
= (sint_t
)*sp
;
472 *sp
= (pint_t
)(-svalue
);
474 fprintf(stderr
, "abs\n");
481 fprintf(stderr
, "and\n");
485 svalue
= (sint_t
)(*sp
--);
486 svalue2
= (sint_t
)*sp
;
487 *sp
= (pint_t
)(svalue2
/ svalue
);
489 fprintf(stderr
, "div\n");
496 fprintf(stderr
, "minus\n");
500 svalue
= (sint_t
)(*sp
--);
501 svalue2
= (sint_t
)*sp
;
502 *sp
= (pint_t
)(svalue2
% svalue
);
504 fprintf(stderr
, "module\n");
508 svalue
= (sint_t
)(*sp
--);
509 svalue2
= (sint_t
)*sp
;
510 *sp
= (pint_t
)(svalue2
* svalue
);
512 fprintf(stderr
, "mul\n");
518 fprintf(stderr
, "neg\n");
522 svalue
= (sint_t
)(*sp
);
523 *sp
= (pint_t
)(~svalue
);
525 fprintf(stderr
, "not\n");
532 fprintf(stderr
, "or\n");
539 fprintf(stderr
, "plus\n");
542 case DW_OP_plus_uconst
:
543 // pop stack, add uelb128 constant, push result
544 *sp
+= static_cast<pint_t
>(addressSpace
.getULEB128(p
, expressionEnd
));
546 fprintf(stderr
, "add constant\n");
553 fprintf(stderr
, "shift left\n");
560 fprintf(stderr
, "shift left\n");
565 svalue
= (sint_t
)*sp
;
566 *sp
= (pint_t
)(svalue
>> value
);
568 fprintf(stderr
, "shift left arithmetric\n");
575 fprintf(stderr
, "xor\n");
579 svalue
= (int16_t) addressSpace
.get16(p
);
581 p
= (pint_t
)((sint_t
)p
+ svalue
);
583 fprintf(stderr
, "skip %" PRIu64
"\n", (uint64_t)svalue
);
587 svalue
= (int16_t) addressSpace
.get16(p
);
590 p
= (pint_t
)((sint_t
)p
+ svalue
);
592 fprintf(stderr
, "bra %" PRIu64
"\n", (uint64_t)svalue
);
597 *sp
= (*sp
== value
);
599 fprintf(stderr
, "eq\n");
604 *sp
= (*sp
>= value
);
606 fprintf(stderr
, "ge\n");
613 fprintf(stderr
, "gt\n");
618 *sp
= (*sp
<= value
);
620 fprintf(stderr
, "le\n");
627 fprintf(stderr
, "lt\n");
632 *sp
= (*sp
!= value
);
634 fprintf(stderr
, "ne\n");
669 value
= static_cast<pint_t
>(opcode
- DW_OP_lit0
);
672 fprintf(stderr
, "push literal 0x%" PRIx64
"\n", (uint64_t)value
);
707 reg
= static_cast<uint32_t>(opcode
- DW_OP_reg0
);
708 *(++sp
) = registers
.getRegister((int)reg
);
710 fprintf(stderr
, "push reg %d\n", reg
);
714 reg
= static_cast<uint32_t>(addressSpace
.getULEB128(p
, expressionEnd
));
715 *(++sp
) = registers
.getRegister((int)reg
);
717 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
752 reg
= static_cast<uint32_t>(opcode
- DW_OP_breg0
);
753 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
754 svalue
+= static_cast<sint_t
>(registers
.getRegister((int)reg
));
755 *(++sp
) = (pint_t
)(svalue
);
757 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
761 reg
= static_cast<uint32_t>(addressSpace
.getULEB128(p
, expressionEnd
));
762 svalue
= (sint_t
)addressSpace
.getSLEB128(p
, expressionEnd
);
763 svalue
+= static_cast<sint_t
>(registers
.getRegister((int)reg
));
764 *(++sp
) = (pint_t
)(svalue
);
766 fprintf(stderr
, "push reg %d + 0x%" PRIx64
"\n", reg
, (uint64_t)svalue
);
770 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
774 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
777 case DW_OP_deref_size
:
778 // pop stack, dereference, push result
780 switch (addressSpace
.get8(p
++)) {
782 value
= addressSpace
.get8(value
);
785 value
= addressSpace
.get16(value
);
788 value
= addressSpace
.get32(value
);
791 value
= (pint_t
)addressSpace
.get64(value
);
794 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
798 fprintf(stderr
, "sized dereference 0x%" PRIx64
"\n", (uint64_t)value
);
801 case DW_OP_xderef_size
:
803 case DW_OP_push_object_addres
:
808 _LIBUNWIND_ABORT("DWARF opcode not implemented");
813 fprintf(stderr
, "expression evaluates to 0x%" PRIx64
"\n", (uint64_t)*sp
);
819 } // namespace libunwind
821 #endif // __DWARF_INSTRUCTIONS_HPP__