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