📄 unwind-ia64.c
字号:
return _URC_END_OF_STACK;#endif } context->region_start = ent->start_offset + segment_base; fs->when_target = (context->rp - context->region_start) / 16 * 3; unw = (unsigned long *) (ent->info_offset + segment_base); header = *unw; length = UNW_LENGTH (header); /* ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK. */ if (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header)) { fs->personality = *(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp); context->lsda = unw + length + 2; } insn = (unsigned char *) (unw + 1); insn_end = (unsigned char *) (unw + 1 + length); while (!fs->done && insn < insn_end) insn = unw_decode (insn, fs->in_body, fs); free_label_states (fs->labeled_states); free_state_stack (&fs->curr);#ifdef ENABLE_MALLOC_CHECKING if (reg_state_alloced || labeled_state_alloced) abort ();#endif /* If we're in the epilogue, sp has been restored and all values on the memory stack below psp also have been restored. */ if (fs->when_target > fs->epilogue_start) { struct unw_reg_info *r; fs->curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE; fs->curr.reg[UNW_REG_PSP].val = 0; for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r) if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10) || r->where == UNW_WHERE_SPREL) r->where = UNW_WHERE_NONE; } /* If RP did't get saved, generate entry for the return link register. */ if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target) { 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 = fs->return_link_reg; } return _URC_NO_REASON;}static voiduw_update_reg_address (struct _Unwind_Context *context, _Unwind_FrameState *fs, enum unw_register_index regno){ struct unw_reg_info *r = fs->curr.reg + regno; void *addr; unsigned long rval; if (r->where == UNW_WHERE_NONE || r->when >= fs->when_target) return; rval = r->val; switch (r->where) { case UNW_WHERE_GR: if (rval >= 32) addr = ia64_rse_skip_regs ((unsigned long *) context->bsp, rval - 32); else if (rval >= 2) addr = context->ireg[rval - 2].loc; else if (rval == 0) { static const unsigned long dummy; addr = (void *) &dummy; } else abort (); break; case UNW_WHERE_FR: if (rval >= 2 && rval < 32) addr = context->fr_loc[rval - 2]; else abort (); break; case UNW_WHERE_BR: /* Note that while RVAL can only be 1-5 from normal descriptors, we can want to look at B0, B6 and B7 due to having manually unwound a signal frame. */ if (rval < 8) addr = context->br_loc[rval]; else abort (); break; case UNW_WHERE_SPREL: addr = (void *)(context->sp + rval); break; case UNW_WHERE_PSPREL: addr = (void *)(context->psp + rval); break; default: abort (); } switch (regno) { case UNW_REG_R2 ... UNW_REG_R31: context->ireg[regno - UNW_REG_R2].loc = addr; switch (r->where) { case UNW_WHERE_GR: if (rval >= 32) { context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK; context->ireg[regno - UNW_REG_R2].nat.off = context->pri_unat_loc - (unsigned long *) addr; } else if (rval >= 2) { context->ireg[regno - UNW_REG_R2].nat = context->ireg[rval - 2].nat; } else if (rval == 0) { context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE; context->ireg[regno - UNW_REG_R2].nat.off = 0; } else abort (); break; case UNW_WHERE_FR: context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_VAL; context->ireg[regno - UNW_REG_R2].nat.off = 0; break; case UNW_WHERE_BR: context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE; context->ireg[regno - UNW_REG_R2].nat.off = 0; break; case UNW_WHERE_PSPREL: case UNW_WHERE_SPREL: context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK; context->ireg[regno - UNW_REG_R2].nat.off = context->pri_unat_loc - (unsigned long *) addr; break; default: abort (); } break; case UNW_REG_F2 ... UNW_REG_F31: context->fr_loc[regno - UNW_REG_F2] = addr; break; case UNW_REG_B1 ... UNW_REG_B5: context->br_loc[regno - UNW_REG_B0] = addr; break; case UNW_REG_BSP: context->bsp_loc = addr; break; case UNW_REG_BSPSTORE: context->bspstore_loc = addr; break; case UNW_REG_PFS: context->pfs_loc = addr; break; case UNW_REG_RP: context->rp = *(unsigned long *)addr; break; case UNW_REG_UNAT: context->unat_loc = addr; break; case UNW_REG_PR: context->pr = *(unsigned long *) addr; break; case UNW_REG_LC: context->lc_loc = addr; break; case UNW_REG_FPSR: context->fpsr_loc = addr; break; case UNW_REG_PSP: context->psp = *(unsigned long *)addr; break; default: abort (); }}static voiduw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs){ long i;#ifdef MD_HANDLE_UNWABI MD_HANDLE_UNWABI (context, fs);#endif context->sp = context->psp; /* First, set PSP. Subsequent instructions may depend on this value. */ if (fs->when_target > fs->curr.reg[UNW_REG_PSP].when) { if (fs->curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE) context->psp = context->psp + fs->curr.reg[UNW_REG_PSP].val; else uw_update_reg_address (context, fs, UNW_REG_PSP); } /* Determine the location of the primary UNaT. */ { int i; if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_GR].when) i = UNW_REG_PRI_UNAT_MEM; else if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when) i = UNW_REG_PRI_UNAT_GR; else if (fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when > fs->curr.reg[UNW_REG_PRI_UNAT_GR].when) i = UNW_REG_PRI_UNAT_MEM; else i = UNW_REG_PRI_UNAT_GR; uw_update_reg_address (context, fs, i); } /* Compute the addresses of all registers saved in this frame. */ for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i) uw_update_reg_address (context, fs, i); /* Unwind BSP for the local registers allocated this frame. */ /* ??? What to do with stored BSP or BSPSTORE registers. */ /* We assert that we are either at a call site, or we have just unwound through a signal frame. In either case pfs_loc is valid. */ if (!(fs -> no_reg_stack_frame)) { unsigned long pfs = *context->pfs_loc; unsigned long sol = (pfs >> 7) & 0x7f; context->bsp = (unsigned long) ia64_rse_skip_regs ((unsigned long *) context->bsp, -sol); }}/* Fill in CONTEXT for top-of-stack. The only valid registers at this level will be the return address and the CFA. Note that CFA = SP+16. */ #define uw_init_context(CONTEXT) \ do { \ /* ??? There is a whole lot o code in uw_install_context that \ tries to avoid spilling the entire machine state here. We \ should try to make that work again. */ \ __builtin_unwind_init(); \ uw_init_context_1 (CONTEXT, __builtin_ia64_bsp ()); \ } while (0)static voiduw_init_context_1 (struct _Unwind_Context *context, void *bsp){ void *rp = __builtin_extract_return_addr (__builtin_return_address (0)); /* Set psp to the caller's stack pointer. */ void *psp = __builtin_dwarf_cfa () - 16; _Unwind_FrameState fs; /* Flush the register stack to memory so that we can access it. */ __builtin_ia64_flushrs (); memset (context, 0, sizeof (struct _Unwind_Context)); context->bsp = context->regstk_top = (unsigned long) bsp; context->psp = (unsigned long) psp; context->rp = (unsigned long) rp; asm ("mov %0 = sp" : "=r" (context->sp)); asm ("mov %0 = pr" : "=r" (context->pr)); context->pri_unat_loc = &context->initial_unat; /* ??? */ /* ??? Get rnat. Don't we have to turn off the rse for that? */ if (uw_frame_state_for (context, &fs) != _URC_NO_REASON) abort (); uw_update_context (context, &fs);}/* Install (ie longjmp to) the contents of TARGET. */static void __attribute__((noreturn))uw_install_context (struct _Unwind_Context *current __attribute__((unused)), struct _Unwind_Context *target){ unsigned long ireg_buf[4], ireg_nat = 0, ireg_pr = 0; long i; /* Copy integer register data from the target context to a temporary buffer. Do this so that we can frob AR.UNAT to get the NaT bits for these registers set properly. */ for (i = 4; i <= 7; ++i) { char nat; void *t = target->ireg[i - 2].loc; if (t) { unw_access_gr (target, i, &ireg_buf[i - 4], &nat, 0); ireg_nat |= (long)nat << (((size_t)&ireg_buf[i - 4] >> 3) & 0x3f); /* Set p6 - p9. */ ireg_pr |= 4L << i; } } /* The value in uc_bsp that we've computed is that for the target function. The value that we install below will be adjusted by the BR.RET instruction based on the contents of AR.PFS. So we must unadjust that here. */ target->bsp = (unsigned long) ia64_rse_skip_regs ((unsigned long *)target->bsp, (*target->pfs_loc >> 7) & 0x7f); /* Provide assembly with the offsets into the _Unwind_Context. */ asm volatile ("uc_rnat = %0" : : "i"(offsetof (struct _Unwind_Context, rnat))); asm volatile ("uc_bsp = %0" : : "i"(offsetof (struct _Unwind_Context, bsp))); asm volatile ("uc_psp = %0" : : "i"(offsetof (struct _Unwind_Context, psp))); asm volatile ("uc_rp = %0" : : "i"(offsetof (struct _Unwind_Context, rp))); asm volatile ("uc_pr = %0" : : "i"(offsetof (struct _Unwind_Context, pr))); asm volatile ("uc_gp = %0" : : "i"(offsetof (struct _Unwind_Context, gp))); asm volatile ("uc_pfs_loc = %0" : : "i"(offsetof (struct _Unwind_Context, pfs_loc))); asm volatile ("uc_unat_loc = %0" : : "i"(offsetof (struct _Unwind_Context, unat_loc))); asm volatile ("uc_lc_loc = %0" : : "i"(offsetof (struct _Unwind_Context, lc_loc))); asm volatile ("uc_fpsr_loc = %0" : : "i"(offsetof (struct _Unwind_Context, fpsr_loc))); asm volatile ("uc_eh_data = %0" : : "i"(offsetof (struct _Unwind_Context, eh_data))); asm volatile ("uc_br_loc = %0" : : "i"(offsetof (struct _Unwind_Context, br_loc))); asm volatile ("uc_fr_loc = %0" : : "i"(offsetof (struct _Unwind_Context, fr_loc))); asm volatile ( /* Load up call-saved non-window integer registers from ireg_buf. */ "add r20 = 8, %1 \n\t" "mov ar.unat = %2 \n\t" "mov pr = %3, 0x3c0 \n\t" ";; \n\t" "(p6) ld8.fill r4 = [%1] \n\t" "(p7) ld8.fill r5 = [r20] \n\t" "add r21 = uc_br_loc + 16, %0 \n\t" "adds %1 = 16, %1 \n\t" "adds r20 = 16, r20 \n\t" ";; \n\t" "(p8) ld8.fill r6 = [%1] \n\t" "(p9) ld8.fill r7 = [r20] \n\t" "add r20 = uc_br_loc + 8, %0 \n\t" ";; \n\t" /* Load up call-saved branch registers. */ "ld8 r22 = [r20], 16 \n\t" "ld8 r23 = [r21], 16 \n\t" ";; \n\t" "ld8 r24 = [r20], 16 \n\t" "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 32)\n\t" ";; \n\t" "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 40)\n\t" "ld8 r27 = [r21], 24 \n\t" "cmp.ne p6, p0 = r0, r22 \n\t" ";; \n\t" "ld8 r28 = [r20], 8 \n\t" "(p6) ld8 r22 = [r22] \n\t" "cmp.ne p7, p0 = r0, r23 \n\t" ";; \n\t" "(p7) ld8 r23 = [r23] \n\t" "cmp.ne p8, p0 = r0, r24 \n\t" ";; \n\t" "(p8) ld8 r24 = [r24] \n\t" "(p6) mov b1 = r22 \n\t" "cmp.ne p9, p0 = r0, r25 \n\t" ";; \n\t" "(p9) ld8 r25 = [r25] \n\t" "(p7) mov b2 = r23 \n\t" "cmp.ne p6, p0 = r0, r26 \n\t" ";; \n\t" "(p6) ld8 r26 = [r26] \n\t" "(p8) mov b3 = r24 \n\t" "cmp.ne p7, p0 = r0, r27 \n\t" ";; \n\t" /* Load up call-saved fp registers. */ "(p7) ldf.fill f2 = [r27] \n\t" "(p9) mov b4 = r25 \n\t" "cmp.ne p8, p0 = r0, r28 \n\t" ";; \n\t" "(p8) ldf.fill f3 = [r28] \n\t" "(p6) mov b5 = r26 \n\t" ";; \n\t" "ld8 r29 = [r20], 16*8 - 4*8 \n\t" "ld8 r30 = [r21], 17*8 - 5*8 \n\t" ";; \n\t" "ld8 r22 = [r20], 16 \n\t" "ld8 r23 = [r21], 16 \n\t" ";; \n\t" "ld8 r24 = [r20], 16 \n\t" "ld8 r25 = [r21] \n\t" "cmp.ne p6, p0 = r0, r29 \n\t" ";; \n\t" "ld8 r26 = [r20], 8 \n\t" "(p6) ldf.fill f4 = [r29] \n\t" "cmp.ne p7, p0 = r0, r30 \n\t" ";; \n\t" "ld8 r27 = [r20], 8 \n\t" "(p7) ldf.fill f5 = [r30] \n\t" "cmp.ne p6, p0 = r0, r22 \n\t" ";; \n\t" "ld8 r28 = [r20], 8 \n\t" "(p6) ldf.fill f16 = [r22] \n\t" "cmp.ne p7, p0 = r0, r23 \n\t" ";; \n\t" "ld8 r29 = [r20], 8 \n\t" "(p7) ldf.fill f17 = [r23] \n\t" "cmp.ne p6, p0 = r0, r24 \n\t" ";; \n\t" "ld8 r22 = [r20], 8 \n\t" "(p6) ldf.fill f18 = [r24] \n\t" "cmp.ne p7, p0 = r0, r25 \n\t" ";; \n\t" "ld8 r23 = [r20], 8 \n\t" "(p7) ldf.fill f19 = [r25] \n\t" "cmp.ne p6, p0 = r0, r26 \n\t" ";; \n\t" "ld8 r24 = [r20], 8 \n\t" "(p6) ldf.fill f20 = [r26] \n\t" "cmp.ne p7, p0 = r0, r27 \n\t" ";; \n\t" "ld8 r25 = [r20], 8 \n\t" "(p7) ldf.fill f21 = [r27] \n\t" "cmp.ne p6, p0 = r0, r28 \n\t" ";; \n\t" "ld8 r26 = [r20], 8 \n\t" "(p6) ldf.fill f22 = [r28] \n\t" "cmp.ne p7, p0 = r0, r29 \n\t" ";; \n\t" "ld8 r27 = [r20], 8 \n\t" ";; \n\t" "ld8 r28 = [r20], 8 \n\t" "(p7) ldf.fill f23 = [r29] \n\t" "cmp.ne p6, p0 = r0, r22 \n\t" ";; \n\t" "ld8 r29 = [r20], 8 \n\t" "(p6) ldf.fill f24 = [r22] \n\t" "cmp.ne p7, p0 = r0, r23 \n\t" ";; \n\t" "(p7) ldf.fill f25 = [r23] \n\t" "cmp.ne p6, p0 = r0, r24 \n\t" "cmp.ne p7, p0 = r0, r25 \n\t" ";; \n\t" "(p6) ldf.fill f26 = [r24] \n\t" "(p7) ldf.fill f27 = [r25] \n\t" "cmp.ne p6, p0 = r0, r26 \n\t" ";; \n\t" "(p6) ldf.fill f28 = [r26] \n\t" "cmp.ne p7, p0 = r0, r27 \n\t" "cmp.ne p6, p0 = r0, r28 \n\t" ";; \n\t" "(p7) ldf.fill f29 = [r27] \n\t" "(p6) ldf.fill f30 = [r28] \n\t" "cmp.ne p7, p0 = r0, r29 \n\t" ";; \n\t" "(p7) ldf.fill f31 = [r29] \n\t" "add r20 = uc_rnat, %0 \n\t" "add r21 = uc_bsp, %0 \n\t" ";; \n\t" /* Load the balance of the thread state from the context. */ "ld8 r22 = [r20], uc_psp - uc_rnat \n\t" "ld8 r23 = [r21], uc_gp - uc_bsp \n\t" ";; \n\t" "ld8 r24 = [r20], uc_pfs_loc - uc_psp \n\t" "ld8 r1 = [r21], uc_rp - uc_gp \n\t" ";; \n\t" "ld8 r25 = [r20], uc_unat_loc - uc_pfs_loc\n\t" "ld8 r26 = [r21], uc_pr - uc_rp \n\t" ";; \n\t" "ld8 r27 = [r20], uc_lc_loc - uc_unat_loc\n\t" "ld8 r28 = [r21], uc_fpsr_loc - uc_pr \n\t" ";; \n\t" "ld8 r29 = [r20], uc_eh_data - uc_lc_loc\n\t" "ld8 r30 = [r21], uc_eh_data + 8 - uc_fpsr_loc\n\t" ";; \n\t" /* Load data for the exception handler. */ "ld8 r15 = [r20], 16 \n\t" "ld8 r16 = [r21], 16 \n\t" ";; \n\t" "ld8 r17 = [r20] \n\t" "ld8 r18 = [r21] \n\t" ";; \n\t" /* Install the balance of the thread state loaded above. */ "cmp.ne p6, p0 = r0, r25 \n\t" "cmp.ne p7, p0 = r0, r27 \n\t" ";; \n\t" "(p6) ld8 r25 = [r25] \n\t" "(p7) ld8 r27 = [r27] \n\t" ";; \n\t" "(p7) mov.m ar.unat = r27 \n\t" "(p6) mov.i ar.pfs = r25 \n\t" "cmp.ne p9, p0 = r0, r29 \n\t" ";; \n\t" "(p9) ld8 r29 = [r29] \n\t" "cmp.ne p6, p0 = r0, r30 \n\t" ";; \n\t" "(p6) ld8 r30 = [r30] \n\t" /* Don't clobber p6-p9, which are in use at present. */ "mov pr = r28, ~0x3c0 \n\t" "(p9) mov.i ar.lc = r29 \n\t" ";; \n\t" "mov.m r25 = ar.rsc \n\t" "(p6) mov.m ar.fpsr = r30 \n\t" ";; \n\t" "and r25 = 0x1c, r25 \n\t" "mov b0 = r26 \n\t" ";; \n\t" "mov.m ar.rsc = r25 \n\t" ";; \n\t" /* This must be done before setting AR.BSPSTORE, otherwise AR.BSP will be initialized with a random displacement below the value we want, based on the current number of dirty stacked registers. */ "loadrs \n\t" "invala \n\t" ";; \n\t" "mov.m ar.bspstore = r23 \n\t" ";; \n\t" "or r25 = 0x3, r25 \n\t" "mov.m ar.rnat = r22 \n\t" ";; \n\t" "mov.m ar.rsc = r25 \n\t" "mov sp = r24 \n\t" "br.ret.sptk.few b0" : : "r"(target), "r"(ireg_buf), "r"(ireg_nat), "r"(ireg_pr) : "r15", "r16", "r17", "r18", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"); /* NOTREACHED */ while (1);}static inline _Unwind_Ptruw_identify_context (struct _Unwind_Context *context){ return _Unwind_GetIP (context);}#include "unwind.inc"#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -