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 "AddressSpace.hpp"
22 #include "Registers.hpp"
23 #include "DwarfParser.hpp"
30 /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
32 template <typename A, typename R>
33 class DwarfInstructions {
35 typedef typename A::pint_t pint_t;
36 typedef typename A::sint_t sint_t;
38 static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
44 DW_X86_64_RET_ADDR = 16
51 typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;
52 typedef typename CFI_Parser<A>::PrologInfo PrologInfo;
53 typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
54 typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
56 static pint_t evaluateExpression(pint_t expression, A &addressSpace,
58 pint_t initialStackValue);
59 static pint_t getSavedRegister(A &addressSpace, const R ®isters,
60 pint_t cfa, const RegisterLocation &savedReg);
61 static double getSavedFloatRegister(A &addressSpace, const R ®isters,
62 pint_t cfa, const RegisterLocation &savedReg);
63 static v128 getSavedVectorRegister(A &addressSpace, const R ®isters,
64 pint_t cfa, const RegisterLocation &savedReg);
66 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
68 if (prolog.cfaRegister != 0)
69 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
70 prolog.cfaRegisterOffset);
71 if (prolog.cfaExpression != 0)
72 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
74 assert(0 && "getCFA(): unknown location");
75 __builtin_unreachable();
80 template <typename A, typename R>
81 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
82 A &addressSpace, const R ®isters, pint_t cfa,
83 const RegisterLocation &savedReg) {
84 switch (savedReg.location) {
85 case CFI_Parser<A>::kRegisterInCFA:
86 return addressSpace.getP(cfa + (pint_t)savedReg.value);
88 case CFI_Parser<A>::kRegisterAtExpression:
89 return addressSpace.getP(
90 evaluateExpression((pint_t)savedReg.value, addressSpace,
93 case CFI_Parser<A>::kRegisterIsExpression:
94 return evaluateExpression((pint_t)savedReg.value, addressSpace,
97 case CFI_Parser<A>::kRegisterInRegister:
98 return registers.getRegister((int)savedReg.value);
100 case CFI_Parser<A>::kRegisterUnused:
101 case CFI_Parser<A>::kRegisterOffsetFromCFA:
105 _LIBUNWIND_ABORT("unsupported restore location for register");
108 template <typename A, typename R>
109 double DwarfInstructions<A, R>::getSavedFloatRegister(
110 A &addressSpace, const R ®isters, pint_t cfa,
111 const RegisterLocation &savedReg) {
112 switch (savedReg.location) {
113 case CFI_Parser<A>::kRegisterInCFA:
114 return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
116 case CFI_Parser<A>::kRegisterAtExpression:
117 return addressSpace.getDouble(
118 evaluateExpression((pint_t)savedReg.value, addressSpace,
121 case CFI_Parser<A>::kRegisterIsExpression:
122 case CFI_Parser<A>::kRegisterUnused:
123 case CFI_Parser<A>::kRegisterOffsetFromCFA:
124 case CFI_Parser<A>::kRegisterInRegister:
128 _LIBUNWIND_ABORT("unsupported restore location for float register");
131 template <typename A, typename R>
132 v128 DwarfInstructions<A, R>::getSavedVectorRegister(
133 A &addressSpace, const R ®isters, pint_t cfa,
134 const RegisterLocation &savedReg) {
135 switch (savedReg.location) {
136 case CFI_Parser<A>::kRegisterInCFA:
137 return addressSpace.getVector(cfa + (pint_t)savedReg.value);
139 case CFI_Parser<A>::kRegisterAtExpression:
140 return addressSpace.getVector(
141 evaluateExpression((pint_t)savedReg.value, addressSpace,
144 case CFI_Parser<A>::kRegisterIsExpression:
145 case CFI_Parser<A>::kRegisterUnused:
146 case CFI_Parser<A>::kRegisterOffsetFromCFA:
147 case CFI_Parser<A>::kRegisterInRegister:
151 _LIBUNWIND_ABORT("unsupported restore location for vector register");
154 template <typename A, typename R>
155 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
156 pint_t fdeStart, R ®isters) {
159 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
162 if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
164 // get pointer to cfa (architecture specific)
165 pint_t cfa = getCFA(addressSpace, prolog, registers);
167 // restore registers that dwarf says were saved
168 R newRegisters = registers;
169 pint_t returnAddress = 0;
170 const int lastReg = R::lastDwarfRegNum();
171 assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg &&
172 "register range too large");
173 assert(lastReg >= (int)cieInfo.returnAddressRegister &&
174 "register range does not contain return address register");
175 for (int i = 0; i <= lastReg; ++i) {
176 if (prolog.savedRegisters[i].location !=
177 CFI_Parser<A>::kRegisterUnused) {
178 if (registers.validFloatRegister(i))
179 newRegisters.setFloatRegister(
180 i, getSavedFloatRegister(addressSpace, registers, cfa,
181 prolog.savedRegisters[i]));
182 else if (registers.validVectorRegister(i))
183 newRegisters.setVectorRegister(
184 i, getSavedVectorRegister(addressSpace, registers, cfa,
185 prolog.savedRegisters[i]));
186 else if (i == (int)cieInfo.returnAddressRegister)
187 returnAddress = getSavedRegister(addressSpace, registers, cfa,
188 prolog.savedRegisters[i]);
189 else if (registers.validRegister(i))
190 newRegisters.setRegister(
191 i, getSavedRegister(addressSpace, registers, cfa,
192 prolog.savedRegisters[i]));
198 // By definition, the CFA is the stack pointer at the call site, so
199 // restoring SP means setting it to CFA.
200 newRegisters.setSP(cfa);
202 // Return address is address after call site instruction, so setting IP to
203 // that does simualates a return.
204 newRegisters.setIP(returnAddress);
206 // Simulate the step by replacing the register set with the new ones.
207 registers = newRegisters;
209 return UNW_STEP_SUCCESS;
212 return UNW_EBADFRAME;
215 template <typename A, typename R>
217 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
219 pint_t initialStackValue) {
220 const bool log = false;
221 pint_t p = expression;
222 pint_t expressionEnd = expression + 20; // temp, until len read
223 pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
224 expressionEnd = p + length;
226 fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
230 *(++sp) = initialStackValue;
232 while (p < expressionEnd) {
234 for (pint_t *t = sp; t > stack; --t) {
235 fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
238 uint8_t opcode = addressSpace.get8(p++);
239 sint_t svalue, svalue2;
244 // push immediate address sized value
245 value = addressSpace.getP(p);
249 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
253 // pop stack, dereference, push result
255 *(++sp) = addressSpace.getP(value);
257 fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
261 // push immediate 1 byte value
262 value = addressSpace.get8(p);
266 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
270 // push immediate 1 byte signed value
271 svalue = (int8_t) addressSpace.get8(p);
273 *(++sp) = (pint_t)svalue;
275 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
279 // push immediate 2 byte value
280 value = addressSpace.get16(p);
284 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
288 // push immediate 2 byte signed value
289 svalue = (int16_t) addressSpace.get16(p);
291 *(++sp) = (pint_t)svalue;
293 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
297 // push immediate 4 byte value
298 value = addressSpace.get32(p);
302 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
306 // push immediate 4 byte signed value
307 svalue = (int32_t)addressSpace.get32(p);
309 *(++sp) = (pint_t)svalue;
311 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
315 // push immediate 8 byte value
316 value = (pint_t)addressSpace.get64(p);
320 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
324 // push immediate 8 byte signed value
325 value = (pint_t)addressSpace.get64(p);
329 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
333 // push immediate ULEB128 value
334 value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
337 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
341 // push immediate SLEB128 value
342 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
343 *(++sp) = (pint_t)svalue;
345 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
353 fprintf(stderr, "duplicate top of stack\n");
360 fprintf(stderr, "pop top of stack\n");
368 fprintf(stderr, "duplicate second in stack\n");
373 reg = addressSpace.get8(p);
378 fprintf(stderr, "duplicate %d in stack\n", reg);
387 fprintf(stderr, "swap top of stack\n");
397 fprintf(stderr, "rotate top three of stack\n");
401 // pop stack, dereference, push result
403 *sp = *((pint_t*)value);
405 fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
409 svalue = (sint_t)*sp;
411 *sp = (pint_t)(-svalue);
413 fprintf(stderr, "abs\n");
420 fprintf(stderr, "and\n");
424 svalue = (sint_t)(*sp--);
425 svalue2 = (sint_t)*sp;
426 *sp = (pint_t)(svalue2 / svalue);
428 fprintf(stderr, "div\n");
435 fprintf(stderr, "minus\n");
439 svalue = (sint_t)(*sp--);
440 svalue2 = (sint_t)*sp;
441 *sp = (pint_t)(svalue2 % svalue);
443 fprintf(stderr, "module\n");
447 svalue = (sint_t)(*sp--);
448 svalue2 = (sint_t)*sp;
449 *sp = (pint_t)(svalue2 * svalue);
451 fprintf(stderr, "mul\n");
457 fprintf(stderr, "neg\n");
461 svalue = (sint_t)(*sp);
462 *sp = (pint_t)(~svalue);
464 fprintf(stderr, "not\n");
471 fprintf(stderr, "or\n");
478 fprintf(stderr, "plus\n");
481 case DW_OP_plus_uconst:
482 // pop stack, add uelb128 constant, push result
483 *sp += addressSpace.getULEB128(p, expressionEnd);
485 fprintf(stderr, "add constant\n");
492 fprintf(stderr, "shift left\n");
499 fprintf(stderr, "shift left\n");
504 svalue = (sint_t)*sp;
505 *sp = (pint_t)(svalue >> value);
507 fprintf(stderr, "shift left arithmetric\n");
514 fprintf(stderr, "xor\n");
518 svalue = (int16_t) addressSpace.get16(p);
520 p = (pint_t)((sint_t)p + svalue);
522 fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
526 svalue = (int16_t) addressSpace.get16(p);
529 p = (pint_t)((sint_t)p + svalue);
531 fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
536 *sp = (*sp == value);
538 fprintf(stderr, "eq\n");
543 *sp = (*sp >= value);
545 fprintf(stderr, "ge\n");
552 fprintf(stderr, "gt\n");
557 *sp = (*sp <= value);
559 fprintf(stderr, "le\n");
566 fprintf(stderr, "lt\n");
571 *sp = (*sp != value);
573 fprintf(stderr, "ne\n");
608 value = static_cast<pint_t>(opcode - DW_OP_lit0);
611 fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
646 reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
647 *(++sp) = registers.getRegister((int)reg);
649 fprintf(stderr, "push reg %d\n", reg);
653 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
654 *(++sp) = registers.getRegister((int)reg);
656 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
691 reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
692 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
693 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
694 *(++sp) = (pint_t)(svalue);
696 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
700 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
701 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
702 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
703 *(++sp) = (pint_t)(svalue);
705 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
709 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
713 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
716 case DW_OP_deref_size:
717 // pop stack, dereference, push result
719 switch (addressSpace.get8(p++)) {
721 value = addressSpace.get8(value);
724 value = addressSpace.get16(value);
727 value = addressSpace.get32(value);
730 value = (pint_t)addressSpace.get64(value);
733 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
737 fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
740 case DW_OP_xderef_size:
742 case DW_OP_push_object_addres:
747 _LIBUNWIND_ABORT("dwarf opcode not implemented");
752 fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
758 } // namespace libunwind
760 #endif // __DWARF_INSTRUCTIONS_HPP__