00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tconfig.h"
00023 #include "tsystem.h"
00024 #include "dwarf2.h"
00025 #include "unwind.h"
00026 #include "unwind-pe.h"
00027 #include "unwind-dw2-fde.h"
00028 #include "gthr.h"
00029
00030
00031 #ifndef __USING_SJLJ_EXCEPTIONS__
00032
00033 #ifndef STACK_GROWS_DOWNWARD
00034 #define STACK_GROWS_DOWNWARD 0
00035 #else
00036 #undef STACK_GROWS_DOWNWARD
00037 #define STACK_GROWS_DOWNWARD 1
00038 #endif
00039
00040
00041
00042 #ifndef DWARF_FRAME_REGISTERS
00043 #define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
00044 #endif
00045
00046
00047 #ifndef PRE_GCC3_DWARF_FRAME_REGISTERS
00048 #define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
00049 #endif
00050
00051
00052 #ifndef MD_FROB_UPDATE_CONTEXT
00053 #define MD_FROB_UPDATE_CONTEXT(CTX, FS) do { } while (0)
00054 #endif
00055
00056
00057
00058
00059 struct _Unwind_Context
00060 {
00061 void *reg[DWARF_FRAME_REGISTERS+1];
00062 void *cfa;
00063 void *ra;
00064 void *lsda;
00065 struct dwarf_eh_bases bases;
00066 _Unwind_Word args_size;
00067 };
00068
00069
00070 static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS];
00071
00072
00073
00074
00075
00076 typedef struct
00077 {
00078
00079
00080 struct frame_state_reg_info
00081 {
00082 struct {
00083 union {
00084 _Unwind_Word reg;
00085 _Unwind_Sword offset;
00086 const unsigned char *exp;
00087 } loc;
00088 enum {
00089 REG_UNSAVED,
00090 REG_SAVED_OFFSET,
00091 REG_SAVED_REG,
00092 REG_SAVED_EXP,
00093 } how;
00094 } reg[DWARF_FRAME_REGISTERS+1];
00095
00096
00097 struct frame_state_reg_info *prev;
00098 } regs;
00099
00100
00101
00102 _Unwind_Sword cfa_offset;
00103 _Unwind_Word cfa_reg;
00104 const unsigned char *cfa_exp;
00105 enum {
00106 CFA_UNSET,
00107 CFA_REG_OFFSET,
00108 CFA_EXP,
00109 } cfa_how;
00110
00111
00112 void *pc;
00113
00114
00115 _Unwind_Personality_Fn personality;
00116 _Unwind_Sword data_align;
00117 _Unwind_Word code_align;
00118 unsigned char retaddr_column;
00119 unsigned char fde_encoding;
00120 unsigned char lsda_encoding;
00121 unsigned char saw_z;
00122 void *eh_ptr;
00123 } _Unwind_FrameState;
00124
00125
00126
00127 union unaligned
00128 {
00129 void *p;
00130 unsigned u2 __attribute__ ((mode (HI)));
00131 unsigned u4 __attribute__ ((mode (SI)));
00132 unsigned u8 __attribute__ ((mode (DI)));
00133 signed s2 __attribute__ ((mode (HI)));
00134 signed s4 __attribute__ ((mode (SI)));
00135 signed s8 __attribute__ ((mode (DI)));
00136 } __attribute__ ((packed));
00137
00138 static inline void *
00139 read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
00140
00141 static inline int
00142 read_1u (const void *p) { return *(const unsigned char *) p; }
00143
00144 static inline int
00145 read_1s (const void *p) { return *(const signed char *) p; }
00146
00147 static inline int
00148 read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
00149
00150 static inline int
00151 read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
00152
00153 static inline unsigned int
00154 read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
00155
00156 static inline int
00157 read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
00158
00159 static inline unsigned long
00160 read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
00161
00162 static inline unsigned long
00163 read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
00164
00165
00166
00167 inline _Unwind_Word
00168 _Unwind_GetGR (struct _Unwind_Context *context, int index)
00169 {
00170
00171 return * (_Unwind_Word *) context->reg[index];
00172 }
00173
00174
00175
00176 _Unwind_Word
00177 _Unwind_GetCFA (struct _Unwind_Context *context)
00178 {
00179 return (_Unwind_Word) context->cfa;
00180 }
00181
00182
00183
00184 inline void
00185 _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
00186 {
00187 * (_Unwind_Word *) context->reg[index] = val;
00188 }
00189
00190
00191
00192 inline _Unwind_Ptr
00193 _Unwind_GetIP (struct _Unwind_Context *context)
00194 {
00195 return (_Unwind_Ptr) context->ra;
00196 }
00197
00198
00199
00200 inline void
00201 _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
00202 {
00203 context->ra = (void *) val;
00204 }
00205
00206 void *
00207 _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
00208 {
00209 return context->lsda;
00210 }
00211
00212 _Unwind_Ptr
00213 _Unwind_GetRegionStart (struct _Unwind_Context *context)
00214 {
00215 return (_Unwind_Ptr) context->bases.func;
00216 }
00217
00218 void *
00219 _Unwind_FindEnclosingFunction (void *pc)
00220 {
00221 struct dwarf_eh_bases bases;
00222 struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
00223 if (fde)
00224 return bases.func;
00225 else
00226 return NULL;
00227 }
00228
00229 #ifndef __ia64__
00230 _Unwind_Ptr
00231 _Unwind_GetDataRelBase (struct _Unwind_Context *context)
00232 {
00233 return (_Unwind_Ptr) context->bases.dbase;
00234 }
00235
00236 _Unwind_Ptr
00237 _Unwind_GetTextRelBase (struct _Unwind_Context *context)
00238 {
00239 return (_Unwind_Ptr) context->bases.tbase;
00240 }
00241 #endif
00242
00243
00244
00245
00246
00247 static const unsigned char *
00248 extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
00249 _Unwind_FrameState *fs)
00250 {
00251 const unsigned char *aug = cie->augmentation;
00252 const unsigned char *p = aug + strlen (aug) + 1;
00253 const unsigned char *ret = NULL;
00254 _Unwind_Word utmp;
00255
00256
00257
00258 if (aug[0] == 'e' && aug[1] == 'h')
00259 {
00260 fs->eh_ptr = read_pointer (p);
00261 p += sizeof (void *);
00262 aug += 2;
00263 }
00264
00265
00266
00267 p = read_uleb128 (p, &fs->code_align);
00268 p = read_sleb128 (p, &fs->data_align);
00269 fs->retaddr_column = *p++;
00270 fs->lsda_encoding = DW_EH_PE_omit;
00271
00272
00273
00274
00275 if (*aug == 'z')
00276 {
00277 p = read_uleb128 (p, &utmp);
00278 ret = p + utmp;
00279
00280 fs->saw_z = 1;
00281 ++aug;
00282 }
00283
00284
00285 while (*aug != '\0')
00286 {
00287
00288 if (aug[0] == 'L')
00289 {
00290 fs->lsda_encoding = *p++;
00291 aug += 1;
00292 }
00293
00294
00295 else if (aug[0] == 'R')
00296 {
00297 fs->fde_encoding = *p++;
00298 aug += 1;
00299 }
00300
00301
00302 else if (aug[0] == 'P')
00303 {
00304 p = read_encoded_value (context, *p, p + 1,
00305 (_Unwind_Ptr *) &fs->personality);
00306 aug += 1;
00307 }
00308
00309
00310
00311 else
00312 return ret;
00313 }
00314
00315 return ret ? ret : p;
00316 }
00317
00318
00319
00320
00321
00322 static _Unwind_Word
00323 execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
00324 struct _Unwind_Context *context, _Unwind_Word initial)
00325 {
00326 _Unwind_Word stack[64];
00327 int stack_elt;
00328
00329 stack[0] = initial;
00330 stack_elt = 1;
00331
00332 while (op_ptr < op_end)
00333 {
00334 enum dwarf_location_atom op = *op_ptr++;
00335 _Unwind_Word result, reg, utmp;
00336 _Unwind_Sword offset, stmp;
00337
00338 switch (op)
00339 {
00340 case DW_OP_lit0:
00341 case DW_OP_lit1:
00342 case DW_OP_lit2:
00343 case DW_OP_lit3:
00344 case DW_OP_lit4:
00345 case DW_OP_lit5:
00346 case DW_OP_lit6:
00347 case DW_OP_lit7:
00348 case DW_OP_lit8:
00349 case DW_OP_lit9:
00350 case DW_OP_lit10:
00351 case DW_OP_lit11:
00352 case DW_OP_lit12:
00353 case DW_OP_lit13:
00354 case DW_OP_lit14:
00355 case DW_OP_lit15:
00356 case DW_OP_lit16:
00357 case DW_OP_lit17:
00358 case DW_OP_lit18:
00359 case DW_OP_lit19:
00360 case DW_OP_lit20:
00361 case DW_OP_lit21:
00362 case DW_OP_lit22:
00363 case DW_OP_lit23:
00364 case DW_OP_lit24:
00365 case DW_OP_lit25:
00366 case DW_OP_lit26:
00367 case DW_OP_lit27:
00368 case DW_OP_lit28:
00369 case DW_OP_lit29:
00370 case DW_OP_lit30:
00371 case DW_OP_lit31:
00372 result = op - DW_OP_lit0;
00373 break;
00374
00375 case DW_OP_addr:
00376 result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr);
00377 op_ptr += sizeof (void *);
00378 break;
00379
00380 case DW_OP_const1u:
00381 result = read_1u (op_ptr);
00382 op_ptr += 1;
00383 break;
00384 case DW_OP_const1s:
00385 result = read_1s (op_ptr);
00386 op_ptr += 1;
00387 break;
00388 case DW_OP_const2u:
00389 result = read_2u (op_ptr);
00390 op_ptr += 2;
00391 break;
00392 case DW_OP_const2s:
00393 result = read_2s (op_ptr);
00394 op_ptr += 2;
00395 break;
00396 case DW_OP_const4u:
00397 result = read_4u (op_ptr);
00398 op_ptr += 4;
00399 break;
00400 case DW_OP_const4s:
00401 result = read_4s (op_ptr);
00402 op_ptr += 4;
00403 break;
00404 case DW_OP_const8u:
00405 result = read_8u (op_ptr);
00406 op_ptr += 8;
00407 break;
00408 case DW_OP_const8s:
00409 result = read_8s (op_ptr);
00410 op_ptr += 8;
00411 break;
00412 case DW_OP_constu:
00413 op_ptr = read_uleb128 (op_ptr, &result);
00414 break;
00415 case DW_OP_consts:
00416 op_ptr = read_sleb128 (op_ptr, &stmp);
00417 result = stmp;
00418 break;
00419
00420 case DW_OP_reg0:
00421 case DW_OP_reg1:
00422 case DW_OP_reg2:
00423 case DW_OP_reg3:
00424 case DW_OP_reg4:
00425 case DW_OP_reg5:
00426 case DW_OP_reg6:
00427 case DW_OP_reg7:
00428 case DW_OP_reg8:
00429 case DW_OP_reg9:
00430 case DW_OP_reg10:
00431 case DW_OP_reg11:
00432 case DW_OP_reg12:
00433 case DW_OP_reg13:
00434 case DW_OP_reg14:
00435 case DW_OP_reg15:
00436 case DW_OP_reg16:
00437 case DW_OP_reg17:
00438 case DW_OP_reg18:
00439 case DW_OP_reg19:
00440 case DW_OP_reg20:
00441 case DW_OP_reg21:
00442 case DW_OP_reg22:
00443 case DW_OP_reg23:
00444 case DW_OP_reg24:
00445 case DW_OP_reg25:
00446 case DW_OP_reg26:
00447 case DW_OP_reg27:
00448 case DW_OP_reg28:
00449 case DW_OP_reg29:
00450 case DW_OP_reg30:
00451 case DW_OP_reg31:
00452 result = _Unwind_GetGR (context, op - DW_OP_reg0);
00453 break;
00454 case DW_OP_regx:
00455 op_ptr = read_uleb128 (op_ptr, ®);
00456 result = _Unwind_GetGR (context, reg);
00457 break;
00458
00459 case DW_OP_breg0:
00460 case DW_OP_breg1:
00461 case DW_OP_breg2:
00462 case DW_OP_breg3:
00463 case DW_OP_breg4:
00464 case DW_OP_breg5:
00465 case DW_OP_breg6:
00466 case DW_OP_breg7:
00467 case DW_OP_breg8:
00468 case DW_OP_breg9:
00469 case DW_OP_breg10:
00470 case DW_OP_breg11:
00471 case DW_OP_breg12:
00472 case DW_OP_breg13:
00473 case DW_OP_breg14:
00474 case DW_OP_breg15:
00475 case DW_OP_breg16:
00476 case DW_OP_breg17:
00477 case DW_OP_breg18:
00478 case DW_OP_breg19:
00479 case DW_OP_breg20:
00480 case DW_OP_breg21:
00481 case DW_OP_breg22:
00482 case DW_OP_breg23:
00483 case DW_OP_breg24:
00484 case DW_OP_breg25:
00485 case DW_OP_breg26:
00486 case DW_OP_breg27:
00487 case DW_OP_breg28:
00488 case DW_OP_breg29:
00489 case DW_OP_breg30:
00490 case DW_OP_breg31:
00491 op_ptr = read_sleb128 (op_ptr, &offset);
00492 result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset;
00493 break;
00494 case DW_OP_bregx:
00495 op_ptr = read_uleb128 (op_ptr, ®);
00496 op_ptr = read_sleb128 (op_ptr, &offset);
00497 result = _Unwind_GetGR (context, reg) + offset;
00498 break;
00499
00500 case DW_OP_dup:
00501 if (stack_elt < 1)
00502 abort ();
00503 result = stack[stack_elt - 1];
00504 break;
00505
00506 case DW_OP_drop:
00507 if (--stack_elt < 0)
00508 abort ();
00509 goto no_push;
00510
00511 case DW_OP_pick:
00512 offset = *op_ptr++;
00513 if (offset >= stack_elt - 1)
00514 abort ();
00515 result = stack[stack_elt - 1 - offset];
00516 break;
00517
00518 case DW_OP_over:
00519 if (stack_elt < 2)
00520 abort ();
00521 result = stack[stack_elt - 2];
00522 break;
00523
00524 case DW_OP_rot:
00525 {
00526 _Unwind_Word t1, t2, t3;
00527
00528 if (stack_elt < 3)
00529 abort ();
00530 t1 = stack[stack_elt - 1];
00531 t2 = stack[stack_elt - 2];
00532 t3 = stack[stack_elt - 3];
00533 stack[stack_elt - 1] = t2;
00534 stack[stack_elt - 2] = t3;
00535 stack[stack_elt - 3] = t1;
00536 goto no_push;
00537 }
00538
00539 case DW_OP_deref:
00540 case DW_OP_deref_size:
00541 case DW_OP_abs:
00542 case DW_OP_neg:
00543 case DW_OP_not:
00544 case DW_OP_plus_uconst:
00545
00546 if (--stack_elt < 0)
00547 abort ();
00548 result = stack[stack_elt];
00549
00550 switch (op)
00551 {
00552 case DW_OP_deref:
00553 {
00554 void *ptr = (void *) (_Unwind_Ptr) result;
00555 result = (_Unwind_Ptr) read_pointer (ptr);
00556 }
00557 break;
00558
00559 case DW_OP_deref_size:
00560 {
00561 void *ptr = (void *) (_Unwind_Ptr) result;
00562 switch (*op_ptr++)
00563 {
00564 case 1:
00565 result = read_1u (ptr);
00566 break;
00567 case 2:
00568 result = read_2u (ptr);
00569 break;
00570 case 4:
00571 result = read_4u (ptr);
00572 break;
00573 case 8:
00574 result = read_8u (ptr);
00575 break;
00576 default:
00577 abort ();
00578 }
00579 }
00580 break;
00581
00582 case DW_OP_abs:
00583 if ((_Unwind_Sword) result < 0)
00584 result = -result;
00585 break;
00586 case DW_OP_neg:
00587 result = -result;
00588 break;
00589 case DW_OP_not:
00590 result = ~result;
00591 break;
00592 case DW_OP_plus_uconst:
00593 op_ptr = read_uleb128 (op_ptr, &utmp);
00594 result += utmp;
00595 break;
00596
00597 default:
00598 abort ();
00599 }
00600 break;
00601
00602 case DW_OP_and:
00603 case DW_OP_div:
00604 case DW_OP_minus:
00605 case DW_OP_mod:
00606 case DW_OP_mul:
00607 case DW_OP_or:
00608 case DW_OP_plus:
00609 case DW_OP_le:
00610 case DW_OP_ge:
00611 case DW_OP_eq:
00612 case DW_OP_lt:
00613 case DW_OP_gt:
00614 case DW_OP_ne:
00615 {
00616
00617 _Unwind_Word first, second;
00618 if ((stack_elt -= 2) < 0)
00619 abort ();
00620 second = stack[stack_elt];
00621 first = stack[stack_elt + 1];
00622
00623 switch (op)
00624 {
00625 case DW_OP_and:
00626 result = second & first;
00627 break;
00628 case DW_OP_div:
00629 result = (_Unwind_Sword) second / (_Unwind_Sword) first;
00630 break;
00631 case DW_OP_minus:
00632 result = second - first;
00633 break;
00634 case DW_OP_mod:
00635 result = (_Unwind_Sword) second % (_Unwind_Sword) first;
00636 break;
00637 case DW_OP_mul:
00638 result = second * first;
00639 break;
00640 case DW_OP_or:
00641 result = second | first;
00642 break;
00643 case DW_OP_plus:
00644 result = second + first;
00645 break;
00646 case DW_OP_shl:
00647 result = second << first;
00648 break;
00649 case DW_OP_shr:
00650 result = second >> first;
00651 break;
00652 case DW_OP_shra:
00653 result = (_Unwind_Sword) second >> first;
00654 break;
00655 case DW_OP_xor:
00656 result = second ^ first;
00657 break;
00658 case DW_OP_le:
00659 result = (_Unwind_Sword) first <= (_Unwind_Sword) second;
00660 break;
00661 case DW_OP_ge:
00662 result = (_Unwind_Sword) first >= (_Unwind_Sword) second;
00663 break;
00664 case DW_OP_eq:
00665 result = (_Unwind_Sword) first == (_Unwind_Sword) second;
00666 break;
00667 case DW_OP_lt:
00668 result = (_Unwind_Sword) first < (_Unwind_Sword) second;
00669 break;
00670 case DW_OP_gt:
00671 result = (_Unwind_Sword) first > (_Unwind_Sword) second;
00672 break;
00673 case DW_OP_ne:
00674 result = (_Unwind_Sword) first != (_Unwind_Sword) second;
00675 break;
00676
00677 default:
00678 abort ();
00679 }
00680 }
00681 break;
00682
00683 case DW_OP_skip:
00684 offset = read_2s (op_ptr);
00685 op_ptr += 2;
00686 op_ptr += offset;
00687 goto no_push;
00688
00689 case DW_OP_bra:
00690 if (--stack_elt < 0)
00691 abort ();
00692 offset = read_2s (op_ptr);
00693 op_ptr += 2;
00694 if (stack[stack_elt] != 0)
00695 op_ptr += offset;
00696 goto no_push;
00697
00698 case DW_OP_nop:
00699 goto no_push;
00700
00701 default:
00702 abort ();
00703 }
00704
00705
00706 if ((size_t) stack_elt >= sizeof(stack)/sizeof(*stack))
00707 abort ();
00708 stack[stack_elt++] = result;
00709 no_push:;
00710 }
00711
00712
00713
00714 if (--stack_elt < 0)
00715 abort ();
00716 return stack[stack_elt];
00717 }
00718
00719
00720
00721
00722
00723
00724 static void
00725 execute_cfa_program (const unsigned char *insn_ptr,
00726 const unsigned char *insn_end,
00727 struct _Unwind_Context *context,
00728 _Unwind_FrameState *fs)
00729 {
00730 struct frame_state_reg_info *unused_rs = NULL;
00731
00732
00733 fs->regs.prev = NULL;
00734
00735
00736
00737
00738
00739
00740
00741
00742 while (insn_ptr < insn_end && fs->pc < context->ra)
00743 {
00744 unsigned char insn = *insn_ptr++;
00745 _Unwind_Word reg, utmp;
00746 _Unwind_Sword offset, stmp;
00747
00748 if ((insn & 0xc0) == DW_CFA_advance_loc)
00749 fs->pc += (insn & 0x3f) * fs->code_align;
00750 else if ((insn & 0xc0) == DW_CFA_offset)
00751 {
00752 reg = insn & 0x3f;
00753 insn_ptr = read_uleb128 (insn_ptr, &utmp);
00754 offset = (_Unwind_Sword) utmp * fs->data_align;
00755 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
00756 fs->regs.reg[reg].loc.offset = offset;
00757 }
00758 else if ((insn & 0xc0) == DW_CFA_restore)
00759 {
00760 reg = insn & 0x3f;
00761 fs->regs.reg[reg].how = REG_UNSAVED;
00762 }
00763 else switch (insn)
00764 {
00765 case DW_CFA_set_loc:
00766 insn_ptr = read_encoded_value (context, fs->fde_encoding,
00767 insn_ptr, (_Unwind_Ptr *) &fs->pc);
00768 break;
00769
00770 case DW_CFA_advance_loc1:
00771 fs->pc += read_1u (insn_ptr) * fs->code_align;
00772 insn_ptr += 1;
00773 break;
00774 case DW_CFA_advance_loc2:
00775 fs->pc += read_2u (insn_ptr) * fs->code_align;
00776 insn_ptr += 2;
00777 break;
00778 case DW_CFA_advance_loc4:
00779 fs->pc += read_4u (insn_ptr) * fs->code_align;
00780 insn_ptr += 4;
00781 break;
00782
00783 case DW_CFA_offset_extended:
00784 insn_ptr = read_uleb128 (insn_ptr, ®);
00785 insn_ptr = read_uleb128 (insn_ptr, &utmp);
00786 offset = (_Unwind_Sword) utmp * fs->data_align;
00787 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
00788 fs->regs.reg[reg].loc.offset = offset;
00789 break;
00790
00791 case DW_CFA_restore_extended:
00792 insn_ptr = read_uleb128 (insn_ptr, ®);
00793 fs->regs.reg[reg].how = REG_UNSAVED;
00794 break;
00795
00796 case DW_CFA_undefined:
00797 case DW_CFA_same_value:
00798 insn_ptr = read_uleb128 (insn_ptr, ®);
00799 break;
00800
00801 case DW_CFA_nop:
00802 break;
00803
00804 case DW_CFA_register:
00805 {
00806 _Unwind_Word reg2;
00807 insn_ptr = read_uleb128 (insn_ptr, ®);
00808 insn_ptr = read_uleb128 (insn_ptr, ®2);
00809 fs->regs.reg[reg].how = REG_SAVED_REG;
00810 fs->regs.reg[reg].loc.reg = reg2;
00811 }
00812 break;
00813
00814 case DW_CFA_remember_state:
00815 {
00816 struct frame_state_reg_info *new_rs;
00817 if (unused_rs)
00818 {
00819 new_rs = unused_rs;
00820 unused_rs = unused_rs->prev;
00821 }
00822 else
00823 new_rs = __builtin_alloca (sizeof (struct frame_state_reg_info));
00824
00825 *new_rs = fs->regs;
00826 fs->regs.prev = new_rs;
00827 }
00828 break;
00829
00830 case DW_CFA_restore_state:
00831 {
00832 struct frame_state_reg_info *old_rs = fs->regs.prev;
00833 fs->regs = *old_rs;
00834 old_rs->prev = unused_rs;
00835 unused_rs = old_rs;
00836 }
00837 break;
00838
00839 case DW_CFA_def_cfa:
00840 insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
00841 insn_ptr = read_uleb128 (insn_ptr, &utmp);
00842 fs->cfa_offset = utmp;
00843 fs->cfa_how = CFA_REG_OFFSET;
00844 break;
00845
00846 case DW_CFA_def_cfa_register:
00847 insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
00848 fs->cfa_how = CFA_REG_OFFSET;
00849 break;
00850
00851 case DW_CFA_def_cfa_offset:
00852 insn_ptr = read_uleb128 (insn_ptr, &utmp);
00853 fs->cfa_offset = utmp;
00854
00855 break;
00856
00857 case DW_CFA_def_cfa_expression:
00858 fs->cfa_exp = insn_ptr;
00859 fs->cfa_how = CFA_EXP;
00860 insn_ptr = read_uleb128 (insn_ptr, &utmp);
00861 insn_ptr += utmp;
00862 break;
00863
00864 case DW_CFA_expression:
00865 insn_ptr = read_uleb128 (insn_ptr, ®);
00866 fs->regs.reg[reg].how = REG_SAVED_EXP;
00867 fs->regs.reg[reg].loc.exp = insn_ptr;
00868 insn_ptr = read_uleb128 (insn_ptr, &utmp);
00869 insn_ptr += utmp;
00870 break;
00871
00872
00873 case DW_CFA_offset_extended_sf:
00874 insn_ptr = read_uleb128 (insn_ptr, ®);
00875 insn_ptr = read_sleb128 (insn_ptr, &stmp);
00876 offset = stmp * fs->data_align;
00877 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
00878 fs->regs.reg[reg].loc.offset = offset;
00879 break;
00880
00881 case DW_CFA_def_cfa_sf:
00882 insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
00883 insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
00884 fs->cfa_how = CFA_REG_OFFSET;
00885 break;
00886
00887 case DW_CFA_def_cfa_offset_sf:
00888 insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
00889
00890 break;
00891
00892 case DW_CFA_GNU_window_save:
00893
00894 for (reg = 16; reg < 32; ++reg)
00895 {
00896 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
00897 fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *);
00898 }
00899 break;
00900
00901 case DW_CFA_GNU_args_size:
00902 insn_ptr = read_uleb128 (insn_ptr, &context->args_size);
00903 break;
00904
00905 case DW_CFA_GNU_negative_offset_extended:
00906
00907
00908 insn_ptr = read_uleb128 (insn_ptr, ®);
00909 insn_ptr = read_uleb128 (insn_ptr, &utmp);
00910 offset = (_Unwind_Word) utmp * fs->data_align;
00911 fs->regs.reg[reg].how = REG_SAVED_OFFSET;
00912 fs->regs.reg[reg].loc.offset = -offset;
00913 break;
00914
00915 default:
00916 abort ();
00917 }
00918 }
00919 }
00920
00921
00922
00923
00924
00925
00926 static _Unwind_Reason_Code
00927 uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
00928 {
00929 struct dwarf_fde *fde;
00930 struct dwarf_cie *cie;
00931 const unsigned char *aug, *insn, *end;
00932
00933 memset (fs, 0, sizeof (*fs));
00934 context->args_size = 0;
00935 context->lsda = 0;
00936
00937 fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
00938 if (fde == NULL)
00939 {
00940
00941
00942
00943 #ifdef MD_FALLBACK_FRAME_STATE_FOR
00944 MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
00945 return _URC_END_OF_STACK;
00946 success:
00947 return _URC_NO_REASON;
00948 #else
00949 return _URC_END_OF_STACK;
00950 #endif
00951 }
00952
00953 fs->pc = context->bases.func;
00954
00955 cie = get_cie (fde);
00956 insn = extract_cie_info (cie, context, fs);
00957 if (insn == NULL)
00958
00959 return _URC_FATAL_PHASE1_ERROR;
00960
00961
00962 end = (unsigned char *) next_fde ((struct dwarf_fde *) cie);
00963 execute_cfa_program (insn, end, context, fs);
00964
00965
00966 aug = (unsigned char *) fde + sizeof (*fde);
00967 aug += 2 * size_of_encoded_value (fs->fde_encoding);
00968 insn = NULL;
00969 if (fs->saw_z)
00970 {
00971 _Unwind_Word i;
00972 aug = read_uleb128 (aug, &i);
00973 insn = aug + i;
00974 }
00975 if (fs->lsda_encoding != DW_EH_PE_omit)
00976 aug = read_encoded_value (context, fs->lsda_encoding, aug,
00977 (_Unwind_Ptr *) &context->lsda);
00978
00979
00980 if (insn == NULL)
00981 insn = aug;
00982 end = (unsigned char *) next_fde (fde);
00983 execute_cfa_program (insn, end, context, fs);
00984
00985 return _URC_NO_REASON;
00986 }
00987
00988 typedef struct frame_state
00989 {
00990 void *cfa;
00991 void *eh_ptr;
00992 long cfa_offset;
00993 long args_size;
00994 long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
00995 unsigned short cfa_reg;
00996 unsigned short retaddr_column;
00997 char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1];
00998 } frame_state;
00999
01000
01001 typedef struct frame_state_296
01002 {
01003 frame_state state;
01004 long base_offset;
01005 char indirect;
01006 } frame_state_296;
01007
01008
01009
01010
01011
01012 #if defined(__linux__) && defined(__sparc__) && !defined(__arch64__)
01013
01014
01015 asm (" .text \n\
01016 .globl __frame_state_for \n\
01017 .type __frame_state_for, #function \n\
01018 __frame_state_for: \n\
01019 mov %fp, %o2 \n\
01020 b ___frame_state_for \n\
01021 mov %i0, %o3 \n\
01022 ");
01023
01024 static struct frame_state *
01025 ___frame_state_for (void *pc_target, struct frame_state *state_in, void *pfp,
01026 int i0);
01027
01028 static struct frame_state *
01029 ___frame_state_for (void *pc_target, struct frame_state *state_in, void *pfp,
01030 int i0)
01031 #elif defined(__linux__) && defined(__alpha__)
01032 struct frame_state *
01033 __frame_state_for (void *pc_target, struct frame_state *state_in, long a2);
01034
01035 struct frame_state *
01036 __frame_state_for (void *pc_target, struct frame_state *state_in, long a2)
01037 #else
01038 struct frame_state *
01039 __frame_state_for (void *pc_target, struct frame_state *state_in);
01040
01041 struct frame_state *
01042 __frame_state_for (void *pc_target, struct frame_state *state_in)
01043 #endif
01044 {
01045 struct _Unwind_Context context;
01046 _Unwind_FrameState fs;
01047 int reg;
01048
01049 memset (&context, 0, sizeof (struct _Unwind_Context));
01050 context.ra = pc_target + 1;
01051
01052 if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
01053 return 0;
01054
01055
01056
01057 if (fs.cfa_how == CFA_EXP)
01058 return 0;
01059
01060 for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++)
01061 {
01062 state_in->saved[reg] = fs.regs.reg[reg].how;
01063 switch (state_in->saved[reg])
01064 {
01065 case REG_SAVED_REG:
01066 state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg;
01067 break;
01068 case REG_SAVED_OFFSET:
01069 state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset;
01070 break;
01071 default:
01072 state_in->reg_or_offset[reg] = 0;
01073 break;
01074 }
01075 }
01076
01077 state_in->cfa_offset = fs.cfa_offset;
01078 state_in->cfa_reg = fs.cfa_reg;
01079 state_in->retaddr_column = fs.retaddr_column;
01080 state_in->args_size = context.args_size;
01081 state_in->eh_ptr = fs.eh_ptr;
01082
01083 #ifdef __linux__
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095 # ifdef __i386__
01096 {
01097 unsigned long pbp, bp;
01098 unsigned char *ppc;
01099
01100 asm ("movl (%%ebp), %0; movl 4(%%ebp), %1; movl %%ebp, %2"
01101 : "=r" (pbp), "=r" (ppc), "=r" (bp));
01102 if (pbp < (unsigned long)state_in && pbp - bp == 0x40)
01103
01104
01105
01106 {
01107 unsigned char *end;
01108 int indirect = 0;
01109
01110
01111
01112 for (end = ppc + 512; ppc < end && *ppc != 0xc3 && indirect < 2;
01113 ppc++)
01114 {
01115 if (*ppc == 0x74 && ppc[1] == 0)
01116 indirect++;
01117 else if (*ppc == 0x70)
01118 indirect++;
01119 }
01120 if (indirect == 2)
01121 {
01122 ((frame_state_296 *) state_in)->base_offset = 0;
01123 ((frame_state_296 *) state_in)->indirect = 0;
01124 }
01125 }
01126 }
01127 # elif defined(__sparc__) && !defined(__arch64__)
01128 if (pfp < (unsigned long)state_in && i0 == 0)
01129
01130
01131
01132
01133 {
01134 unsigned int *ppc, *end;
01135 int indirect = 0;
01136
01137 ppc = (unsigned int *) __builtin_return_address (0);
01138
01139
01140
01141 for (end = ppc + 128; ppc < end && indirect < 2
01142 && (*ppc | 0x00080000) != 0x81cfe008; ppc++)
01143 switch (*ppc & 0xc1b83fff)
01144 {
01145 case 0xc0082218:
01146 case 0xc0002214:
01147 indirect++;
01148 break;
01149 }
01150 if (indirect == 2)
01151 {
01152 ((frame_state_296 *) state_in)->base_offset = 0;
01153 ((frame_state_296 *) state_in)->indirect = 0;
01154 }
01155 }
01156 # elif defined(__alpha__)
01157 if ((long)state_in == a2)
01158
01159
01160 {
01161 unsigned int *ppc, *end;
01162 int indirect = 0;
01163
01164 ppc = (unsigned int *) __builtin_return_address (0);
01165
01166
01167 for (end = ppc + 128; ppc < end && indirect < 2
01168 && *ppc != 0x6bfa8001; ppc++)
01169 switch (*ppc & 0xfc00ffff)
01170 {
01171 case 0xa4000270:
01172 case 0xa0000278:
01173 case 0xa8000278:
01174 indirect++;
01175 break;
01176 }
01177 if (indirect == 2)
01178 {
01179 ((frame_state_296 *) state_in)->base_offset = 0;
01180 ((frame_state_296 *) state_in)->indirect = 0;
01181 }
01182 }
01183 # endif
01184 #endif
01185
01186 return state_in;
01187 }
01188
01189 static void
01190 uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
01191 {
01192 struct _Unwind_Context orig_context = *context;
01193 void *cfa;
01194 long i;
01195
01196 #ifdef EH_RETURN_STACKADJ_RTX
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 _Unwind_Word tmp_sp;
01213
01214 if (!orig_context.reg[__builtin_dwarf_sp_column ()])
01215 {
01216 tmp_sp = (_Unwind_Ptr) context->cfa;
01217 orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
01218 }
01219 context->reg[__builtin_dwarf_sp_column ()] = NULL;
01220 #endif
01221
01222
01223 switch (fs->cfa_how)
01224 {
01225 case CFA_REG_OFFSET:
01226 cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (&orig_context, fs->cfa_reg);
01227 cfa += fs->cfa_offset;
01228 break;
01229
01230 case CFA_EXP:
01231 {
01232 const unsigned char *exp = fs->cfa_exp;
01233 _Unwind_Word len;
01234
01235 exp = read_uleb128 (exp, &len);
01236 cfa = (void *) (_Unwind_Ptr)
01237 execute_stack_op (exp, exp + len, &orig_context, 0);
01238 break;
01239 }
01240
01241 default:
01242 abort ();
01243 }
01244 context->cfa = cfa;
01245
01246
01247 for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i)
01248 switch (fs->regs.reg[i].how)
01249 {
01250 case REG_UNSAVED:
01251 break;
01252
01253 case REG_SAVED_OFFSET:
01254 context->reg[i] = cfa + fs->regs.reg[i].loc.offset;
01255 break;
01256
01257 case REG_SAVED_REG:
01258 context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg];
01259 break;
01260
01261 case REG_SAVED_EXP:
01262 {
01263 const unsigned char *exp = fs->regs.reg[i].loc.exp;
01264 _Unwind_Word len;
01265 _Unwind_Ptr val;
01266
01267 exp = read_uleb128 (exp, &len);
01268 val = execute_stack_op (exp, exp + len, &orig_context,
01269 (_Unwind_Ptr) cfa);
01270 context->reg[i] = (void *) val;
01271 }
01272 break;
01273 }
01274
01275 MD_FROB_UPDATE_CONTEXT (context, fs);
01276 }
01277
01278
01279
01280
01281
01282
01283 static void
01284 uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
01285 {
01286 uw_update_context_1 (context, fs);
01287
01288
01289
01290 context->ra = __builtin_extract_return_addr
01291 ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column));
01292 }
01293
01294
01295
01296
01297 #define uw_init_context(CONTEXT) \
01298 do \
01299 { \
01300
01301 \
01302 __builtin_unwind_init (); \
01303 uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \
01304 __builtin_return_address (0)); \
01305 } \
01306 while (0)
01307
01308 static void
01309 uw_init_context_1 (struct _Unwind_Context *context,
01310 void *outer_cfa, void *outer_ra)
01311 {
01312 void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
01313 _Unwind_FrameState fs;
01314 _Unwind_Word sp_slot;
01315
01316 memset (context, 0, sizeof (struct _Unwind_Context));
01317 context->ra = ra;
01318
01319 if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
01320 abort ();
01321
01322
01323 sp_slot = (_Unwind_Ptr) outer_cfa;
01324 context->reg[__builtin_dwarf_sp_column ()] = &sp_slot;
01325 fs.cfa_how = CFA_REG_OFFSET;
01326 fs.cfa_reg = __builtin_dwarf_sp_column ();
01327 fs.cfa_offset = 0;
01328
01329 uw_update_context_1 (context, &fs);
01330
01331
01332
01333
01334 context->ra = __builtin_extract_return_addr (outer_ra);
01335 }
01336
01337
01338
01339
01340
01341
01342 #define uw_install_context(CURRENT, TARGET) \
01343 do \
01344 { \
01345 long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
01346 void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
01347 __builtin_eh_return (offset, handler); \
01348 } \
01349 while (0)
01350
01351 static inline void
01352 init_dwarf_reg_size_table (void)
01353 {
01354 __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
01355 }
01356
01357 static long
01358 uw_install_context_1 (struct _Unwind_Context *current,
01359 struct _Unwind_Context *target)
01360 {
01361 long i;
01362
01363 #if __GTHREADS
01364 {
01365 static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
01366 if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
01367 || dwarf_reg_size_table[0] == 0)
01368 init_dwarf_reg_size_table ();
01369 }
01370 #else
01371 if (dwarf_reg_size_table[0] == 0)
01372 init_dwarf_reg_size_table ();
01373 #endif
01374
01375 for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
01376 {
01377 void *c = current->reg[i];
01378 void *t = target->reg[i];
01379 if (t && c && t != c)
01380 memcpy (c, t, dwarf_reg_size_table[i]);
01381 }
01382
01383 #ifdef EH_RETURN_STACKADJ_RTX
01384 {
01385 void *target_cfa;
01386
01387
01388 if (target->reg[__builtin_dwarf_sp_column ()])
01389 target_cfa = (void *)(_Unwind_Ptr)
01390 _Unwind_GetGR (target, __builtin_dwarf_sp_column ());
01391 else
01392 target_cfa = target->cfa;
01393
01394
01395 if (STACK_GROWS_DOWNWARD)
01396 return target_cfa - current->cfa + target->args_size;
01397 else
01398 return current->cfa - target_cfa - target->args_size;
01399 }
01400 #else
01401 return 0;
01402 #endif
01403 }
01404
01405 static inline _Unwind_Ptr
01406 uw_identify_context (struct _Unwind_Context *context)
01407 {
01408 return _Unwind_GetIP (context);
01409 }
01410
01411
01412 #include "unwind.inc"
01413
01414 #endif