1aa0b96d0Sjoerg //===-------------------------- DwarfInstructions.hpp ---------------------===//
2aa0b96d0Sjoerg //
3aa0b96d0Sjoerg // The LLVM Compiler Infrastructure
4aa0b96d0Sjoerg //
5aa0b96d0Sjoerg // This file is dual licensed under the MIT and the University of Illinois Open
6aa0b96d0Sjoerg // Source Licenses. See LICENSE.TXT for details.
7aa0b96d0Sjoerg //
8aa0b96d0Sjoerg //
9aa0b96d0Sjoerg // Processor specific interpretation of DWARF unwind info.
10aa0b96d0Sjoerg //
11aa0b96d0Sjoerg //===----------------------------------------------------------------------===//
12aa0b96d0Sjoerg
13aa0b96d0Sjoerg #ifndef __DWARF_INSTRUCTIONS_HPP__
14aa0b96d0Sjoerg #define __DWARF_INSTRUCTIONS_HPP__
15aa0b96d0Sjoerg
16aa0b96d0Sjoerg #include <cstdint>
17aa0b96d0Sjoerg #include <cstdlib>
18aa0b96d0Sjoerg
19aa0b96d0Sjoerg #include "dwarf2.h"
20aa0b96d0Sjoerg #include "AddressSpace.hpp"
21aa0b96d0Sjoerg #include "Registers.hpp"
22aa0b96d0Sjoerg #include "DwarfParser.hpp"
23aa0b96d0Sjoerg
24aa0b96d0Sjoerg namespace _Unwind {
25aa0b96d0Sjoerg
26aa0b96d0Sjoerg enum step_result {
27aa0b96d0Sjoerg UNW_STEP_SUCCESS,
28aa0b96d0Sjoerg UNW_STEP_END,
29aa0b96d0Sjoerg UNW_STEP_FAILED
30aa0b96d0Sjoerg };
31aa0b96d0Sjoerg
32aa0b96d0Sjoerg /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
33aa0b96d0Sjoerg /// architecture
34aa0b96d0Sjoerg template <typename A, typename R> class DwarfInstructions {
35aa0b96d0Sjoerg public:
36aa0b96d0Sjoerg typedef typename A::pint_t pint_t;
37aa0b96d0Sjoerg typedef typename A::sint_t sint_t;
38aa0b96d0Sjoerg
39aa0b96d0Sjoerg static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *);
40aa0b96d0Sjoerg
41aa0b96d0Sjoerg private:
42aa0b96d0Sjoerg static pint_t evaluateExpression(pint_t, A &, const R &, pint_t);
43aa0b96d0Sjoerg static pint_t
44aa0b96d0Sjoerg getSavedRegister(A &, const R &, pint_t,
45aa0b96d0Sjoerg const typename CFI_Parser<A, R>::RegisterLocation &);
46aa0b96d0Sjoerg static pint_t
47aa0b96d0Sjoerg computeRegisterLocation(A &, const R &, pint_t,
48aa0b96d0Sjoerg const typename CFI_Parser<A, R>::RegisterLocation &);
49aa0b96d0Sjoerg
lastRestoreReg(const R &)50aa0b96d0Sjoerg static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; }
51aa0b96d0Sjoerg
getCFA(A & addressSpace,const typename CFI_Parser<A,R>::PrologInfo & prolog,const R & registers)52aa0b96d0Sjoerg static pint_t getCFA(A &addressSpace,
53aa0b96d0Sjoerg const typename CFI_Parser<A, R>::PrologInfo &prolog,
54aa0b96d0Sjoerg const R ®isters) {
55aa0b96d0Sjoerg if (prolog.cfaRegister != 0)
56aa0b96d0Sjoerg return registers.getRegister(prolog.cfaRegister) +
57aa0b96d0Sjoerg prolog.cfaRegisterOffset;
58aa0b96d0Sjoerg if (prolog.cfaExpression != 0)
59aa0b96d0Sjoerg return evaluateExpression(prolog.cfaExpression, addressSpace, registers,
60aa0b96d0Sjoerg 0);
61aa0b96d0Sjoerg assert(0 && "getCFA(): unknown location");
62aa0b96d0Sjoerg __builtin_unreachable();
63aa0b96d0Sjoerg }
64aa0b96d0Sjoerg };
65aa0b96d0Sjoerg
66aa0b96d0Sjoerg template <typename A, typename R>
getSavedRegister(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)67aa0b96d0Sjoerg typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
68aa0b96d0Sjoerg A &addressSpace, const R ®isters, pint_t cfa,
69aa0b96d0Sjoerg const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
70aa0b96d0Sjoerg switch (savedReg.location) {
71aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterInCFA:
72aa0b96d0Sjoerg return addressSpace.getP(cfa + savedReg.value);
73aa0b96d0Sjoerg
74aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterAtExpression:
75aa0b96d0Sjoerg return addressSpace.getP(
76aa0b96d0Sjoerg evaluateExpression(savedReg.value, addressSpace, registers, cfa));
77aa0b96d0Sjoerg
78aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterIsExpression:
79aa0b96d0Sjoerg return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
80aa0b96d0Sjoerg
81aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterInRegister:
82aa0b96d0Sjoerg return registers.getRegister(savedReg.value);
83aa0b96d0Sjoerg
84aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterUnused:
85aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
86aa0b96d0Sjoerg assert(0 && "unsupported restore location for register");
87aa0b96d0Sjoerg }
88aa0b96d0Sjoerg __builtin_unreachable();
89aa0b96d0Sjoerg }
90aa0b96d0Sjoerg
91aa0b96d0Sjoerg template <typename A, typename R>
92aa0b96d0Sjoerg typename DwarfInstructions<A, R>::pint_t
computeRegisterLocation(A & addressSpace,const R & registers,pint_t cfa,const typename CFI_Parser<A,R>::RegisterLocation & savedReg)93aa0b96d0Sjoerg DwarfInstructions<A, R>::computeRegisterLocation(
94aa0b96d0Sjoerg A &addressSpace, const R ®isters, pint_t cfa,
95aa0b96d0Sjoerg const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
96aa0b96d0Sjoerg switch (savedReg.location) {
97aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterInCFA:
98aa0b96d0Sjoerg return cfa + savedReg.value;
99aa0b96d0Sjoerg
100aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterAtExpression:
101aa0b96d0Sjoerg return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
102aa0b96d0Sjoerg
103aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterIsExpression:
104aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterUnused:
105aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
106aa0b96d0Sjoerg case CFI_Parser<A, R>::kRegisterInRegister:
107aa0b96d0Sjoerg assert(0 && "unsupported restore location for float/vector register");
108aa0b96d0Sjoerg }
109aa0b96d0Sjoerg __builtin_unreachable();
110aa0b96d0Sjoerg }
111aa0b96d0Sjoerg
112aa0b96d0Sjoerg template <typename A, typename R>
stepWithDwarf(A & addressSpace,pint_t pc,pint_t fdeStart,R & registers,unw_proc_info_t * ctx)113aa0b96d0Sjoerg step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
114aa0b96d0Sjoerg pint_t fdeStart,
115aa0b96d0Sjoerg R ®isters,
116aa0b96d0Sjoerg unw_proc_info_t *ctx) {
117aa0b96d0Sjoerg typename CFI_Parser<A, R>::FDE_Info fdeInfo;
118aa0b96d0Sjoerg typename CFI_Parser<A, R>::CIE_Info cieInfo;
119aa0b96d0Sjoerg if (!CFI_Parser<A, R>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo,
120aa0b96d0Sjoerg ctx))
121aa0b96d0Sjoerg return UNW_STEP_FAILED;
122aa0b96d0Sjoerg
123aa0b96d0Sjoerg typename CFI_Parser<A, R>::PrologInfo prolog;
124aa0b96d0Sjoerg if (!CFI_Parser<A, R>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo,
125aa0b96d0Sjoerg pc, &prolog, ctx))
126aa0b96d0Sjoerg return UNW_STEP_FAILED;
127aa0b96d0Sjoerg
128aa0b96d0Sjoerg // Create working copy of the register set.
129aa0b96d0Sjoerg R newRegisters = registers;
130aa0b96d0Sjoerg
131aa0b96d0Sjoerg // Get pointer to CFA by the architecture-specific code.
132aa0b96d0Sjoerg pint_t cfa = getCFA(addressSpace, prolog, registers);
133aa0b96d0Sjoerg
134aa0b96d0Sjoerg // Restore registers according to DWARF instructions
135aa0b96d0Sjoerg pint_t returnAddress = 0;
136aa0b96d0Sjoerg for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
137aa0b96d0Sjoerg if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused)
138aa0b96d0Sjoerg continue;
139215abdb1Sjoerg if (i == (int)cieInfo.returnAddressRegister)
140aa0b96d0Sjoerg returnAddress = getSavedRegister(addressSpace, registers, cfa,
141aa0b96d0Sjoerg prolog.savedRegisters[i]);
142aa0b96d0Sjoerg else if (registers.validRegister(i))
143aa0b96d0Sjoerg newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa,
144aa0b96d0Sjoerg prolog.savedRegisters[i]));
145aa0b96d0Sjoerg else if (registers.validFloatVectorRegister(i))
146aa0b96d0Sjoerg newRegisters.copyFloatVectorRegister(
147aa0b96d0Sjoerg i, computeRegisterLocation(addressSpace, registers, cfa,
148aa0b96d0Sjoerg prolog.savedRegisters[i]));
149aa0b96d0Sjoerg else
150aa0b96d0Sjoerg return UNW_STEP_FAILED;
151aa0b96d0Sjoerg }
152aa0b96d0Sjoerg
153aa0b96d0Sjoerg // The CFA is defined as the stack pointer at the call site.
154aa0b96d0Sjoerg // Therefore the SP is restored by setting it to the CFA.
155aa0b96d0Sjoerg newRegisters.setSP(cfa);
156*0282220bSjoerg returnAddress += R::RETURN_OFFSET;
157*0282220bSjoerg returnAddress &= ~R::RETURN_MASK;
158*0282220bSjoerg newRegisters.setIP(returnAddress);
159aa0b96d0Sjoerg
160aa0b96d0Sjoerg // Now replace register set with the working copy.
161aa0b96d0Sjoerg registers = newRegisters;
162aa0b96d0Sjoerg
163aa0b96d0Sjoerg return UNW_STEP_SUCCESS;
164aa0b96d0Sjoerg }
165aa0b96d0Sjoerg
166aa0b96d0Sjoerg template <typename A, typename R>
167aa0b96d0Sjoerg typename A::pint_t
evaluateExpression(pint_t expression,A & addressSpace,const R & registers,pint_t initialStackValue)168aa0b96d0Sjoerg DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
169aa0b96d0Sjoerg const R ®isters,
170aa0b96d0Sjoerg pint_t initialStackValue) {
171aa0b96d0Sjoerg pint_t p = expression;
172aa0b96d0Sjoerg pint_t expressionEnd = expression + 20; // Rough estimate
173aa0b96d0Sjoerg uint64_t length = addressSpace.getULEB128(p, expressionEnd);
174aa0b96d0Sjoerg expressionEnd = p + length;
175aa0b96d0Sjoerg pint_t stack[100];
176aa0b96d0Sjoerg pint_t *sp = stack;
177aa0b96d0Sjoerg *(++sp) = initialStackValue;
178aa0b96d0Sjoerg
179aa0b96d0Sjoerg while (p < expressionEnd) {
180aa0b96d0Sjoerg uint8_t opcode = addressSpace.get8(p++);
181aa0b96d0Sjoerg sint_t svalue;
182aa0b96d0Sjoerg pint_t value;
183aa0b96d0Sjoerg uint32_t reg;
184aa0b96d0Sjoerg switch (opcode) {
185aa0b96d0Sjoerg case DW_OP_addr:
186aa0b96d0Sjoerg // push immediate address sized value
187aa0b96d0Sjoerg value = addressSpace.getP(p);
188aa0b96d0Sjoerg p += sizeof(pint_t);
189aa0b96d0Sjoerg *(++sp) = value;
190aa0b96d0Sjoerg break;
191aa0b96d0Sjoerg
192aa0b96d0Sjoerg case DW_OP_deref:
193aa0b96d0Sjoerg // pop stack, dereference, push result
194aa0b96d0Sjoerg value = *sp--;
195aa0b96d0Sjoerg *(++sp) = addressSpace.getP(value);
196aa0b96d0Sjoerg break;
197aa0b96d0Sjoerg
198aa0b96d0Sjoerg case DW_OP_const1u:
199aa0b96d0Sjoerg // push immediate 1 byte value
200aa0b96d0Sjoerg value = addressSpace.get8(p);
201aa0b96d0Sjoerg p += 1;
202aa0b96d0Sjoerg *(++sp) = value;
203aa0b96d0Sjoerg break;
204aa0b96d0Sjoerg
205aa0b96d0Sjoerg case DW_OP_const1s:
206aa0b96d0Sjoerg // push immediate 1 byte signed value
207aa0b96d0Sjoerg svalue = (int8_t)addressSpace.get8(p);
208aa0b96d0Sjoerg p += 1;
209aa0b96d0Sjoerg *(++sp) = svalue;
210aa0b96d0Sjoerg break;
211aa0b96d0Sjoerg
212aa0b96d0Sjoerg case DW_OP_const2u:
213aa0b96d0Sjoerg // push immediate 2 byte value
214aa0b96d0Sjoerg value = addressSpace.get16(p);
215aa0b96d0Sjoerg p += 2;
216aa0b96d0Sjoerg *(++sp) = value;
217aa0b96d0Sjoerg break;
218aa0b96d0Sjoerg
219aa0b96d0Sjoerg case DW_OP_const2s:
220aa0b96d0Sjoerg // push immediate 2 byte signed value
221aa0b96d0Sjoerg svalue = (int16_t)addressSpace.get16(p);
222aa0b96d0Sjoerg p += 2;
223aa0b96d0Sjoerg *(++sp) = svalue;
224aa0b96d0Sjoerg break;
225aa0b96d0Sjoerg
226aa0b96d0Sjoerg case DW_OP_const4u:
227aa0b96d0Sjoerg // push immediate 4 byte value
228aa0b96d0Sjoerg value = addressSpace.get32(p);
229aa0b96d0Sjoerg p += 4;
230aa0b96d0Sjoerg *(++sp) = value;
231aa0b96d0Sjoerg break;
232aa0b96d0Sjoerg
233aa0b96d0Sjoerg case DW_OP_const4s:
234aa0b96d0Sjoerg // push immediate 4 byte signed value
235aa0b96d0Sjoerg svalue = (int32_t)addressSpace.get32(p);
236aa0b96d0Sjoerg p += 4;
237aa0b96d0Sjoerg *(++sp) = svalue;
238aa0b96d0Sjoerg break;
239aa0b96d0Sjoerg
240aa0b96d0Sjoerg case DW_OP_const8u:
241aa0b96d0Sjoerg // push immediate 8 byte value
242aa0b96d0Sjoerg value = addressSpace.get64(p);
243aa0b96d0Sjoerg p += 8;
244aa0b96d0Sjoerg *(++sp) = value;
245aa0b96d0Sjoerg break;
246aa0b96d0Sjoerg
247aa0b96d0Sjoerg case DW_OP_const8s:
248aa0b96d0Sjoerg // push immediate 8 byte signed value
249aa0b96d0Sjoerg value = (int32_t)addressSpace.get64(p);
250aa0b96d0Sjoerg p += 8;
251aa0b96d0Sjoerg *(++sp) = value;
252aa0b96d0Sjoerg break;
253aa0b96d0Sjoerg
254aa0b96d0Sjoerg case DW_OP_constu:
255aa0b96d0Sjoerg // push immediate ULEB128 value
256aa0b96d0Sjoerg value = addressSpace.getULEB128(p, expressionEnd);
257aa0b96d0Sjoerg *(++sp) = value;
258aa0b96d0Sjoerg break;
259aa0b96d0Sjoerg
260aa0b96d0Sjoerg case DW_OP_consts:
261aa0b96d0Sjoerg // push immediate SLEB128 value
262aa0b96d0Sjoerg svalue = addressSpace.getSLEB128(p, expressionEnd);
263aa0b96d0Sjoerg *(++sp) = svalue;
264aa0b96d0Sjoerg break;
265aa0b96d0Sjoerg
266aa0b96d0Sjoerg case DW_OP_dup:
267aa0b96d0Sjoerg // push top of stack
268aa0b96d0Sjoerg value = *sp;
269aa0b96d0Sjoerg *(++sp) = value;
270aa0b96d0Sjoerg break;
271aa0b96d0Sjoerg
272aa0b96d0Sjoerg case DW_OP_drop:
273aa0b96d0Sjoerg // pop
274aa0b96d0Sjoerg --sp;
275aa0b96d0Sjoerg break;
276aa0b96d0Sjoerg
277aa0b96d0Sjoerg case DW_OP_over:
278aa0b96d0Sjoerg // dup second
279aa0b96d0Sjoerg value = sp[-1];
280aa0b96d0Sjoerg *(++sp) = value;
281aa0b96d0Sjoerg break;
282aa0b96d0Sjoerg
283aa0b96d0Sjoerg case DW_OP_pick:
284aa0b96d0Sjoerg // pick from
285aa0b96d0Sjoerg reg = addressSpace.get8(p);
286aa0b96d0Sjoerg p += 1;
287aa0b96d0Sjoerg value = sp[-reg];
288aa0b96d0Sjoerg *(++sp) = value;
289aa0b96d0Sjoerg break;
290aa0b96d0Sjoerg
291aa0b96d0Sjoerg case DW_OP_swap:
292aa0b96d0Sjoerg // swap top two
293aa0b96d0Sjoerg value = sp[0];
294aa0b96d0Sjoerg sp[0] = sp[-1];
295aa0b96d0Sjoerg sp[-1] = value;
296aa0b96d0Sjoerg break;
297aa0b96d0Sjoerg
298aa0b96d0Sjoerg case DW_OP_rot:
299aa0b96d0Sjoerg // rotate top three
300aa0b96d0Sjoerg value = sp[0];
301aa0b96d0Sjoerg sp[0] = sp[-1];
302aa0b96d0Sjoerg sp[-1] = sp[-2];
303aa0b96d0Sjoerg sp[-2] = value;
304aa0b96d0Sjoerg break;
305aa0b96d0Sjoerg
306aa0b96d0Sjoerg case DW_OP_xderef:
307aa0b96d0Sjoerg // pop stack, dereference, push result
308aa0b96d0Sjoerg value = *sp--;
309aa0b96d0Sjoerg *sp = *((uint64_t *)value);
310aa0b96d0Sjoerg break;
311aa0b96d0Sjoerg
312aa0b96d0Sjoerg case DW_OP_abs:
313aa0b96d0Sjoerg svalue = *sp;
314aa0b96d0Sjoerg if (svalue < 0)
315aa0b96d0Sjoerg *sp = -svalue;
316aa0b96d0Sjoerg break;
317aa0b96d0Sjoerg
318aa0b96d0Sjoerg case DW_OP_and:
319aa0b96d0Sjoerg value = *sp--;
320aa0b96d0Sjoerg *sp &= value;
321aa0b96d0Sjoerg break;
322aa0b96d0Sjoerg
323aa0b96d0Sjoerg case DW_OP_div:
324aa0b96d0Sjoerg svalue = *sp--;
325aa0b96d0Sjoerg *sp = *sp / svalue;
326aa0b96d0Sjoerg break;
327aa0b96d0Sjoerg
328aa0b96d0Sjoerg case DW_OP_minus:
329aa0b96d0Sjoerg svalue = *sp--;
330aa0b96d0Sjoerg *sp = *sp - svalue;
331aa0b96d0Sjoerg break;
332aa0b96d0Sjoerg
333aa0b96d0Sjoerg case DW_OP_mod:
334aa0b96d0Sjoerg svalue = *sp--;
335aa0b96d0Sjoerg *sp = *sp % svalue;
336aa0b96d0Sjoerg break;
337aa0b96d0Sjoerg
338aa0b96d0Sjoerg case DW_OP_mul:
339aa0b96d0Sjoerg svalue = *sp--;
340aa0b96d0Sjoerg *sp = *sp * svalue;
341aa0b96d0Sjoerg break;
342aa0b96d0Sjoerg
343aa0b96d0Sjoerg case DW_OP_neg:
344aa0b96d0Sjoerg *sp = 0 - *sp;
345aa0b96d0Sjoerg break;
346aa0b96d0Sjoerg
347aa0b96d0Sjoerg case DW_OP_not:
348aa0b96d0Sjoerg svalue = *sp;
349aa0b96d0Sjoerg *sp = ~svalue;
350aa0b96d0Sjoerg break;
351aa0b96d0Sjoerg
352aa0b96d0Sjoerg case DW_OP_or:
353aa0b96d0Sjoerg value = *sp--;
354aa0b96d0Sjoerg *sp |= value;
355aa0b96d0Sjoerg break;
356aa0b96d0Sjoerg
357aa0b96d0Sjoerg case DW_OP_plus:
358aa0b96d0Sjoerg value = *sp--;
359aa0b96d0Sjoerg *sp += value;
360aa0b96d0Sjoerg break;
361aa0b96d0Sjoerg
362aa0b96d0Sjoerg case DW_OP_plus_uconst:
363aa0b96d0Sjoerg // pop stack, add uelb128 constant, push result
364aa0b96d0Sjoerg *sp += addressSpace.getULEB128(p, expressionEnd);
365aa0b96d0Sjoerg break;
366aa0b96d0Sjoerg
367aa0b96d0Sjoerg case DW_OP_shl:
368aa0b96d0Sjoerg value = *sp--;
369aa0b96d0Sjoerg *sp = *sp << value;
370aa0b96d0Sjoerg break;
371aa0b96d0Sjoerg
372aa0b96d0Sjoerg case DW_OP_shr:
373aa0b96d0Sjoerg value = *sp--;
374aa0b96d0Sjoerg *sp = *sp >> value;
375aa0b96d0Sjoerg break;
376aa0b96d0Sjoerg
377aa0b96d0Sjoerg case DW_OP_shra:
378aa0b96d0Sjoerg value = *sp--;
379aa0b96d0Sjoerg svalue = *sp;
380aa0b96d0Sjoerg *sp = svalue >> value;
381aa0b96d0Sjoerg break;
382aa0b96d0Sjoerg
383aa0b96d0Sjoerg case DW_OP_xor:
384aa0b96d0Sjoerg value = *sp--;
385aa0b96d0Sjoerg *sp ^= value;
386aa0b96d0Sjoerg break;
387aa0b96d0Sjoerg
388aa0b96d0Sjoerg case DW_OP_skip:
389aa0b96d0Sjoerg svalue = (int16_t)addressSpace.get16(p);
390aa0b96d0Sjoerg p += 2;
391aa0b96d0Sjoerg p += svalue;
392aa0b96d0Sjoerg break;
393aa0b96d0Sjoerg
394aa0b96d0Sjoerg case DW_OP_bra:
395aa0b96d0Sjoerg svalue = (int16_t)addressSpace.get16(p);
396aa0b96d0Sjoerg p += 2;
397aa0b96d0Sjoerg if (*sp--)
398aa0b96d0Sjoerg p += svalue;
399aa0b96d0Sjoerg break;
400aa0b96d0Sjoerg
401aa0b96d0Sjoerg case DW_OP_eq:
402aa0b96d0Sjoerg value = *sp--;
403aa0b96d0Sjoerg *sp = (*sp == value);
404aa0b96d0Sjoerg break;
405aa0b96d0Sjoerg
406aa0b96d0Sjoerg case DW_OP_ge:
407aa0b96d0Sjoerg value = *sp--;
408aa0b96d0Sjoerg *sp = (*sp >= value);
409aa0b96d0Sjoerg break;
410aa0b96d0Sjoerg
411aa0b96d0Sjoerg case DW_OP_gt:
412aa0b96d0Sjoerg value = *sp--;
413aa0b96d0Sjoerg *sp = (*sp > value);
414aa0b96d0Sjoerg break;
415aa0b96d0Sjoerg
416aa0b96d0Sjoerg case DW_OP_le:
417aa0b96d0Sjoerg value = *sp--;
418aa0b96d0Sjoerg *sp = (*sp <= value);
419aa0b96d0Sjoerg break;
420aa0b96d0Sjoerg
421aa0b96d0Sjoerg case DW_OP_lt:
422aa0b96d0Sjoerg value = *sp--;
423aa0b96d0Sjoerg *sp = (*sp < value);
424aa0b96d0Sjoerg break;
425aa0b96d0Sjoerg
426aa0b96d0Sjoerg case DW_OP_ne:
427aa0b96d0Sjoerg value = *sp--;
428aa0b96d0Sjoerg *sp = (*sp != value);
429aa0b96d0Sjoerg break;
430aa0b96d0Sjoerg
431aa0b96d0Sjoerg case DW_OP_lit0:
432aa0b96d0Sjoerg case DW_OP_lit1:
433aa0b96d0Sjoerg case DW_OP_lit2:
434aa0b96d0Sjoerg case DW_OP_lit3:
435aa0b96d0Sjoerg case DW_OP_lit4:
436aa0b96d0Sjoerg case DW_OP_lit5:
437aa0b96d0Sjoerg case DW_OP_lit6:
438aa0b96d0Sjoerg case DW_OP_lit7:
439aa0b96d0Sjoerg case DW_OP_lit8:
440aa0b96d0Sjoerg case DW_OP_lit9:
441aa0b96d0Sjoerg case DW_OP_lit10:
442aa0b96d0Sjoerg case DW_OP_lit11:
443aa0b96d0Sjoerg case DW_OP_lit12:
444aa0b96d0Sjoerg case DW_OP_lit13:
445aa0b96d0Sjoerg case DW_OP_lit14:
446aa0b96d0Sjoerg case DW_OP_lit15:
447aa0b96d0Sjoerg case DW_OP_lit16:
448aa0b96d0Sjoerg case DW_OP_lit17:
449aa0b96d0Sjoerg case DW_OP_lit18:
450aa0b96d0Sjoerg case DW_OP_lit19:
451aa0b96d0Sjoerg case DW_OP_lit20:
452aa0b96d0Sjoerg case DW_OP_lit21:
453aa0b96d0Sjoerg case DW_OP_lit22:
454aa0b96d0Sjoerg case DW_OP_lit23:
455aa0b96d0Sjoerg case DW_OP_lit24:
456aa0b96d0Sjoerg case DW_OP_lit25:
457aa0b96d0Sjoerg case DW_OP_lit26:
458aa0b96d0Sjoerg case DW_OP_lit27:
459aa0b96d0Sjoerg case DW_OP_lit28:
460aa0b96d0Sjoerg case DW_OP_lit29:
461aa0b96d0Sjoerg case DW_OP_lit30:
462aa0b96d0Sjoerg case DW_OP_lit31:
463aa0b96d0Sjoerg value = opcode - DW_OP_lit0;
464aa0b96d0Sjoerg *(++sp) = value;
465aa0b96d0Sjoerg break;
466aa0b96d0Sjoerg
467aa0b96d0Sjoerg case DW_OP_reg0:
468aa0b96d0Sjoerg case DW_OP_reg1:
469aa0b96d0Sjoerg case DW_OP_reg2:
470aa0b96d0Sjoerg case DW_OP_reg3:
471aa0b96d0Sjoerg case DW_OP_reg4:
472aa0b96d0Sjoerg case DW_OP_reg5:
473aa0b96d0Sjoerg case DW_OP_reg6:
474aa0b96d0Sjoerg case DW_OP_reg7:
475aa0b96d0Sjoerg case DW_OP_reg8:
476aa0b96d0Sjoerg case DW_OP_reg9:
477aa0b96d0Sjoerg case DW_OP_reg10:
478aa0b96d0Sjoerg case DW_OP_reg11:
479aa0b96d0Sjoerg case DW_OP_reg12:
480aa0b96d0Sjoerg case DW_OP_reg13:
481aa0b96d0Sjoerg case DW_OP_reg14:
482aa0b96d0Sjoerg case DW_OP_reg15:
483aa0b96d0Sjoerg case DW_OP_reg16:
484aa0b96d0Sjoerg case DW_OP_reg17:
485aa0b96d0Sjoerg case DW_OP_reg18:
486aa0b96d0Sjoerg case DW_OP_reg19:
487aa0b96d0Sjoerg case DW_OP_reg20:
488aa0b96d0Sjoerg case DW_OP_reg21:
489aa0b96d0Sjoerg case DW_OP_reg22:
490aa0b96d0Sjoerg case DW_OP_reg23:
491aa0b96d0Sjoerg case DW_OP_reg24:
492aa0b96d0Sjoerg case DW_OP_reg25:
493aa0b96d0Sjoerg case DW_OP_reg26:
494aa0b96d0Sjoerg case DW_OP_reg27:
495aa0b96d0Sjoerg case DW_OP_reg28:
496aa0b96d0Sjoerg case DW_OP_reg29:
497aa0b96d0Sjoerg case DW_OP_reg30:
498aa0b96d0Sjoerg case DW_OP_reg31:
499aa0b96d0Sjoerg reg = opcode - DW_OP_reg0;
500aa0b96d0Sjoerg *(++sp) = registers.getRegister(reg);
501aa0b96d0Sjoerg break;
502aa0b96d0Sjoerg
503aa0b96d0Sjoerg case DW_OP_regx:
504aa0b96d0Sjoerg reg = addressSpace.getULEB128(p, expressionEnd);
505aa0b96d0Sjoerg *(++sp) = registers.getRegister(reg);
506aa0b96d0Sjoerg break;
507aa0b96d0Sjoerg
508aa0b96d0Sjoerg case DW_OP_breg0:
509aa0b96d0Sjoerg case DW_OP_breg1:
510aa0b96d0Sjoerg case DW_OP_breg2:
511aa0b96d0Sjoerg case DW_OP_breg3:
512aa0b96d0Sjoerg case DW_OP_breg4:
513aa0b96d0Sjoerg case DW_OP_breg5:
514aa0b96d0Sjoerg case DW_OP_breg6:
515aa0b96d0Sjoerg case DW_OP_breg7:
516aa0b96d0Sjoerg case DW_OP_breg8:
517aa0b96d0Sjoerg case DW_OP_breg9:
518aa0b96d0Sjoerg case DW_OP_breg10:
519aa0b96d0Sjoerg case DW_OP_breg11:
520aa0b96d0Sjoerg case DW_OP_breg12:
521aa0b96d0Sjoerg case DW_OP_breg13:
522aa0b96d0Sjoerg case DW_OP_breg14:
523aa0b96d0Sjoerg case DW_OP_breg15:
524aa0b96d0Sjoerg case DW_OP_breg16:
525aa0b96d0Sjoerg case DW_OP_breg17:
526aa0b96d0Sjoerg case DW_OP_breg18:
527aa0b96d0Sjoerg case DW_OP_breg19:
528aa0b96d0Sjoerg case DW_OP_breg20:
529aa0b96d0Sjoerg case DW_OP_breg21:
530aa0b96d0Sjoerg case DW_OP_breg22:
531aa0b96d0Sjoerg case DW_OP_breg23:
532aa0b96d0Sjoerg case DW_OP_breg24:
533aa0b96d0Sjoerg case DW_OP_breg25:
534aa0b96d0Sjoerg case DW_OP_breg26:
535aa0b96d0Sjoerg case DW_OP_breg27:
536aa0b96d0Sjoerg case DW_OP_breg28:
537aa0b96d0Sjoerg case DW_OP_breg29:
538aa0b96d0Sjoerg case DW_OP_breg30:
539aa0b96d0Sjoerg case DW_OP_breg31:
540aa0b96d0Sjoerg reg = opcode - DW_OP_breg0;
541aa0b96d0Sjoerg svalue = addressSpace.getSLEB128(p, expressionEnd);
542aa0b96d0Sjoerg *(++sp) = registers.getRegister(reg) + svalue;
543aa0b96d0Sjoerg break;
544aa0b96d0Sjoerg
545aa0b96d0Sjoerg case DW_OP_bregx:
546aa0b96d0Sjoerg reg = addressSpace.getULEB128(p, expressionEnd);
547aa0b96d0Sjoerg svalue = addressSpace.getSLEB128(p, expressionEnd);
548aa0b96d0Sjoerg *(++sp) = registers.getRegister(reg) + svalue;
549aa0b96d0Sjoerg break;
550aa0b96d0Sjoerg
551aa0b96d0Sjoerg case DW_OP_deref_size:
552aa0b96d0Sjoerg // pop stack, dereference, push result
553aa0b96d0Sjoerg value = *sp--;
554aa0b96d0Sjoerg switch (addressSpace.get8(p++)) {
555aa0b96d0Sjoerg case 1:
556aa0b96d0Sjoerg value = addressSpace.get8(value);
557aa0b96d0Sjoerg break;
558aa0b96d0Sjoerg case 2:
559aa0b96d0Sjoerg value = addressSpace.get16(value);
560aa0b96d0Sjoerg break;
561aa0b96d0Sjoerg case 4:
562aa0b96d0Sjoerg value = addressSpace.get32(value);
563aa0b96d0Sjoerg break;
564aa0b96d0Sjoerg case 8:
565aa0b96d0Sjoerg value = addressSpace.get64(value);
566aa0b96d0Sjoerg break;
567aa0b96d0Sjoerg default:
568aa0b96d0Sjoerg assert(0 && "DW_OP_deref_size with bad size");
569aa0b96d0Sjoerg }
570aa0b96d0Sjoerg *(++sp) = value;
571aa0b96d0Sjoerg break;
572aa0b96d0Sjoerg
573aa0b96d0Sjoerg case DW_OP_fbreg:
574aa0b96d0Sjoerg case DW_OP_piece:
575aa0b96d0Sjoerg case DW_OP_xderef_size:
576aa0b96d0Sjoerg case DW_OP_nop:
577aa0b96d0Sjoerg case DW_OP_push_object_addres:
578aa0b96d0Sjoerg case DW_OP_call2:
579aa0b96d0Sjoerg case DW_OP_call4:
580aa0b96d0Sjoerg case DW_OP_call_ref:
581aa0b96d0Sjoerg default:
582aa0b96d0Sjoerg assert(0 && "dwarf opcode not implemented");
583aa0b96d0Sjoerg }
584aa0b96d0Sjoerg }
585aa0b96d0Sjoerg return *sp;
586aa0b96d0Sjoerg }
587aa0b96d0Sjoerg
588aa0b96d0Sjoerg } // namespace _Unwind
589aa0b96d0Sjoerg
590aa0b96d0Sjoerg #endif // __DWARF_INSTRUCTIONS_HPP__
591