]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libunwind/src/DwarfInstructions.hpp
MFC r345703:
[FreeBSD/FreeBSD.git] / contrib / libunwind / src / DwarfInstructions.hpp
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 <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include "dwarf2.h"
21 #include "Registers.hpp"
22 #include "DwarfParser.hpp"
23 #include "config.h"
24
25
26 namespace libunwind {
27
28
29 /// DwarfInstructions maps abtract DWARF unwind instructions to a particular
30 /// architecture
31 template <typename A, typename R>
32 class DwarfInstructions {
33 public:
34   typedef typename A::pint_t pint_t;
35   typedef typename A::sint_t sint_t;
36
37   static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
38                            R &registers);
39
40 private:
41
42   enum {
43     DW_X86_64_RET_ADDR = 16
44   };
45
46   enum {
47     DW_X86_RET_ADDR = 8
48   };
49
50   typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
51   typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
52   typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
53   typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
54
55   static pint_t evaluateExpression(pint_t expression, A &addressSpace,
56                                    const R &registers,
57                                    pint_t initialStackValue);
58   static pint_t getSavedRegister(A &addressSpace, const R &registers,
59                                  pint_t cfa, const RegisterLocation &savedReg);
60   static double getSavedFloatRegister(A &addressSpace, const R &registers,
61                                   pint_t cfa, const RegisterLocation &savedReg);
62   static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
63                                   pint_t cfa, const RegisterLocation &savedReg);
64
65   static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
66                        const R &registers) {
67     if (prolog.cfaRegister != 0)
68       return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
69              prolog.cfaRegisterOffset);
70     if (prolog.cfaExpression != 0)
71       return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, 
72                                 registers, 0);
73     assert(0 && "getCFA(): unknown location");
74     __builtin_unreachable();
75   }
76 };
77
78
79 template <typename A, typename R>
80 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
81     A &addressSpace, const R &registers, pint_t cfa,
82     const RegisterLocation &savedReg) {
83   switch (savedReg.location) {
84   case CFI_Parser<A>::kRegisterInCFA:
85     return addressSpace.getRegister(cfa + (pint_t)savedReg.value);
86
87   case CFI_Parser<A>::kRegisterAtExpression:
88     return addressSpace.getRegister(
89         evaluateExpression((pint_t)savedReg.value, addressSpace,
90                             registers, cfa));
91
92   case CFI_Parser<A>::kRegisterIsExpression:
93     return evaluateExpression((pint_t)savedReg.value, addressSpace,
94                               registers, cfa);
95
96   case CFI_Parser<A>::kRegisterInRegister:
97     return registers.getRegister((int)savedReg.value);
98
99   case CFI_Parser<A>::kRegisterUnused:
100   case CFI_Parser<A>::kRegisterOffsetFromCFA:
101     // FIX ME
102     break;
103   }
104   _LIBUNWIND_ABORT("unsupported restore location for register");
105 }
106
107 template <typename A, typename R>
108 double DwarfInstructions<A, R>::getSavedFloatRegister(
109     A &addressSpace, const R &registers, pint_t cfa,
110     const RegisterLocation &savedReg) {
111   switch (savedReg.location) {
112   case CFI_Parser<A>::kRegisterInCFA:
113     return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
114
115   case CFI_Parser<A>::kRegisterAtExpression:
116     return addressSpace.getDouble(
117         evaluateExpression((pint_t)savedReg.value, addressSpace,
118                             registers, cfa));
119
120   case CFI_Parser<A>::kRegisterIsExpression:
121   case CFI_Parser<A>::kRegisterUnused:
122   case CFI_Parser<A>::kRegisterOffsetFromCFA:
123   case CFI_Parser<A>::kRegisterInRegister:
124     // FIX ME
125     break;
126   }
127   _LIBUNWIND_ABORT("unsupported restore location for float register");
128 }
129
130 template <typename A, typename R>
131 v128 DwarfInstructions<A, R>::getSavedVectorRegister(
132     A &addressSpace, const R &registers, pint_t cfa,
133     const RegisterLocation &savedReg) {
134   switch (savedReg.location) {
135   case CFI_Parser<A>::kRegisterInCFA:
136     return addressSpace.getVector(cfa + (pint_t)savedReg.value);
137
138   case CFI_Parser<A>::kRegisterAtExpression:
139     return addressSpace.getVector(
140         evaluateExpression((pint_t)savedReg.value, addressSpace,
141                             registers, cfa));
142
143   case CFI_Parser<A>::kRegisterIsExpression:
144   case CFI_Parser<A>::kRegisterUnused:
145   case CFI_Parser<A>::kRegisterOffsetFromCFA:
146   case CFI_Parser<A>::kRegisterInRegister:
147     // FIX ME
148     break;
149   }
150   _LIBUNWIND_ABORT("unsupported restore location for vector register");
151 }
152
153 template <typename A, typename R>
154 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
155                                            pint_t fdeStart, R &registers) {
156   FDE_Info fdeInfo;
157   CIE_Info cieInfo;
158   if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
159                                &cieInfo) == NULL) {
160     PrologInfo prolog;
161     if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
162                                             R::getArch(), &prolog)) {
163       // get pointer to cfa (architecture specific)
164       pint_t cfa = getCFA(addressSpace, prolog, registers);
165
166        // restore registers that DWARF says were saved
167       R newRegisters = registers;
168       pint_t returnAddress = 0;
169       const int lastReg = R::lastDwarfRegNum();
170       assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
171              "register range too large");
172       assert(lastReg >= (int)cieInfo.returnAddressRegister &&
173              "register range does not contain return address register");
174       for (int i = 0; i <= lastReg; ++i) {
175         if (prolog.savedRegisters[i].location !=
176             CFI_Parser<A>::kRegisterUnused) {
177           if (registers.validFloatRegister(i))
178             newRegisters.setFloatRegister(
179                 i, getSavedFloatRegister(addressSpace, registers, cfa,
180                                          prolog.savedRegisters[i]));
181           else if (registers.validVectorRegister(i))
182             newRegisters.setVectorRegister(
183                 i, getSavedVectorRegister(addressSpace, registers, cfa,
184                                           prolog.savedRegisters[i]));
185           else if (i == (int)cieInfo.returnAddressRegister)
186             returnAddress = getSavedRegister(addressSpace, registers, cfa,
187                                              prolog.savedRegisters[i]);
188           else if (registers.validRegister(i))
189             newRegisters.setRegister(
190                 i, getSavedRegister(addressSpace, registers, cfa,
191                                     prolog.savedRegisters[i]));
192           else
193             return UNW_EBADREG;
194         }
195       }
196
197       // By definition, the CFA is the stack pointer at the call site, so
198       // restoring SP means setting it to CFA.
199       newRegisters.setSP(cfa);
200
201 #if defined(_LIBUNWIND_TARGET_AARCH64)
202       // If the target is aarch64 then the return address may have been signed
203       // using the v8.3 pointer authentication extensions. The original
204       // return address needs to be authenticated before the return address is
205       // restored. autia1716 is used instead of autia as autia1716 assembles
206       // to a NOP on pre-v8.3a architectures.
207       if ((R::getArch() == REGISTERS_ARM64) &&
208           prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
209 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
210         return UNW_ECROSSRASIGNING;
211 #else
212         register unsigned long long x17 __asm("x17") = returnAddress;
213         register unsigned long long x16 __asm("x16") = cfa;
214
215         // These are the autia1716/autib1716 instructions. The hint instructions
216         // are used here as gcc does not assemble autia1716/autib1716 for pre
217         // armv8.3a targets.
218         if (cieInfo.addressesSignedWithBKey)
219           asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
220         else
221           asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
222         returnAddress = x17;
223 #endif
224       }
225 #endif
226
227 #if defined(_LIBUNWIND_TARGET_SPARC)
228       if (R::getArch() == REGISTERS_SPARC) {
229         // Skip call site instruction and delay slot
230         returnAddress += 8;
231         // Skip unimp instruction if function returns a struct
232         if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
233           returnAddress += 4;
234       }
235 #endif
236
237       // Return address is address after call site instruction, so setting IP to
238       // that does simualates a return.
239       newRegisters.setIP(returnAddress);
240
241       // Simulate the step by replacing the register set with the new ones.
242       registers = newRegisters;
243
244       return UNW_STEP_SUCCESS;
245     }
246   }
247   return UNW_EBADFRAME;
248 }
249
250 template <typename A, typename R>
251 typename A::pint_t
252 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
253                                             const R &registers,
254                                             pint_t initialStackValue) {
255   const bool log = false;
256   pint_t p = expression;
257   pint_t expressionEnd = expression + 20; // temp, until len read
258   pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
259   expressionEnd = p + length;
260   if (log)
261     fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
262             (uint64_t)length);
263   pint_t stack[100];
264   pint_t *sp = stack;
265   *(++sp) = initialStackValue;
266
267   while (p < expressionEnd) {
268     if (log) {
269       for (pint_t *t = sp; t > stack; --t) {
270         fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
271       }
272     }
273     uint8_t opcode = addressSpace.get8(p++);
274     sint_t svalue, svalue2;
275     pint_t value;
276     uint32_t reg;
277     switch (opcode) {
278     case DW_OP_addr:
279       // push immediate address sized value
280       value = addressSpace.getP(p);
281       p += sizeof(pint_t);
282       *(++sp) = value;
283       if (log)
284         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
285       break;
286
287     case DW_OP_deref:
288       // pop stack, dereference, push result
289       value = *sp--;
290       *(++sp) = addressSpace.getP(value);
291       if (log)
292         fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
293       break;
294
295     case DW_OP_const1u:
296       // push immediate 1 byte value
297       value = addressSpace.get8(p);
298       p += 1;
299       *(++sp) = value;
300       if (log)
301         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
302       break;
303
304     case DW_OP_const1s:
305       // push immediate 1 byte signed value
306       svalue = (int8_t) addressSpace.get8(p);
307       p += 1;
308       *(++sp) = (pint_t)svalue;
309       if (log)
310         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
311       break;
312
313     case DW_OP_const2u:
314       // push immediate 2 byte value
315       value = addressSpace.get16(p);
316       p += 2;
317       *(++sp) = value;
318       if (log)
319         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
320       break;
321
322     case DW_OP_const2s:
323       // push immediate 2 byte signed value
324       svalue = (int16_t) addressSpace.get16(p);
325       p += 2;
326       *(++sp) = (pint_t)svalue;
327       if (log)
328         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
329       break;
330
331     case DW_OP_const4u:
332       // push immediate 4 byte value
333       value = addressSpace.get32(p);
334       p += 4;
335       *(++sp) = value;
336       if (log)
337         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
338       break;
339
340     case DW_OP_const4s:
341       // push immediate 4 byte signed value
342       svalue = (int32_t)addressSpace.get32(p);
343       p += 4;
344       *(++sp) = (pint_t)svalue;
345       if (log)
346         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
347       break;
348
349     case DW_OP_const8u:
350       // push immediate 8 byte value
351       value = (pint_t)addressSpace.get64(p);
352       p += 8;
353       *(++sp) = value;
354       if (log)
355         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
356       break;
357
358     case DW_OP_const8s:
359       // push immediate 8 byte signed value
360       value = (pint_t)addressSpace.get64(p);
361       p += 8;
362       *(++sp) = value;
363       if (log)
364         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
365       break;
366
367     case DW_OP_constu:
368       // push immediate ULEB128 value
369       value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
370       *(++sp) = value;
371       if (log)
372         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
373       break;
374
375     case DW_OP_consts:
376       // push immediate SLEB128 value
377       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
378       *(++sp) = (pint_t)svalue;
379       if (log)
380         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
381       break;
382
383     case DW_OP_dup:
384       // push top of stack
385       value = *sp;
386       *(++sp) = value;
387       if (log)
388         fprintf(stderr, "duplicate top of stack\n");
389       break;
390
391     case DW_OP_drop:
392       // pop
393       --sp;
394       if (log)
395         fprintf(stderr, "pop top of stack\n");
396       break;
397
398     case DW_OP_over:
399       // dup second
400       value = sp[-1];
401       *(++sp) = value;
402       if (log)
403         fprintf(stderr, "duplicate second in stack\n");
404       break;
405
406     case DW_OP_pick:
407       // pick from
408       reg = addressSpace.get8(p);
409       p += 1;
410       value = sp[-reg];
411       *(++sp) = value;
412       if (log)
413         fprintf(stderr, "duplicate %d in stack\n", reg);
414       break;
415
416     case DW_OP_swap:
417       // swap top two
418       value = sp[0];
419       sp[0] = sp[-1];
420       sp[-1] = value;
421       if (log)
422         fprintf(stderr, "swap top of stack\n");
423       break;
424
425     case DW_OP_rot:
426       // rotate top three
427       value = sp[0];
428       sp[0] = sp[-1];
429       sp[-1] = sp[-2];
430       sp[-2] = value;
431       if (log)
432         fprintf(stderr, "rotate top three of stack\n");
433       break;
434
435     case DW_OP_xderef:
436       // pop stack, dereference, push result
437       value = *sp--;
438       *sp = *((pint_t*)value);
439       if (log)
440         fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
441       break;
442
443     case DW_OP_abs:
444       svalue = (sint_t)*sp;
445       if (svalue < 0)
446         *sp = (pint_t)(-svalue);
447       if (log)
448         fprintf(stderr, "abs\n");
449       break;
450
451     case DW_OP_and:
452       value = *sp--;
453       *sp &= value;
454       if (log)
455         fprintf(stderr, "and\n");
456       break;
457
458     case DW_OP_div:
459       svalue = (sint_t)(*sp--);
460       svalue2 = (sint_t)*sp;
461       *sp = (pint_t)(svalue2 / svalue);
462       if (log)
463         fprintf(stderr, "div\n");
464       break;
465
466     case DW_OP_minus:
467       value = *sp--;
468       *sp = *sp - value;
469       if (log)
470         fprintf(stderr, "minus\n");
471       break;
472
473     case DW_OP_mod:
474       svalue = (sint_t)(*sp--);
475       svalue2 = (sint_t)*sp;
476       *sp = (pint_t)(svalue2 % svalue);
477       if (log)
478         fprintf(stderr, "module\n");
479       break;
480
481     case DW_OP_mul:
482       svalue = (sint_t)(*sp--);
483       svalue2 = (sint_t)*sp;
484       *sp = (pint_t)(svalue2 * svalue);
485       if (log)
486         fprintf(stderr, "mul\n");
487       break;
488
489     case DW_OP_neg:
490       *sp = 0 - *sp;
491       if (log)
492         fprintf(stderr, "neg\n");
493       break;
494
495     case DW_OP_not:
496       svalue = (sint_t)(*sp);
497       *sp = (pint_t)(~svalue);
498       if (log)
499         fprintf(stderr, "not\n");
500       break;
501
502     case DW_OP_or:
503       value = *sp--;
504       *sp |= value;
505       if (log)
506         fprintf(stderr, "or\n");
507       break;
508
509     case DW_OP_plus:
510       value = *sp--;
511       *sp += value;
512       if (log)
513         fprintf(stderr, "plus\n");
514       break;
515
516     case DW_OP_plus_uconst:
517       // pop stack, add uelb128 constant, push result
518       *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
519       if (log)
520         fprintf(stderr, "add constant\n");
521       break;
522
523     case DW_OP_shl:
524       value = *sp--;
525       *sp = *sp << value;
526       if (log)
527         fprintf(stderr, "shift left\n");
528       break;
529
530     case DW_OP_shr:
531       value = *sp--;
532       *sp = *sp >> value;
533       if (log)
534         fprintf(stderr, "shift left\n");
535       break;
536
537     case DW_OP_shra:
538       value = *sp--;
539       svalue = (sint_t)*sp;
540       *sp = (pint_t)(svalue >> value);
541       if (log)
542         fprintf(stderr, "shift left arithmetric\n");
543       break;
544
545     case DW_OP_xor:
546       value = *sp--;
547       *sp ^= value;
548       if (log)
549         fprintf(stderr, "xor\n");
550       break;
551
552     case DW_OP_skip:
553       svalue = (int16_t) addressSpace.get16(p);
554       p += 2;
555       p = (pint_t)((sint_t)p + svalue);
556       if (log)
557         fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
558       break;
559
560     case DW_OP_bra:
561       svalue = (int16_t) addressSpace.get16(p);
562       p += 2;
563       if (*sp--)
564         p = (pint_t)((sint_t)p + svalue);
565       if (log)
566         fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
567       break;
568
569     case DW_OP_eq:
570       value = *sp--;
571       *sp = (*sp == value);
572       if (log)
573         fprintf(stderr, "eq\n");
574       break;
575
576     case DW_OP_ge:
577       value = *sp--;
578       *sp = (*sp >= value);
579       if (log)
580         fprintf(stderr, "ge\n");
581       break;
582
583     case DW_OP_gt:
584       value = *sp--;
585       *sp = (*sp > value);
586       if (log)
587         fprintf(stderr, "gt\n");
588       break;
589
590     case DW_OP_le:
591       value = *sp--;
592       *sp = (*sp <= value);
593       if (log)
594         fprintf(stderr, "le\n");
595       break;
596
597     case DW_OP_lt:
598       value = *sp--;
599       *sp = (*sp < value);
600       if (log)
601         fprintf(stderr, "lt\n");
602       break;
603
604     case DW_OP_ne:
605       value = *sp--;
606       *sp = (*sp != value);
607       if (log)
608         fprintf(stderr, "ne\n");
609       break;
610
611     case DW_OP_lit0:
612     case DW_OP_lit1:
613     case DW_OP_lit2:
614     case DW_OP_lit3:
615     case DW_OP_lit4:
616     case DW_OP_lit5:
617     case DW_OP_lit6:
618     case DW_OP_lit7:
619     case DW_OP_lit8:
620     case DW_OP_lit9:
621     case DW_OP_lit10:
622     case DW_OP_lit11:
623     case DW_OP_lit12:
624     case DW_OP_lit13:
625     case DW_OP_lit14:
626     case DW_OP_lit15:
627     case DW_OP_lit16:
628     case DW_OP_lit17:
629     case DW_OP_lit18:
630     case DW_OP_lit19:
631     case DW_OP_lit20:
632     case DW_OP_lit21:
633     case DW_OP_lit22:
634     case DW_OP_lit23:
635     case DW_OP_lit24:
636     case DW_OP_lit25:
637     case DW_OP_lit26:
638     case DW_OP_lit27:
639     case DW_OP_lit28:
640     case DW_OP_lit29:
641     case DW_OP_lit30:
642     case DW_OP_lit31:
643       value = static_cast<pint_t>(opcode - DW_OP_lit0);
644       *(++sp) = value;
645       if (log)
646         fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
647       break;
648
649     case DW_OP_reg0:
650     case DW_OP_reg1:
651     case DW_OP_reg2:
652     case DW_OP_reg3:
653     case DW_OP_reg4:
654     case DW_OP_reg5:
655     case DW_OP_reg6:
656     case DW_OP_reg7:
657     case DW_OP_reg8:
658     case DW_OP_reg9:
659     case DW_OP_reg10:
660     case DW_OP_reg11:
661     case DW_OP_reg12:
662     case DW_OP_reg13:
663     case DW_OP_reg14:
664     case DW_OP_reg15:
665     case DW_OP_reg16:
666     case DW_OP_reg17:
667     case DW_OP_reg18:
668     case DW_OP_reg19:
669     case DW_OP_reg20:
670     case DW_OP_reg21:
671     case DW_OP_reg22:
672     case DW_OP_reg23:
673     case DW_OP_reg24:
674     case DW_OP_reg25:
675     case DW_OP_reg26:
676     case DW_OP_reg27:
677     case DW_OP_reg28:
678     case DW_OP_reg29:
679     case DW_OP_reg30:
680     case DW_OP_reg31:
681       reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
682       *(++sp) = registers.getRegister((int)reg);
683       if (log)
684         fprintf(stderr, "push reg %d\n", reg);
685       break;
686
687     case DW_OP_regx:
688       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
689       *(++sp) = registers.getRegister((int)reg);
690       if (log)
691         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
692       break;
693
694     case DW_OP_breg0:
695     case DW_OP_breg1:
696     case DW_OP_breg2:
697     case DW_OP_breg3:
698     case DW_OP_breg4:
699     case DW_OP_breg5:
700     case DW_OP_breg6:
701     case DW_OP_breg7:
702     case DW_OP_breg8:
703     case DW_OP_breg9:
704     case DW_OP_breg10:
705     case DW_OP_breg11:
706     case DW_OP_breg12:
707     case DW_OP_breg13:
708     case DW_OP_breg14:
709     case DW_OP_breg15:
710     case DW_OP_breg16:
711     case DW_OP_breg17:
712     case DW_OP_breg18:
713     case DW_OP_breg19:
714     case DW_OP_breg20:
715     case DW_OP_breg21:
716     case DW_OP_breg22:
717     case DW_OP_breg23:
718     case DW_OP_breg24:
719     case DW_OP_breg25:
720     case DW_OP_breg26:
721     case DW_OP_breg27:
722     case DW_OP_breg28:
723     case DW_OP_breg29:
724     case DW_OP_breg30:
725     case DW_OP_breg31:
726       reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
727       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
728       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
729       *(++sp) = (pint_t)(svalue);
730       if (log)
731         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
732       break;
733
734     case DW_OP_bregx:
735       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
736       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
737       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
738       *(++sp) = (pint_t)(svalue);
739       if (log)
740         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
741       break;
742
743     case DW_OP_fbreg:
744       _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
745       break;
746
747     case DW_OP_piece:
748       _LIBUNWIND_ABORT("DW_OP_piece not implemented");
749       break;
750
751     case DW_OP_deref_size:
752       // pop stack, dereference, push result
753       value = *sp--;
754       switch (addressSpace.get8(p++)) {
755       case 1:
756         value = addressSpace.get8(value);
757         break;
758       case 2:
759         value = addressSpace.get16(value);
760         break;
761       case 4:
762         value = addressSpace.get32(value);
763         break;
764       case 8:
765         value = (pint_t)addressSpace.get64(value);
766         break;
767       default:
768         _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
769       }
770       *(++sp) = value;
771       if (log)
772         fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
773       break;
774
775     case DW_OP_xderef_size:
776     case DW_OP_nop:
777     case DW_OP_push_object_addres:
778     case DW_OP_call2:
779     case DW_OP_call4:
780     case DW_OP_call_ref:
781     default:
782       _LIBUNWIND_ABORT("DWARF opcode not implemented");
783     }
784
785   }
786   if (log)
787     fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
788   return *sp;
789 }
790
791
792
793 } // namespace libunwind
794
795 #endif // __DWARF_INSTRUCTIONS_HPP__