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