Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: third_party/libc++abi/src/Unwind/DwarfInstructions.hpp

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

Powered by Google App Engine
This is Rietveld 408576698