📄 unwind-ia64.c
字号:
int body = (code & 0x20) != 0; unw_word rlen; rlen = (code & 0x1f); UNW_DEC_PROLOGUE(R1, body, rlen, arg); return dp;}static unsigned char *unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg){ unsigned char byte1, mask, grsave; unw_word rlen; byte1 = *dp++; mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); grsave = (byte1 & 0x7f); rlen = unw_decode_uleb128 (&dp); UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg); return dp;}static unsigned char *unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg){ unw_word rlen; rlen = unw_decode_uleb128 (&dp); UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg); return dp;}static unsigned char *unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg){ unsigned char brmask = (code & 0x1f); UNW_DEC_BR_MEM(P1, brmask, arg); return dp;}static unsigned char *unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg){ if ((code & 0x10) == 0) { unsigned char byte1 = *dp++; UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1), (byte1 & 0x7f), arg); } else if ((code & 0x08) == 0) { unsigned char byte1 = *dp++, r, dst; r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); dst = (byte1 & 0x7f); switch (r) { case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break; case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break; case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break; case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break; case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break; case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break; case 6: UNW_DEC_RP_BR(P3, dst, arg); break; case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break; case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break; case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break; case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break; case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break; default: UNW_DEC_BAD_CODE(r); break; } } else if ((code & 0x7) == 0) UNW_DEC_SPILL_MASK(P4, dp, arg); else if ((code & 0x7) == 1) { unw_word grmask, frmask, byte1, byte2, byte3; byte1 = *dp++; byte2 = *dp++; byte3 = *dp++; grmask = ((byte1 >> 4) & 0xf); frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3; UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg); } else UNW_DEC_BAD_CODE(code); return dp;}static unsigned char *unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg){ int gregs = (code & 0x10) != 0; unsigned char mask = (code & 0x0f); if (gregs) UNW_DEC_GR_MEM(P6, mask, arg); else UNW_DEC_FR_MEM(P6, mask, arg); return dp;}static unsigned char *unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg){ unsigned char r, byte1, byte2; unw_word t, size; if ((code & 0x10) == 0) { r = (code & 0xf); t = unw_decode_uleb128 (&dp); switch (r) { case 0: size = unw_decode_uleb128 (&dp); UNW_DEC_MEM_STACK_F(P7, t, size, arg); break; case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break; case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break; case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break; case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break; case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break; case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break; case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break; case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break; case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break; case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break; case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break; case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break; case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break; case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break; case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break; default: UNW_DEC_BAD_CODE(r); break; } } else { switch (code & 0xf) { case 0x0: /* p8 */ { r = *dp++; t = unw_decode_uleb128 (&dp); switch (r) { case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break; case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break; case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break; case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break; case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break; case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break; case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break; case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break; case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break; case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break; case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break; case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break; case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break; case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break; case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break; case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break; case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break; case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break; case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break; default: UNW_DEC_BAD_CODE(r); break; } } break; case 0x1: byte1 = *dp++; byte2 = *dp++; UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg); break; case 0xf: /* p10 */ byte1 = *dp++; byte2 = *dp++; UNW_DEC_ABI(P10, byte1, byte2, arg); break; case 0x9: return unw_decode_x1 (dp, code, arg); case 0xa: return unw_decode_x2 (dp, code, arg); case 0xb: return unw_decode_x3 (dp, code, arg); case 0xc: return unw_decode_x4 (dp, code, arg); default: UNW_DEC_BAD_CODE(code); break; } } return dp;}static unsigned char *unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg){ unw_word label = (code & 0x1f); if ((code & 0x20) != 0) UNW_DEC_COPY_STATE(B1, label, arg); else UNW_DEC_LABEL_STATE(B1, label, arg); return dp;}static unsigned char *unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg){ unw_word t; t = unw_decode_uleb128 (&dp); UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg); return dp;}static unsigned char *unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg){ unw_word t, ecount, label; if ((code & 0x10) == 0) { t = unw_decode_uleb128 (&dp); ecount = unw_decode_uleb128 (&dp); UNW_DEC_EPILOGUE(B3, t, ecount, arg); } else if ((code & 0x07) == 0) { label = unw_decode_uleb128 (&dp); if ((code & 0x08) != 0) UNW_DEC_COPY_STATE(B4, label, arg); else UNW_DEC_LABEL_STATE(B4, label, arg); } else switch (code & 0x7) { case 1: return unw_decode_x1 (dp, code, arg); case 2: return unw_decode_x2 (dp, code, arg); case 3: return unw_decode_x3 (dp, code, arg); case 4: return unw_decode_x4 (dp, code, arg); default: UNW_DEC_BAD_CODE(code); break; } return dp;}typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);static const unw_decoder unw_decode_table[2][8] ={ /* prologue table: */ { unw_decode_r1, /* 0 */ unw_decode_r1, unw_decode_r2, unw_decode_r3, unw_decode_p1, /* 4 */ unw_decode_p2_p5, unw_decode_p6, unw_decode_p7_p10 }, { unw_decode_r1, /* 0 */ unw_decode_r1, unw_decode_r2, unw_decode_r3, unw_decode_b1, /* 4 */ unw_decode_b1, unw_decode_b2, unw_decode_b3_x4 }};/* * Decode one descriptor and return address of next descriptor. */static inline unsigned char *unw_decode (unsigned char *dp, int inside_body, void *arg){ unw_decoder decoder; unsigned char code; code = *dp++; decoder = unw_decode_table[inside_body][code >> 5]; dp = (*decoder) (dp, code, arg); return dp;}/* RSE helper functions. */static inline unsigned longia64_rse_slot_num (unsigned long *addr){ return (((unsigned long) addr) >> 3) & 0x3f;}/* Return TRUE if ADDR is the address of an RNAT slot. */static inline unsigned longia64_rse_is_rnat_slot (unsigned long *addr){ return ia64_rse_slot_num (addr) == 0x3f;}/* Returns the address of the RNAT slot that covers the slot at address SLOT_ADDR. */static inline unsigned long *ia64_rse_rnat_addr (unsigned long *slot_addr){ return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));}/* Calcuate the number of registers in the dirty partition starting at BSPSTORE with a size of DIRTY bytes. This isn't simply DIRTY divided by eight because the 64th slot is used to store ar.rnat. */static inline unsigned longia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp){ unsigned long slots = (bsp - bspstore); return slots - (ia64_rse_slot_num (bspstore) + slots)/0x40;}/* The inverse of the above: given bspstore and the number of registers, calculate ar.bsp. */static inline unsigned long *ia64_rse_skip_regs (unsigned long *addr, long num_regs){ long delta = ia64_rse_slot_num (addr) + num_regs; if (num_regs < 0) delta -= 0x3e; return addr + num_regs + delta/0x3f;}/* Unwind accessors. */static voidunw_access_gr (struct _Unwind_Context *info, int regnum, unsigned long *val, char *nat, int write){ unsigned long *addr, *nat_addr = 0, nat_mask = 0, dummy_nat; struct unw_ireg *ireg; if ((unsigned) regnum - 1 >= 127) abort (); if (regnum < 1) { nat_addr = addr = &dummy_nat; dummy_nat = 0; } else if (regnum < 32) { /* Access a non-stacked register. */ ireg = &info->ireg[regnum - 2]; addr = ireg->loc; if (addr) { nat_addr = addr + ireg->nat.off; switch (ireg->nat.type) { case UNW_NAT_VAL: /* Simulate getf.sig/setf.sig. */ if (write) { if (*nat) { /* Write NaTVal and be done with it. */ addr[0] = 0; addr[1] = 0x1fffe; return; } addr[1] = 0x1003e; } else if (addr[0] == 0 && addr[1] == 0x1ffe) { /* Return NaT and be done with it. */ *val = 0; *nat = 1; return; } /* FALLTHRU */ case UNW_NAT_NONE: dummy_nat = 0; nat_addr = &dummy_nat; break; case UNW_NAT_MEMSTK: nat_mask = 1UL << ((long) addr & 0x1f8)/8; break; case UNW_NAT_REGSTK: nat_addr = ia64_rse_rnat_addr (addr); if ((unsigned long) nat_addr >= info->regstk_top) nat_addr = &info->rnat; nat_mask = 1UL << ia64_rse_slot_num (addr); break; } } } else { /* Access a stacked register. */ addr = ia64_rse_skip_regs ((unsigned long *) info->bsp, regnum - 32); nat_addr = ia64_rse_rnat_addr (addr); if ((unsigned long) nat_addr >= info->regstk_top) nat_addr = &info->rnat; nat_mask = 1UL << ia64_rse_slot_num (addr); } if (write) { *addr = *val; if (*nat) *nat_addr |= nat_mask; else *nat_addr &= ~nat_mask; } else { *val = *addr; *nat = (*nat_addr & nat_mask) != 0; }}/* Get the value of register REG as saved in CONTEXT. */_Unwind_Word_Unwind_GetGR (struct _Unwind_Context *context, int index){ _Unwind_Word ret; char nat; if (index == 1) return context->gp; else if (index >= 15 && index <= 18) return context->eh_data[index - 15]; else unw_access_gr (context, index, &ret, &nat, 0); return ret;}/* Overwrite the saved value for register REG in CONTEXT with VAL. */void_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val){ char nat = 0; if (index == 1) context->gp = val; else if (index >= 15 && index <= 18) context->eh_data[index - 15] = val; else unw_access_gr (context, index, &val, &nat, 1);}/* Retrieve the return address for CONTEXT. */inline _Unwind_Ptr_Unwind_GetIP (struct _Unwind_Context *context){ return context->rp;}/* Overwrite the return address for CONTEXT with VAL. */inline void_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val){ context->rp = val;}void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context){ return context->lsda;}_Unwind_Ptr_Unwind_GetRegionStart (struct _Unwind_Context *context){ return context->region_start;}void *_Unwind_FindEnclosingFunction (void *pc){ struct unw_table_entry *ent; unsigned long segment_base, gp; ent = _Unwind_FindTableEntry (pc, &segment_base, &gp); if (ent == NULL) return NULL; else return (void *)(segment_base + ent->start_offset);}/* Get the value of the CFA as saved in CONTEXT. In GCC/Dwarf2 parlance, the CFA is the value of the stack pointer on entry; In IA-64 unwind parlance, this is the PSP. */_Unwind_Word_Unwind_GetCFA (struct _Unwind_Context *context){ return (_Unwind_Ptr) context->psp;}/* Get the value of the Backing Store Pointer as saved in CONTEXT. */_Unwind_Word_Unwind_GetBSP (struct _Unwind_Context *context){ return (_Unwind_Ptr) context->bsp;}static _Unwind_Reason_Codeuw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs){ struct unw_table_entry *ent; unsigned long *unw, header, length; unsigned char *insn, *insn_end; unsigned long segment_base; struct unw_reg_info *r; memset (fs, 0, sizeof (*fs)); for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r) r->when = UNW_WHEN_NEVER; context->lsda = 0; ent = _Unwind_FindTableEntry ((void *) context->rp, &segment_base, &context->gp); if (ent == NULL) { /* Couldn't find unwind info for this function. Try an os-specific fallback mechanism. This will necessarily not provide a personality routine or LSDA. */#ifdef MD_FALLBACK_FRAME_STATE_FOR MD_FALLBACK_FRAME_STATE_FOR (context, fs, success); /* [SCRA 11.4.1] A leaf function with no memory stack, no exception handlers, and which keeps the return value in B0 does not need an unwind table entry. This can only happen in the frame after unwinding through a signal handler. Avoid infinite looping by requiring that B0 != RP. */ if (context->br_loc[0] && *context->br_loc[0] != context->rp) { fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; fs->curr.reg[UNW_REG_RP].when = -1; fs->curr.reg[UNW_REG_RP].val = 0; goto success; } return _URC_END_OF_STACK; success: return _URC_NO_REASON;#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -