1 //===-------------------------- DwarfInstructions.hpp ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
9 // Processor specific interpretation of DWARF unwind info.
11 //===----------------------------------------------------------------------===//
13 #ifndef __DWARF_INSTRUCTIONS_HPP__
14 #define __DWARF_INSTRUCTIONS_HPP__
21 #include "Registers.hpp"
22 #include "DwarfParser.hpp"
29 /// DwarfInstructions maps abtract 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,
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();
79 template <typename A, typename R>
80 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
81 A &addressSpace, const R ®isters, pint_t cfa,
82 const RegisterLocation &savedReg) {
83 switch (savedReg.location) {
84 case CFI_Parser<A>::kRegisterInCFA:
85 return addressSpace.getRegister(cfa + (pint_t)savedReg.value);
87 case CFI_Parser<A>::kRegisterAtExpression:
88 return addressSpace.getRegister(
89 evaluateExpression((pint_t)savedReg.value, addressSpace,
92 case CFI_Parser<A>::kRegisterIsExpression:
93 return evaluateExpression((pint_t)savedReg.value, addressSpace,
96 case CFI_Parser<A>::kRegisterInRegister:
97 return registers.getRegister((int)savedReg.value);
99 case CFI_Parser<A>::kRegisterUnused:
100 case CFI_Parser<A>::kRegisterOffsetFromCFA:
104 _LIBUNWIND_ABORT("unsupported restore location for register");
107 template <typename A, typename R>
108 double DwarfInstructions<A, R>::getSavedFloatRegister(
109 A &addressSpace, const R ®isters, pint_t cfa,
110 const RegisterLocation &savedReg) {
111 switch (savedReg.location) {
112 case CFI_Parser<A>::kRegisterInCFA:
113 return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
115 case CFI_Parser<A>::kRegisterAtExpression:
116 return addressSpace.getDouble(
117 evaluateExpression((pint_t)savedReg.value, addressSpace,
120 case CFI_Parser<A>::kRegisterIsExpression:
121 case CFI_Parser<A>::kRegisterUnused:
122 case CFI_Parser<A>::kRegisterOffsetFromCFA:
123 case CFI_Parser<A>::kRegisterInRegister:
127 _LIBUNWIND_ABORT("unsupported restore location for float register");
130 template <typename A, typename R>
131 v128 DwarfInstructions<A, R>::getSavedVectorRegister(
132 A &addressSpace, const R ®isters, pint_t cfa,
133 const RegisterLocation &savedReg) {
134 switch (savedReg.location) {
135 case CFI_Parser<A>::kRegisterInCFA:
136 return addressSpace.getVector(cfa + (pint_t)savedReg.value);
138 case CFI_Parser<A>::kRegisterAtExpression:
139 return addressSpace.getVector(
140 evaluateExpression((pint_t)savedReg.value, addressSpace,
143 case CFI_Parser<A>::kRegisterIsExpression:
144 case CFI_Parser<A>::kRegisterUnused:
145 case CFI_Parser<A>::kRegisterOffsetFromCFA:
146 case CFI_Parser<A>::kRegisterInRegister:
150 _LIBUNWIND_ABORT("unsupported restore location for vector register");
153 template <typename A, typename R>
154 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
155 pint_t fdeStart, R ®isters) {
158 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
161 if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
162 R::getArch(), &prolog)) {
163 // get pointer to cfa (architecture specific)
164 pint_t cfa = getCFA(addressSpace, prolog, registers);
166 // restore registers that DWARF says were saved
167 R newRegisters = registers;
168 pint_t returnAddress = 0;
169 const int lastReg = R::lastDwarfRegNum();
170 assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
171 "register range too large");
172 assert(lastReg >= (int)cieInfo.returnAddressRegister &&
173 "register range does not contain return address register");
174 for (int i = 0; i <= lastReg; ++i) {
175 if (prolog.savedRegisters[i].location !=
176 CFI_Parser<A>::kRegisterUnused) {
177 if (registers.validFloatRegister(i))
178 newRegisters.setFloatRegister(
179 i, getSavedFloatRegister(addressSpace, registers, cfa,
180 prolog.savedRegisters[i]));
181 else if (registers.validVectorRegister(i))
182 newRegisters.setVectorRegister(
183 i, getSavedVectorRegister(addressSpace, registers, cfa,
184 prolog.savedRegisters[i]));
185 else if (i == (int)cieInfo.returnAddressRegister)
186 returnAddress = getSavedRegister(addressSpace, registers, cfa,
187 prolog.savedRegisters[i]);
188 else if (registers.validRegister(i))
189 newRegisters.setRegister(
190 i, getSavedRegister(addressSpace, registers, cfa,
191 prolog.savedRegisters[i]));
197 // By definition, the CFA is the stack pointer at the call site, so
198 // restoring SP means setting it to CFA.
199 newRegisters.setSP(cfa);
201 #if defined(_LIBUNWIND_TARGET_AARCH64)
202 // If the target is aarch64 then the return address may have been signed
203 // using the v8.3 pointer authentication extensions. The original
204 // return address needs to be authenticated before the return address is
205 // restored. autia1716 is used instead of autia as autia1716 assembles
206 // to a NOP on pre-v8.3a architectures.
207 if ((R::getArch() == REGISTERS_ARM64) &&
208 prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
209 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
210 return UNW_ECROSSRASIGNING;
212 register unsigned long long x17 __asm("x17") = returnAddress;
213 register unsigned long long x16 __asm("x16") = cfa;
215 // These are the autia1716/autib1716 instructions. The hint instructions
216 // are used here as gcc does not assemble autia1716/autib1716 for pre
218 if (cieInfo.addressesSignedWithBKey)
219 asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
221 asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
227 #if defined(_LIBUNWIND_TARGET_SPARC)
228 if (R::getArch() == REGISTERS_SPARC) {
229 // Skip call site instruction and delay slot
231 // Skip unimp instruction if function returns a struct
232 if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
237 // Return address is address after call site instruction, so setting IP to
238 // that does simualates a return.
239 newRegisters.setIP(returnAddress);
241 // Simulate the step by replacing the register set with the new ones.
242 registers = newRegisters;
244 return UNW_STEP_SUCCESS;
247 return UNW_EBADFRAME;
250 template <typename A, typename R>
252 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
254 pint_t initialStackValue) {
255 const bool log = false;
256 pint_t p = expression;
257 pint_t expressionEnd = expression + 20; // temp, until len read
258 pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
259 expressionEnd = p + length;
261 fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
265 *(++sp) = initialStackValue;
267 while (p < expressionEnd) {
269 for (pint_t *t = sp; t > stack; --t) {
270 fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
273 uint8_t opcode = addressSpace.get8(p++);
274 sint_t svalue, svalue2;
279 // push immediate address sized value
280 value = addressSpace.getP(p);
284 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
288 // pop stack, dereference, push result
290 *(++sp) = addressSpace.getP(value);
292 fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
296 // push immediate 1 byte value
297 value = addressSpace.get8(p);
301 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
305 // push immediate 1 byte signed value
306 svalue = (int8_t) addressSpace.get8(p);
308 *(++sp) = (pint_t)svalue;
310 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
314 // push immediate 2 byte value
315 value = addressSpace.get16(p);
319 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
323 // push immediate 2 byte signed value
324 svalue = (int16_t) addressSpace.get16(p);
326 *(++sp) = (pint_t)svalue;
328 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
332 // push immediate 4 byte value
333 value = addressSpace.get32(p);
337 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
341 // push immediate 4 byte signed value
342 svalue = (int32_t)addressSpace.get32(p);
344 *(++sp) = (pint_t)svalue;
346 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
350 // push immediate 8 byte value
351 value = (pint_t)addressSpace.get64(p);
355 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
359 // push immediate 8 byte signed value
360 value = (pint_t)addressSpace.get64(p);
364 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
368 // push immediate ULEB128 value
369 value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
372 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
376 // push immediate SLEB128 value
377 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
378 *(++sp) = (pint_t)svalue;
380 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
388 fprintf(stderr, "duplicate top of stack\n");
395 fprintf(stderr, "pop top of stack\n");
403 fprintf(stderr, "duplicate second in stack\n");
408 reg = addressSpace.get8(p);
413 fprintf(stderr, "duplicate %d in stack\n", reg);
422 fprintf(stderr, "swap top of stack\n");
432 fprintf(stderr, "rotate top three of stack\n");
436 // pop stack, dereference, push result
438 *sp = *((pint_t*)value);
440 fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
444 svalue = (sint_t)*sp;
446 *sp = (pint_t)(-svalue);
448 fprintf(stderr, "abs\n");
455 fprintf(stderr, "and\n");
459 svalue = (sint_t)(*sp--);
460 svalue2 = (sint_t)*sp;
461 *sp = (pint_t)(svalue2 / svalue);
463 fprintf(stderr, "div\n");
470 fprintf(stderr, "minus\n");
474 svalue = (sint_t)(*sp--);
475 svalue2 = (sint_t)*sp;
476 *sp = (pint_t)(svalue2 % svalue);
478 fprintf(stderr, "module\n");
482 svalue = (sint_t)(*sp--);
483 svalue2 = (sint_t)*sp;
484 *sp = (pint_t)(svalue2 * svalue);
486 fprintf(stderr, "mul\n");
492 fprintf(stderr, "neg\n");
496 svalue = (sint_t)(*sp);
497 *sp = (pint_t)(~svalue);
499 fprintf(stderr, "not\n");
506 fprintf(stderr, "or\n");
513 fprintf(stderr, "plus\n");
516 case DW_OP_plus_uconst:
517 // pop stack, add uelb128 constant, push result
518 *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
520 fprintf(stderr, "add constant\n");
527 fprintf(stderr, "shift left\n");
534 fprintf(stderr, "shift left\n");
539 svalue = (sint_t)*sp;
540 *sp = (pint_t)(svalue >> value);
542 fprintf(stderr, "shift left arithmetric\n");
549 fprintf(stderr, "xor\n");
553 svalue = (int16_t) addressSpace.get16(p);
555 p = (pint_t)((sint_t)p + svalue);
557 fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
561 svalue = (int16_t) addressSpace.get16(p);
564 p = (pint_t)((sint_t)p + svalue);
566 fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
571 *sp = (*sp == value);
573 fprintf(stderr, "eq\n");
578 *sp = (*sp >= value);
580 fprintf(stderr, "ge\n");
587 fprintf(stderr, "gt\n");
592 *sp = (*sp <= value);
594 fprintf(stderr, "le\n");
601 fprintf(stderr, "lt\n");
606 *sp = (*sp != value);
608 fprintf(stderr, "ne\n");
643 value = static_cast<pint_t>(opcode - DW_OP_lit0);
646 fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
681 reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
682 *(++sp) = registers.getRegister((int)reg);
684 fprintf(stderr, "push reg %d\n", reg);
688 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
689 *(++sp) = registers.getRegister((int)reg);
691 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
726 reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
727 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
728 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
729 *(++sp) = (pint_t)(svalue);
731 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
735 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
736 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
737 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
738 *(++sp) = (pint_t)(svalue);
740 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
744 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
748 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
751 case DW_OP_deref_size:
752 // pop stack, dereference, push result
754 switch (addressSpace.get8(p++)) {
756 value = addressSpace.get8(value);
759 value = addressSpace.get16(value);
762 value = addressSpace.get32(value);
765 value = (pint_t)addressSpace.get64(value);
768 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
772 fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
775 case DW_OP_xderef_size:
777 case DW_OP_push_object_addres:
782 _LIBUNWIND_ABORT("DWARF opcode not implemented");
787 fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
793 } // namespace libunwind
795 #endif // __DWARF_INSTRUCTIONS_HPP__