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__
20 #include "AddressSpace.hpp"
21 #include "Registers.hpp"
22 #include "DwarfParser.hpp"
32 /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
34 template <typename A
, typename R
> class DwarfInstructions
{
36 typedef typename
A::pint_t pint_t
;
37 typedef typename
A::sint_t sint_t
;
39 static step_result
stepWithDwarf(A
&, pint_t
, pint_t
, R
&, unw_proc_info_t
*);
42 static pint_t
evaluateExpression(pint_t
, A
&, const R
&, pint_t
);
44 getSavedRegister(A
&, const R
&, pint_t
,
45 const typename CFI_Parser
<A
, R
>::RegisterLocation
&);
47 computeRegisterLocation(A
&, const R
&, pint_t
,
48 const typename CFI_Parser
<A
, R
>::RegisterLocation
&);
50 static int lastRestoreReg(const R
&) { return R::LAST_RESTORE_REG
; }
52 static pint_t
getCFA(A
&addressSpace
,
53 const typename CFI_Parser
<A
, R
>::PrologInfo
&prolog
,
55 if (prolog
.cfaRegister
!= 0)
56 return registers
.getRegister(prolog
.cfaRegister
) +
57 prolog
.cfaRegisterOffset
;
58 if (prolog
.cfaExpression
!= 0)
59 return evaluateExpression(prolog
.cfaExpression
, addressSpace
, registers
,
61 assert(0 && "getCFA(): unknown location");
62 __builtin_unreachable();
66 template <typename A
, typename R
>
67 typename
A::pint_t DwarfInstructions
<A
, R
>::getSavedRegister(
68 A
&addressSpace
, const R
®isters
, pint_t cfa
,
69 const typename CFI_Parser
<A
, R
>::RegisterLocation
&savedReg
) {
70 switch (savedReg
.location
) {
71 case CFI_Parser
<A
, R
>::kRegisterInCFA
:
72 return addressSpace
.getP(cfa
+ savedReg
.value
);
74 case CFI_Parser
<A
, R
>::kRegisterAtExpression
:
75 return addressSpace
.getP(
76 evaluateExpression(savedReg
.value
, addressSpace
, registers
, cfa
));
78 case CFI_Parser
<A
, R
>::kRegisterIsExpression
:
79 return evaluateExpression(savedReg
.value
, addressSpace
, registers
, cfa
);
81 case CFI_Parser
<A
, R
>::kRegisterInRegister
:
82 return registers
.getRegister(savedReg
.value
);
84 case CFI_Parser
<A
, R
>::kRegisterUnused
:
85 case CFI_Parser
<A
, R
>::kRegisterOffsetFromCFA
:
86 assert(0 && "unsupported restore location for register");
88 __builtin_unreachable();
91 template <typename A
, typename R
>
92 typename DwarfInstructions
<A
, R
>::pint_t
93 DwarfInstructions
<A
, R
>::computeRegisterLocation(
94 A
&addressSpace
, const R
®isters
, pint_t cfa
,
95 const typename CFI_Parser
<A
, R
>::RegisterLocation
&savedReg
) {
96 switch (savedReg
.location
) {
97 case CFI_Parser
<A
, R
>::kRegisterInCFA
:
98 return cfa
+ savedReg
.value
;
100 case CFI_Parser
<A
, R
>::kRegisterAtExpression
:
101 return evaluateExpression(savedReg
.value
, addressSpace
, registers
, cfa
);
103 case CFI_Parser
<A
, R
>::kRegisterIsExpression
:
104 case CFI_Parser
<A
, R
>::kRegisterUnused
:
105 case CFI_Parser
<A
, R
>::kRegisterOffsetFromCFA
:
106 case CFI_Parser
<A
, R
>::kRegisterInRegister
:
107 assert(0 && "unsupported restore location for float/vector register");
109 __builtin_unreachable();
112 template <typename A
, typename R
>
113 step_result DwarfInstructions
<A
, R
>::stepWithDwarf(A
&addressSpace
, pint_t pc
,
116 unw_proc_info_t
*ctx
) {
117 typename CFI_Parser
<A
, R
>::FDE_Info fdeInfo
;
118 typename CFI_Parser
<A
, R
>::CIE_Info cieInfo
;
119 if (!CFI_Parser
<A
, R
>::decodeFDE(addressSpace
, fdeStart
, &fdeInfo
, &cieInfo
,
121 return UNW_STEP_FAILED
;
123 typename CFI_Parser
<A
, R
>::PrologInfo prolog
;
124 if (!CFI_Parser
<A
, R
>::parseFDEInstructions(addressSpace
, fdeInfo
, cieInfo
,
126 return UNW_STEP_FAILED
;
128 // Create working copy of the register set.
129 R newRegisters
= registers
;
131 // Get pointer to CFA by the architecture-specific code.
132 pint_t cfa
= getCFA(addressSpace
, prolog
, registers
);
134 // Restore registers according to DWARF instructions
135 pint_t returnAddress
= 0;
136 for (int i
= 0; i
<= lastRestoreReg(newRegisters
); ++i
) {
137 if (prolog
.savedRegisters
[i
].location
== CFI_Parser
<A
, R
>::kRegisterUnused
)
139 if (i
== (int)cieInfo
.returnAddressRegister
)
140 returnAddress
= getSavedRegister(addressSpace
, registers
, cfa
,
141 prolog
.savedRegisters
[i
]);
142 else if (registers
.validRegister(i
))
143 newRegisters
.setRegister(i
, getSavedRegister(addressSpace
, registers
, cfa
,
144 prolog
.savedRegisters
[i
]));
145 else if (registers
.validFloatVectorRegister(i
))
146 newRegisters
.copyFloatVectorRegister(
147 i
, computeRegisterLocation(addressSpace
, registers
, cfa
,
148 prolog
.savedRegisters
[i
]));
150 return UNW_STEP_FAILED
;
153 // The CFA is defined as the stack pointer at the call site.
154 // Therefore the SP is restored by setting it to the CFA.
155 newRegisters
.setSP(cfa
);
156 newRegisters
.setIP(returnAddress
+ R::RETURN_OFFSET
);
157 returnAddress
+= R::RETURN_OFFSET
;
158 returnAddress
&= ~R::RETURN_MASK
;
159 newRegisters
.setIP(returnAddress
);
161 // Now replace register set with the working copy.
162 registers
= newRegisters
;
164 return UNW_STEP_SUCCESS
;
167 template <typename A
, typename R
>
169 DwarfInstructions
<A
, R
>::evaluateExpression(pint_t expression
, A
&addressSpace
,
171 pint_t initialStackValue
) {
172 pint_t p
= expression
;
173 pint_t expressionEnd
= expression
+ 20; // Rough estimate
174 uint64_t length
= addressSpace
.getULEB128(p
, expressionEnd
);
175 expressionEnd
= p
+ length
;
178 *(++sp
) = initialStackValue
;
180 while (p
< expressionEnd
) {
181 uint8_t opcode
= addressSpace
.get8(p
++);
187 // push immediate address sized value
188 value
= addressSpace
.getP(p
);
194 // pop stack, dereference, push result
196 *(++sp
) = addressSpace
.getP(value
);
200 // push immediate 1 byte value
201 value
= addressSpace
.get8(p
);
207 // push immediate 1 byte signed value
208 svalue
= (int8_t)addressSpace
.get8(p
);
214 // push immediate 2 byte value
215 value
= addressSpace
.get16(p
);
221 // push immediate 2 byte signed value
222 svalue
= (int16_t)addressSpace
.get16(p
);
228 // push immediate 4 byte value
229 value
= addressSpace
.get32(p
);
235 // push immediate 4 byte signed value
236 svalue
= (int32_t)addressSpace
.get32(p
);
242 // push immediate 8 byte value
243 value
= addressSpace
.get64(p
);
249 // push immediate 8 byte signed value
250 value
= (int32_t)addressSpace
.get64(p
);
256 // push immediate ULEB128 value
257 value
= addressSpace
.getULEB128(p
, expressionEnd
);
262 // push immediate SLEB128 value
263 svalue
= addressSpace
.getSLEB128(p
, expressionEnd
);
286 reg
= addressSpace
.get8(p
);
308 // pop stack, dereference, push result
310 *sp
= *((uint64_t *)value
);
363 case DW_OP_plus_uconst
:
364 // pop stack, add uelb128 constant, push result
365 *sp
+= addressSpace
.getULEB128(p
, expressionEnd
);
381 *sp
= svalue
>> value
;
390 svalue
= (int16_t)addressSpace
.get16(p
);
396 svalue
= (int16_t)addressSpace
.get16(p
);
404 *sp
= (*sp
== value
);
409 *sp
= (*sp
>= value
);
419 *sp
= (*sp
<= value
);
429 *sp
= (*sp
!= value
);
464 value
= opcode
- DW_OP_lit0
;
500 reg
= opcode
- DW_OP_reg0
;
501 *(++sp
) = registers
.getRegister(reg
);
505 reg
= addressSpace
.getULEB128(p
, expressionEnd
);
506 *(++sp
) = registers
.getRegister(reg
);
541 reg
= opcode
- DW_OP_breg0
;
542 svalue
= addressSpace
.getSLEB128(p
, expressionEnd
);
543 *(++sp
) = registers
.getRegister(reg
) + svalue
;
547 reg
= addressSpace
.getULEB128(p
, expressionEnd
);
548 svalue
= addressSpace
.getSLEB128(p
, expressionEnd
);
549 *(++sp
) = registers
.getRegister(reg
) + svalue
;
552 case DW_OP_deref_size
:
553 // pop stack, dereference, push result
555 switch (addressSpace
.get8(p
++)) {
557 value
= addressSpace
.get8(value
);
560 value
= addressSpace
.get16(value
);
563 value
= addressSpace
.get32(value
);
566 value
= addressSpace
.get64(value
);
569 assert(0 && "DW_OP_deref_size with bad size");
576 case DW_OP_xderef_size
:
578 case DW_OP_push_object_addres
:
583 assert(0 && "dwarf opcode not implemented");
589 } // namespace _Unwind
591 #endif // __DWARF_INSTRUCTIONS_HPP__