1472758f3SLionel Sambuc //===-------------------------- DwarfInstructions.hpp ---------------------===//
2472758f3SLionel Sambuc //
3472758f3SLionel Sambuc // The LLVM Compiler Infrastructure
4472758f3SLionel Sambuc //
5472758f3SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6472758f3SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7472758f3SLionel Sambuc //
8472758f3SLionel Sambuc //
9472758f3SLionel Sambuc // Processor specific interpretation of DWARF unwind info.
10472758f3SLionel Sambuc //
11472758f3SLionel Sambuc //===----------------------------------------------------------------------===//
12472758f3SLionel Sambuc
13472758f3SLionel Sambuc #ifndef __DWARF_INSTRUCTIONS_HPP__
14472758f3SLionel Sambuc #define __DWARF_INSTRUCTIONS_HPP__
15472758f3SLionel Sambuc
16472758f3SLionel Sambuc #include <cstdint>
17472758f3SLionel Sambuc #include <cstdlib>
18472758f3SLionel Sambuc
19472758f3SLionel Sambuc #include "dwarf2.h"
20472758f3SLionel Sambuc #include "AddressSpace.hpp"
21472758f3SLionel Sambuc #include "Registers.hpp"
22472758f3SLionel Sambuc #include "DwarfParser.hpp"
23472758f3SLionel Sambuc
24472758f3SLionel Sambuc namespace _Unwind {
25472758f3SLionel Sambuc
26472758f3SLionel Sambuc enum step_result {
27472758f3SLionel Sambuc UNW_STEP_SUCCESS,
28472758f3SLionel Sambuc UNW_STEP_END,
29472758f3SLionel Sambuc UNW_STEP_FAILED
30472758f3SLionel Sambuc };
31472758f3SLionel Sambuc
32472758f3SLionel Sambuc /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
33472758f3SLionel Sambuc /// architecture
34472758f3SLionel Sambuc template <typename A, typename R> class DwarfInstructions {
35472758f3SLionel Sambuc public:
36472758f3SLionel Sambuc typedef typename A::pint_t pint_t;
37472758f3SLionel Sambuc typedef typename A::sint_t sint_t;
38472758f3SLionel Sambuc
39472758f3SLionel Sambuc static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *);
40472758f3SLionel Sambuc
41472758f3SLionel Sambuc private:
42472758f3SLionel Sambuc static pint_t evaluateExpression(pint_t, A &, const R &, pint_t);
43472758f3SLionel Sambuc static pint_t
44472758f3SLionel Sambuc getSavedRegister(A &, const R &, pint_t,
45472758f3SLionel Sambuc const typename CFI_Parser<A, R>::RegisterLocation &);
46472758f3SLionel Sambuc static pint_t
47472758f3SLionel Sambuc computeRegisterLocation(A &, const R &, pint_t,
48472758f3SLionel Sambuc const typename CFI_Parser<A, R>::RegisterLocation &);
49472758f3SLionel Sambuc
lastRestoreReg(const R &)50472758f3SLionel Sambuc static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; }
51472758f3SLionel Sambuc
getCFA(A & addressSpace,const typename CFI_Parser<A,R>::PrologInfo & prolog,const R & registers)52472758f3SLionel Sambuc static pint_t getCFA(A &addressSpace,
53472758f3SLionel Sambuc const typename CFI_Parser<A, R>::PrologInfo &prolog,
54472758f3SLionel Sambuc const R ®isters) {
55472758f3SLionel Sambuc if (prolog.cfaRegister != 0)
56472758f3SLionel Sambuc return registers.getRegister(prolog.cfaRegister) +
57472758f3SLionel Sambuc prolog.cfaRegisterOffset;
58472758f3SLionel Sambuc if (prolog.cfaExpression != 0)
59472758f3SLionel Sambuc return evaluateExpression(prolog.cfaExpression, addressSpace, registers,
60472758f3SLionel Sambuc 0);
61472758f3SLionel Sambuc assert(0 && "getCFA(): unknown location");
62472758f3SLionel Sambuc __builtin_unreachable();
63472758f3SLionel Sambuc }
64472758f3SLionel Sambuc };
65472758f3SLionel Sambuc
66472758f3SLionel Sambuc template <typename A, typename R>
getSavedRegister(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)67472758f3SLionel Sambuc typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
68472758f3SLionel Sambuc A &addressSpace, const R ®isters, pint_t cfa,
69472758f3SLionel Sambuc const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
70472758f3SLionel Sambuc switch (savedReg.location) {
71472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterInCFA:
72472758f3SLionel Sambuc return addressSpace.getP(cfa + savedReg.value);
73472758f3SLionel Sambuc
74472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterAtExpression:
75472758f3SLionel Sambuc return addressSpace.getP(
76472758f3SLionel Sambuc evaluateExpression(savedReg.value, addressSpace, registers, cfa));
77472758f3SLionel Sambuc
78472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterIsExpression:
79472758f3SLionel Sambuc return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
80472758f3SLionel Sambuc
81472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterInRegister:
82472758f3SLionel Sambuc return registers.getRegister(savedReg.value);
83472758f3SLionel Sambuc
84472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterUnused:
85472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
86472758f3SLionel Sambuc assert(0 && "unsupported restore location for register");
87472758f3SLionel Sambuc }
88472758f3SLionel Sambuc __builtin_unreachable();
89472758f3SLionel Sambuc }
90472758f3SLionel Sambuc
91472758f3SLionel Sambuc template <typename A, typename R>
92472758f3SLionel Sambuc typename DwarfInstructions<A, R>::pint_t
computeRegisterLocation(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)93472758f3SLionel Sambuc DwarfInstructions<A, R>::computeRegisterLocation(
94472758f3SLionel Sambuc A &addressSpace, const R ®isters, pint_t cfa,
95472758f3SLionel Sambuc const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
96472758f3SLionel Sambuc switch (savedReg.location) {
97472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterInCFA:
98472758f3SLionel Sambuc return cfa + savedReg.value;
99472758f3SLionel Sambuc
100472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterAtExpression:
101472758f3SLionel Sambuc return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
102472758f3SLionel Sambuc
103472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterIsExpression:
104472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterUnused:
105472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
106472758f3SLionel Sambuc case CFI_Parser<A, R>::kRegisterInRegister:
107472758f3SLionel Sambuc assert(0 && "unsupported restore location for float/vector register");
108472758f3SLionel Sambuc }
109472758f3SLionel Sambuc __builtin_unreachable();
110472758f3SLionel Sambuc }
111472758f3SLionel Sambuc
112472758f3SLionel Sambuc template <typename A, typename R>
stepWithDwarf(A & addressSpace,pint_t pc,pint_t fdeStart,R & registers,unw_proc_info_t * ctx)113472758f3SLionel Sambuc step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
114472758f3SLionel Sambuc pint_t fdeStart,
115472758f3SLionel Sambuc R ®isters,
116472758f3SLionel Sambuc unw_proc_info_t *ctx) {
117472758f3SLionel Sambuc typename CFI_Parser<A, R>::FDE_Info fdeInfo;
118472758f3SLionel Sambuc typename CFI_Parser<A, R>::CIE_Info cieInfo;
119472758f3SLionel Sambuc if (!CFI_Parser<A, R>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo,
120472758f3SLionel Sambuc ctx))
121472758f3SLionel Sambuc return UNW_STEP_FAILED;
122472758f3SLionel Sambuc
123472758f3SLionel Sambuc typename CFI_Parser<A, R>::PrologInfo prolog;
124472758f3SLionel Sambuc if (!CFI_Parser<A, R>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo,
125472758f3SLionel Sambuc pc, &prolog, ctx))
126472758f3SLionel Sambuc return UNW_STEP_FAILED;
127472758f3SLionel Sambuc
128472758f3SLionel Sambuc // Create working copy of the register set.
129472758f3SLionel Sambuc R newRegisters = registers;
130472758f3SLionel Sambuc
131472758f3SLionel Sambuc // Get pointer to CFA by the architecture-specific code.
132472758f3SLionel Sambuc pint_t cfa = getCFA(addressSpace, prolog, registers);
133472758f3SLionel Sambuc
134472758f3SLionel Sambuc // Restore registers according to DWARF instructions
135472758f3SLionel Sambuc pint_t returnAddress = 0;
136472758f3SLionel Sambuc for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
137472758f3SLionel Sambuc if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused)
138472758f3SLionel Sambuc continue;
139b029fb59SBen Gras if (i == (int)cieInfo.returnAddressRegister)
140472758f3SLionel Sambuc returnAddress = getSavedRegister(addressSpace, registers, cfa,
141472758f3SLionel Sambuc prolog.savedRegisters[i]);
142472758f3SLionel Sambuc else if (registers.validRegister(i))
143472758f3SLionel Sambuc newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa,
144472758f3SLionel Sambuc prolog.savedRegisters[i]));
145472758f3SLionel Sambuc else if (registers.validFloatVectorRegister(i))
146472758f3SLionel Sambuc newRegisters.copyFloatVectorRegister(
147472758f3SLionel Sambuc i, computeRegisterLocation(addressSpace, registers, cfa,
148472758f3SLionel Sambuc prolog.savedRegisters[i]));
149472758f3SLionel Sambuc else
150472758f3SLionel Sambuc return UNW_STEP_FAILED;
151472758f3SLionel Sambuc }
152472758f3SLionel Sambuc
153472758f3SLionel Sambuc // The CFA is defined as the stack pointer at the call site.
154472758f3SLionel Sambuc // Therefore the SP is restored by setting it to the CFA.
155472758f3SLionel Sambuc newRegisters.setSP(cfa);
156b029fb59SBen Gras newRegisters.setIP(returnAddress + R::RETURN_OFFSET);
157*0a6a1f1dSLionel Sambuc returnAddress += R::RETURN_OFFSET;
158*0a6a1f1dSLionel Sambuc returnAddress &= ~R::RETURN_MASK;
159*0a6a1f1dSLionel Sambuc newRegisters.setIP(returnAddress);
160472758f3SLionel Sambuc
161472758f3SLionel Sambuc // Now replace register set with the working copy.
162472758f3SLionel Sambuc registers = newRegisters;
163472758f3SLionel Sambuc
164472758f3SLionel Sambuc return UNW_STEP_SUCCESS;
165472758f3SLionel Sambuc }
166472758f3SLionel Sambuc
167472758f3SLionel Sambuc template <typename A, typename R>
168472758f3SLionel Sambuc typename A::pint_t
evaluateExpression(pint_t expression,A & addressSpace,const R & registers,pint_t initialStackValue)169472758f3SLionel Sambuc DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
170472758f3SLionel Sambuc const R ®isters,
171472758f3SLionel Sambuc pint_t initialStackValue) {
172472758f3SLionel Sambuc pint_t p = expression;
173472758f3SLionel Sambuc pint_t expressionEnd = expression + 20; // Rough estimate
174472758f3SLionel Sambuc uint64_t length = addressSpace.getULEB128(p, expressionEnd);
175472758f3SLionel Sambuc expressionEnd = p + length;
176472758f3SLionel Sambuc pint_t stack[100];
177472758f3SLionel Sambuc pint_t *sp = stack;
178472758f3SLionel Sambuc *(++sp) = initialStackValue;
179472758f3SLionel Sambuc
180472758f3SLionel Sambuc while (p < expressionEnd) {
181472758f3SLionel Sambuc uint8_t opcode = addressSpace.get8(p++);
182472758f3SLionel Sambuc sint_t svalue;
183472758f3SLionel Sambuc pint_t value;
184472758f3SLionel Sambuc uint32_t reg;
185472758f3SLionel Sambuc switch (opcode) {
186472758f3SLionel Sambuc case DW_OP_addr:
187472758f3SLionel Sambuc // push immediate address sized value
188472758f3SLionel Sambuc value = addressSpace.getP(p);
189472758f3SLionel Sambuc p += sizeof(pint_t);
190472758f3SLionel Sambuc *(++sp) = value;
191472758f3SLionel Sambuc break;
192472758f3SLionel Sambuc
193472758f3SLionel Sambuc case DW_OP_deref:
194472758f3SLionel Sambuc // pop stack, dereference, push result
195472758f3SLionel Sambuc value = *sp--;
196472758f3SLionel Sambuc *(++sp) = addressSpace.getP(value);
197472758f3SLionel Sambuc break;
198472758f3SLionel Sambuc
199472758f3SLionel Sambuc case DW_OP_const1u:
200472758f3SLionel Sambuc // push immediate 1 byte value
201472758f3SLionel Sambuc value = addressSpace.get8(p);
202472758f3SLionel Sambuc p += 1;
203472758f3SLionel Sambuc *(++sp) = value;
204472758f3SLionel Sambuc break;
205472758f3SLionel Sambuc
206472758f3SLionel Sambuc case DW_OP_const1s:
207472758f3SLionel Sambuc // push immediate 1 byte signed value
208472758f3SLionel Sambuc svalue = (int8_t)addressSpace.get8(p);
209472758f3SLionel Sambuc p += 1;
210472758f3SLionel Sambuc *(++sp) = svalue;
211472758f3SLionel Sambuc break;
212472758f3SLionel Sambuc
213472758f3SLionel Sambuc case DW_OP_const2u:
214472758f3SLionel Sambuc // push immediate 2 byte value
215472758f3SLionel Sambuc value = addressSpace.get16(p);
216472758f3SLionel Sambuc p += 2;
217472758f3SLionel Sambuc *(++sp) = value;
218472758f3SLionel Sambuc break;
219472758f3SLionel Sambuc
220472758f3SLionel Sambuc case DW_OP_const2s:
221472758f3SLionel Sambuc // push immediate 2 byte signed value
222472758f3SLionel Sambuc svalue = (int16_t)addressSpace.get16(p);
223472758f3SLionel Sambuc p += 2;
224472758f3SLionel Sambuc *(++sp) = svalue;
225472758f3SLionel Sambuc break;
226472758f3SLionel Sambuc
227472758f3SLionel Sambuc case DW_OP_const4u:
228472758f3SLionel Sambuc // push immediate 4 byte value
229472758f3SLionel Sambuc value = addressSpace.get32(p);
230472758f3SLionel Sambuc p += 4;
231472758f3SLionel Sambuc *(++sp) = value;
232472758f3SLionel Sambuc break;
233472758f3SLionel Sambuc
234472758f3SLionel Sambuc case DW_OP_const4s:
235472758f3SLionel Sambuc // push immediate 4 byte signed value
236472758f3SLionel Sambuc svalue = (int32_t)addressSpace.get32(p);
237472758f3SLionel Sambuc p += 4;
238472758f3SLionel Sambuc *(++sp) = svalue;
239472758f3SLionel Sambuc break;
240472758f3SLionel Sambuc
241472758f3SLionel Sambuc case DW_OP_const8u:
242472758f3SLionel Sambuc // push immediate 8 byte value
243472758f3SLionel Sambuc value = addressSpace.get64(p);
244472758f3SLionel Sambuc p += 8;
245472758f3SLionel Sambuc *(++sp) = value;
246472758f3SLionel Sambuc break;
247472758f3SLionel Sambuc
248472758f3SLionel Sambuc case DW_OP_const8s:
249472758f3SLionel Sambuc // push immediate 8 byte signed value
250472758f3SLionel Sambuc value = (int32_t)addressSpace.get64(p);
251472758f3SLionel Sambuc p += 8;
252472758f3SLionel Sambuc *(++sp) = value;
253472758f3SLionel Sambuc break;
254472758f3SLionel Sambuc
255472758f3SLionel Sambuc case DW_OP_constu:
256472758f3SLionel Sambuc // push immediate ULEB128 value
257472758f3SLionel Sambuc value = addressSpace.getULEB128(p, expressionEnd);
258472758f3SLionel Sambuc *(++sp) = value;
259472758f3SLionel Sambuc break;
260472758f3SLionel Sambuc
261472758f3SLionel Sambuc case DW_OP_consts:
262472758f3SLionel Sambuc // push immediate SLEB128 value
263472758f3SLionel Sambuc svalue = addressSpace.getSLEB128(p, expressionEnd);
264472758f3SLionel Sambuc *(++sp) = svalue;
265472758f3SLionel Sambuc break;
266472758f3SLionel Sambuc
267472758f3SLionel Sambuc case DW_OP_dup:
268472758f3SLionel Sambuc // push top of stack
269472758f3SLionel Sambuc value = *sp;
270472758f3SLionel Sambuc *(++sp) = value;
271472758f3SLionel Sambuc break;
272472758f3SLionel Sambuc
273472758f3SLionel Sambuc case DW_OP_drop:
274472758f3SLionel Sambuc // pop
275472758f3SLionel Sambuc --sp;
276472758f3SLionel Sambuc break;
277472758f3SLionel Sambuc
278472758f3SLionel Sambuc case DW_OP_over:
279472758f3SLionel Sambuc // dup second
280472758f3SLionel Sambuc value = sp[-1];
281472758f3SLionel Sambuc *(++sp) = value;
282472758f3SLionel Sambuc break;
283472758f3SLionel Sambuc
284472758f3SLionel Sambuc case DW_OP_pick:
285472758f3SLionel Sambuc // pick from
286472758f3SLionel Sambuc reg = addressSpace.get8(p);
287472758f3SLionel Sambuc p += 1;
288472758f3SLionel Sambuc value = sp[-reg];
289472758f3SLionel Sambuc *(++sp) = value;
290472758f3SLionel Sambuc break;
291472758f3SLionel Sambuc
292472758f3SLionel Sambuc case DW_OP_swap:
293472758f3SLionel Sambuc // swap top two
294472758f3SLionel Sambuc value = sp[0];
295472758f3SLionel Sambuc sp[0] = sp[-1];
296472758f3SLionel Sambuc sp[-1] = value;
297472758f3SLionel Sambuc break;
298472758f3SLionel Sambuc
299472758f3SLionel Sambuc case DW_OP_rot:
300472758f3SLionel Sambuc // rotate top three
301472758f3SLionel Sambuc value = sp[0];
302472758f3SLionel Sambuc sp[0] = sp[-1];
303472758f3SLionel Sambuc sp[-1] = sp[-2];
304472758f3SLionel Sambuc sp[-2] = value;
305472758f3SLionel Sambuc break;
306472758f3SLionel Sambuc
307472758f3SLionel Sambuc case DW_OP_xderef:
308472758f3SLionel Sambuc // pop stack, dereference, push result
309472758f3SLionel Sambuc value = *sp--;
310472758f3SLionel Sambuc *sp = *((uint64_t *)value);
311472758f3SLionel Sambuc break;
312472758f3SLionel Sambuc
313472758f3SLionel Sambuc case DW_OP_abs:
314472758f3SLionel Sambuc svalue = *sp;
315472758f3SLionel Sambuc if (svalue < 0)
316472758f3SLionel Sambuc *sp = -svalue;
317472758f3SLionel Sambuc break;
318472758f3SLionel Sambuc
319472758f3SLionel Sambuc case DW_OP_and:
320472758f3SLionel Sambuc value = *sp--;
321472758f3SLionel Sambuc *sp &= value;
322472758f3SLionel Sambuc break;
323472758f3SLionel Sambuc
324472758f3SLionel Sambuc case DW_OP_div:
325472758f3SLionel Sambuc svalue = *sp--;
326472758f3SLionel Sambuc *sp = *sp / svalue;
327472758f3SLionel Sambuc break;
328472758f3SLionel Sambuc
329472758f3SLionel Sambuc case DW_OP_minus:
330472758f3SLionel Sambuc svalue = *sp--;
331472758f3SLionel Sambuc *sp = *sp - svalue;
332472758f3SLionel Sambuc break;
333472758f3SLionel Sambuc
334472758f3SLionel Sambuc case DW_OP_mod:
335472758f3SLionel Sambuc svalue = *sp--;
336472758f3SLionel Sambuc *sp = *sp % svalue;
337472758f3SLionel Sambuc break;
338472758f3SLionel Sambuc
339472758f3SLionel Sambuc case DW_OP_mul:
340472758f3SLionel Sambuc svalue = *sp--;
341472758f3SLionel Sambuc *sp = *sp * svalue;
342472758f3SLionel Sambuc break;
343472758f3SLionel Sambuc
344472758f3SLionel Sambuc case DW_OP_neg:
345472758f3SLionel Sambuc *sp = 0 - *sp;
346472758f3SLionel Sambuc break;
347472758f3SLionel Sambuc
348472758f3SLionel Sambuc case DW_OP_not:
349472758f3SLionel Sambuc svalue = *sp;
350472758f3SLionel Sambuc *sp = ~svalue;
351472758f3SLionel Sambuc break;
352472758f3SLionel Sambuc
353472758f3SLionel Sambuc case DW_OP_or:
354472758f3SLionel Sambuc value = *sp--;
355472758f3SLionel Sambuc *sp |= value;
356472758f3SLionel Sambuc break;
357472758f3SLionel Sambuc
358472758f3SLionel Sambuc case DW_OP_plus:
359472758f3SLionel Sambuc value = *sp--;
360472758f3SLionel Sambuc *sp += value;
361472758f3SLionel Sambuc break;
362472758f3SLionel Sambuc
363472758f3SLionel Sambuc case DW_OP_plus_uconst:
364472758f3SLionel Sambuc // pop stack, add uelb128 constant, push result
365472758f3SLionel Sambuc *sp += addressSpace.getULEB128(p, expressionEnd);
366472758f3SLionel Sambuc break;
367472758f3SLionel Sambuc
368472758f3SLionel Sambuc case DW_OP_shl:
369472758f3SLionel Sambuc value = *sp--;
370472758f3SLionel Sambuc *sp = *sp << value;
371472758f3SLionel Sambuc break;
372472758f3SLionel Sambuc
373472758f3SLionel Sambuc case DW_OP_shr:
374472758f3SLionel Sambuc value = *sp--;
375472758f3SLionel Sambuc *sp = *sp >> value;
376472758f3SLionel Sambuc break;
377472758f3SLionel Sambuc
378472758f3SLionel Sambuc case DW_OP_shra:
379472758f3SLionel Sambuc value = *sp--;
380472758f3SLionel Sambuc svalue = *sp;
381472758f3SLionel Sambuc *sp = svalue >> value;
382472758f3SLionel Sambuc break;
383472758f3SLionel Sambuc
384472758f3SLionel Sambuc case DW_OP_xor:
385472758f3SLionel Sambuc value = *sp--;
386472758f3SLionel Sambuc *sp ^= value;
387472758f3SLionel Sambuc break;
388472758f3SLionel Sambuc
389472758f3SLionel Sambuc case DW_OP_skip:
390472758f3SLionel Sambuc svalue = (int16_t)addressSpace.get16(p);
391472758f3SLionel Sambuc p += 2;
392472758f3SLionel Sambuc p += svalue;
393472758f3SLionel Sambuc break;
394472758f3SLionel Sambuc
395472758f3SLionel Sambuc case DW_OP_bra:
396472758f3SLionel Sambuc svalue = (int16_t)addressSpace.get16(p);
397472758f3SLionel Sambuc p += 2;
398472758f3SLionel Sambuc if (*sp--)
399472758f3SLionel Sambuc p += svalue;
400472758f3SLionel Sambuc break;
401472758f3SLionel Sambuc
402472758f3SLionel Sambuc case DW_OP_eq:
403472758f3SLionel Sambuc value = *sp--;
404472758f3SLionel Sambuc *sp = (*sp == value);
405472758f3SLionel Sambuc break;
406472758f3SLionel Sambuc
407472758f3SLionel Sambuc case DW_OP_ge:
408472758f3SLionel Sambuc value = *sp--;
409472758f3SLionel Sambuc *sp = (*sp >= value);
410472758f3SLionel Sambuc break;
411472758f3SLionel Sambuc
412472758f3SLionel Sambuc case DW_OP_gt:
413472758f3SLionel Sambuc value = *sp--;
414472758f3SLionel Sambuc *sp = (*sp > value);
415472758f3SLionel Sambuc break;
416472758f3SLionel Sambuc
417472758f3SLionel Sambuc case DW_OP_le:
418472758f3SLionel Sambuc value = *sp--;
419472758f3SLionel Sambuc *sp = (*sp <= value);
420472758f3SLionel Sambuc break;
421472758f3SLionel Sambuc
422472758f3SLionel Sambuc case DW_OP_lt:
423472758f3SLionel Sambuc value = *sp--;
424472758f3SLionel Sambuc *sp = (*sp < value);
425472758f3SLionel Sambuc break;
426472758f3SLionel Sambuc
427472758f3SLionel Sambuc case DW_OP_ne:
428472758f3SLionel Sambuc value = *sp--;
429472758f3SLionel Sambuc *sp = (*sp != value);
430472758f3SLionel Sambuc break;
431472758f3SLionel Sambuc
432472758f3SLionel Sambuc case DW_OP_lit0:
433472758f3SLionel Sambuc case DW_OP_lit1:
434472758f3SLionel Sambuc case DW_OP_lit2:
435472758f3SLionel Sambuc case DW_OP_lit3:
436472758f3SLionel Sambuc case DW_OP_lit4:
437472758f3SLionel Sambuc case DW_OP_lit5:
438472758f3SLionel Sambuc case DW_OP_lit6:
439472758f3SLionel Sambuc case DW_OP_lit7:
440472758f3SLionel Sambuc case DW_OP_lit8:
441472758f3SLionel Sambuc case DW_OP_lit9:
442472758f3SLionel Sambuc case DW_OP_lit10:
443472758f3SLionel Sambuc case DW_OP_lit11:
444472758f3SLionel Sambuc case DW_OP_lit12:
445472758f3SLionel Sambuc case DW_OP_lit13:
446472758f3SLionel Sambuc case DW_OP_lit14:
447472758f3SLionel Sambuc case DW_OP_lit15:
448472758f3SLionel Sambuc case DW_OP_lit16:
449472758f3SLionel Sambuc case DW_OP_lit17:
450472758f3SLionel Sambuc case DW_OP_lit18:
451472758f3SLionel Sambuc case DW_OP_lit19:
452472758f3SLionel Sambuc case DW_OP_lit20:
453472758f3SLionel Sambuc case DW_OP_lit21:
454472758f3SLionel Sambuc case DW_OP_lit22:
455472758f3SLionel Sambuc case DW_OP_lit23:
456472758f3SLionel Sambuc case DW_OP_lit24:
457472758f3SLionel Sambuc case DW_OP_lit25:
458472758f3SLionel Sambuc case DW_OP_lit26:
459472758f3SLionel Sambuc case DW_OP_lit27:
460472758f3SLionel Sambuc case DW_OP_lit28:
461472758f3SLionel Sambuc case DW_OP_lit29:
462472758f3SLionel Sambuc case DW_OP_lit30:
463472758f3SLionel Sambuc case DW_OP_lit31:
464472758f3SLionel Sambuc value = opcode - DW_OP_lit0;
465472758f3SLionel Sambuc *(++sp) = value;
466472758f3SLionel Sambuc break;
467472758f3SLionel Sambuc
468472758f3SLionel Sambuc case DW_OP_reg0:
469472758f3SLionel Sambuc case DW_OP_reg1:
470472758f3SLionel Sambuc case DW_OP_reg2:
471472758f3SLionel Sambuc case DW_OP_reg3:
472472758f3SLionel Sambuc case DW_OP_reg4:
473472758f3SLionel Sambuc case DW_OP_reg5:
474472758f3SLionel Sambuc case DW_OP_reg6:
475472758f3SLionel Sambuc case DW_OP_reg7:
476472758f3SLionel Sambuc case DW_OP_reg8:
477472758f3SLionel Sambuc case DW_OP_reg9:
478472758f3SLionel Sambuc case DW_OP_reg10:
479472758f3SLionel Sambuc case DW_OP_reg11:
480472758f3SLionel Sambuc case DW_OP_reg12:
481472758f3SLionel Sambuc case DW_OP_reg13:
482472758f3SLionel Sambuc case DW_OP_reg14:
483472758f3SLionel Sambuc case DW_OP_reg15:
484472758f3SLionel Sambuc case DW_OP_reg16:
485472758f3SLionel Sambuc case DW_OP_reg17:
486472758f3SLionel Sambuc case DW_OP_reg18:
487472758f3SLionel Sambuc case DW_OP_reg19:
488472758f3SLionel Sambuc case DW_OP_reg20:
489472758f3SLionel Sambuc case DW_OP_reg21:
490472758f3SLionel Sambuc case DW_OP_reg22:
491472758f3SLionel Sambuc case DW_OP_reg23:
492472758f3SLionel Sambuc case DW_OP_reg24:
493472758f3SLionel Sambuc case DW_OP_reg25:
494472758f3SLionel Sambuc case DW_OP_reg26:
495472758f3SLionel Sambuc case DW_OP_reg27:
496472758f3SLionel Sambuc case DW_OP_reg28:
497472758f3SLionel Sambuc case DW_OP_reg29:
498472758f3SLionel Sambuc case DW_OP_reg30:
499472758f3SLionel Sambuc case DW_OP_reg31:
500472758f3SLionel Sambuc reg = opcode - DW_OP_reg0;
501472758f3SLionel Sambuc *(++sp) = registers.getRegister(reg);
502472758f3SLionel Sambuc break;
503472758f3SLionel Sambuc
504472758f3SLionel Sambuc case DW_OP_regx:
505472758f3SLionel Sambuc reg = addressSpace.getULEB128(p, expressionEnd);
506472758f3SLionel Sambuc *(++sp) = registers.getRegister(reg);
507472758f3SLionel Sambuc break;
508472758f3SLionel Sambuc
509472758f3SLionel Sambuc case DW_OP_breg0:
510472758f3SLionel Sambuc case DW_OP_breg1:
511472758f3SLionel Sambuc case DW_OP_breg2:
512472758f3SLionel Sambuc case DW_OP_breg3:
513472758f3SLionel Sambuc case DW_OP_breg4:
514472758f3SLionel Sambuc case DW_OP_breg5:
515472758f3SLionel Sambuc case DW_OP_breg6:
516472758f3SLionel Sambuc case DW_OP_breg7:
517472758f3SLionel Sambuc case DW_OP_breg8:
518472758f3SLionel Sambuc case DW_OP_breg9:
519472758f3SLionel Sambuc case DW_OP_breg10:
520472758f3SLionel Sambuc case DW_OP_breg11:
521472758f3SLionel Sambuc case DW_OP_breg12:
522472758f3SLionel Sambuc case DW_OP_breg13:
523472758f3SLionel Sambuc case DW_OP_breg14:
524472758f3SLionel Sambuc case DW_OP_breg15:
525472758f3SLionel Sambuc case DW_OP_breg16:
526472758f3SLionel Sambuc case DW_OP_breg17:
527472758f3SLionel Sambuc case DW_OP_breg18:
528472758f3SLionel Sambuc case DW_OP_breg19:
529472758f3SLionel Sambuc case DW_OP_breg20:
530472758f3SLionel Sambuc case DW_OP_breg21:
531472758f3SLionel Sambuc case DW_OP_breg22:
532472758f3SLionel Sambuc case DW_OP_breg23:
533472758f3SLionel Sambuc case DW_OP_breg24:
534472758f3SLionel Sambuc case DW_OP_breg25:
535472758f3SLionel Sambuc case DW_OP_breg26:
536472758f3SLionel Sambuc case DW_OP_breg27:
537472758f3SLionel Sambuc case DW_OP_breg28:
538472758f3SLionel Sambuc case DW_OP_breg29:
539472758f3SLionel Sambuc case DW_OP_breg30:
540472758f3SLionel Sambuc case DW_OP_breg31:
541472758f3SLionel Sambuc reg = opcode - DW_OP_breg0;
542472758f3SLionel Sambuc svalue = addressSpace.getSLEB128(p, expressionEnd);
543472758f3SLionel Sambuc *(++sp) = registers.getRegister(reg) + svalue;
544472758f3SLionel Sambuc break;
545472758f3SLionel Sambuc
546472758f3SLionel Sambuc case DW_OP_bregx:
547472758f3SLionel Sambuc reg = addressSpace.getULEB128(p, expressionEnd);
548472758f3SLionel Sambuc svalue = addressSpace.getSLEB128(p, expressionEnd);
549472758f3SLionel Sambuc *(++sp) = registers.getRegister(reg) + svalue;
550472758f3SLionel Sambuc break;
551472758f3SLionel Sambuc
552472758f3SLionel Sambuc case DW_OP_deref_size:
553472758f3SLionel Sambuc // pop stack, dereference, push result
554472758f3SLionel Sambuc value = *sp--;
555472758f3SLionel Sambuc switch (addressSpace.get8(p++)) {
556472758f3SLionel Sambuc case 1:
557472758f3SLionel Sambuc value = addressSpace.get8(value);
558472758f3SLionel Sambuc break;
559472758f3SLionel Sambuc case 2:
560472758f3SLionel Sambuc value = addressSpace.get16(value);
561472758f3SLionel Sambuc break;
562472758f3SLionel Sambuc case 4:
563472758f3SLionel Sambuc value = addressSpace.get32(value);
564472758f3SLionel Sambuc break;
565472758f3SLionel Sambuc case 8:
566472758f3SLionel Sambuc value = addressSpace.get64(value);
567472758f3SLionel Sambuc break;
568472758f3SLionel Sambuc default:
569472758f3SLionel Sambuc assert(0 && "DW_OP_deref_size with bad size");
570472758f3SLionel Sambuc }
571472758f3SLionel Sambuc *(++sp) = value;
572472758f3SLionel Sambuc break;
573472758f3SLionel Sambuc
574472758f3SLionel Sambuc case DW_OP_fbreg:
575472758f3SLionel Sambuc case DW_OP_piece:
576472758f3SLionel Sambuc case DW_OP_xderef_size:
577472758f3SLionel Sambuc case DW_OP_nop:
578472758f3SLionel Sambuc case DW_OP_push_object_addres:
579472758f3SLionel Sambuc case DW_OP_call2:
580472758f3SLionel Sambuc case DW_OP_call4:
581472758f3SLionel Sambuc case DW_OP_call_ref:
582472758f3SLionel Sambuc default:
583472758f3SLionel Sambuc assert(0 && "dwarf opcode not implemented");
584472758f3SLionel Sambuc }
585472758f3SLionel Sambuc }
586472758f3SLionel Sambuc return *sp;
587472758f3SLionel Sambuc }
588472758f3SLionel Sambuc
589472758f3SLionel Sambuc } // namespace _Unwind
590472758f3SLionel Sambuc
591472758f3SLionel Sambuc #endif // __DWARF_INSTRUCTIONS_HPP__
592