📄 dtrace_isa.c
字号:
if (lwp == NULL || p == NULL || lwp->lwp_regs == NULL) return; if (pcstack_limit <= 0) return; *pcstack++ = (uint64_t)p->p_pid; pcstack_limit--; if (pcstack_limit <= 0) return; rp = lwp->lwp_regs; if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { *fpstack++ = 0; *pcstack++ = (uint64_t)rp->r_pc; pcstack_limit--; if (pcstack_limit <= 0) return; *fpstack++ = (uint64_t)rp->r_sp; *pcstack++ = (uint64_t)rp->r_o7; pcstack_limit--; } else { *fpstack++ = (uint64_t)rp->r_sp; *pcstack++ = (uint64_t)rp->r_pc; pcstack_limit--; } if (pcstack_limit <= 0) return; sp = rp->r_sp; dtrace_flush_user_windows(); if (p->p_model == DATAMODEL_NATIVE) { while (pcstack_limit > 0) { struct frame *fr = (struct frame *)(sp + STACK_BIAS); uintptr_t pc; if (sp == 0 || fr == NULL || ((uintptr_t)&fr->fr_savpc & 3) != 0 || ((uintptr_t)&fr->fr_savfp & 3) != 0) break; pc = dtrace_fulword(&fr->fr_savpc); sp = dtrace_fulword(&fr->fr_savfp); if (pc == 0) break; *fpstack++ = sp; *pcstack++ = pc; pcstack_limit--; } } else { while (pcstack_limit > 0) { struct frame32 *fr = (struct frame32 *)sp; uint32_t pc; if (sp == 0 || ((uintptr_t)&fr->fr_savpc & 3) != 0 || ((uintptr_t)&fr->fr_savfp & 3) != 0) break; pc = dtrace_fuword32(&fr->fr_savpc); sp = dtrace_fuword32(&fr->fr_savfp); *fpstack++ = sp; *pcstack++ = pc; pcstack_limit--; } } while (pcstack_limit-- > 0) *pcstack++ = NULL;}uint64_tdtrace_getarg(int arg, int aframes){ uintptr_t val; struct frame *fp; uint64_t rval; /* * Account for the fact that dtrace_getarg() consumes an additional * stack frame. */ aframes++; if (arg < 6) { if (dtrace_fish(aframes, DTRACE_REG_I0 + arg, &val) == 0) return (val); } else { if (dtrace_fish(aframes, DTRACE_REG_I6, &val) == 0) { /* * We have a stack pointer; grab the argument. */ fp = (struct frame *)(val + STACK_BIAS); DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); rval = fp->fr_argx[arg - 6]; DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); return (rval); } } /* * There are other ways to do this. But the slow, painful way works * just fine. Because this requires some loads, we need to set * CPU_DTRACE_NOFAULT to protect against looking for an argument that * isn't there. */ fp = (struct frame *)((caddr_t)dtrace_getfp() + STACK_BIAS); dtrace_flush_windows(); DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); for (aframes -= 1; aframes; aframes--) fp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS); if (arg < 6) { rval = fp->fr_arg[arg]; } else { fp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS); rval = fp->fr_argx[arg - 6]; } DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); return (rval);}intdtrace_getstackdepth(int aframes){ struct frame *fp, *nextfp, *minfp, *stacktop; int depth = 0; int on_intr; fp = (struct frame *)((caddr_t)dtrace_getfp() + STACK_BIAS); dtrace_flush_windows(); if ((on_intr = CPU_ON_INTR(CPU)) != 0) stacktop = (struct frame *)CPU->cpu_intr_stack + SA(MINFRAME); else stacktop = (struct frame *)curthread->t_stk; minfp = fp; for (;;) { nextfp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS); if (nextfp <= minfp || nextfp >= stacktop) { if (on_intr) { /* * Hop from interrupt stack to thread stack. */ stacktop = (struct frame *)curthread->t_stk; minfp = (struct frame *)curthread->t_stkbase; on_intr = 0; continue; } return (++depth); } if (aframes > 0) { aframes--; } else { depth++; } fp = nextfp; minfp = fp; }}/* * This uses the same register numbering scheme as in sys/procfs_isa.h. */ulong_tdtrace_getreg(struct regs *rp, uint_t reg){ ulong_t value; uintptr_t fp; struct machpcb *mpcb; if (reg == R_G0) return (0); if (reg <= R_G7) return ((&rp->r_g1)[reg - 1]); if (reg > R_I7) { switch (reg) { case R_CCR: return ((rp->r_tstate >> TSTATE_CCR_SHIFT) & TSTATE_CCR_MASK); case R_PC: return (rp->r_pc); case R_nPC: return (rp->r_npc); case R_Y: return (rp->r_y); case R_ASI: return ((rp->r_tstate >> TSTATE_ASI_SHIFT) & TSTATE_ASI_MASK); case R_FPRS: return (dtrace_getfprs()); default: DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); return (0); } } /* * We reach go to the fake restore case if the probe we hit was a pid * return probe on a restore instruction. We partially emulate the * restore in the kernel and then execute a simple restore * instruction that we've secreted away to do the actual register * window manipulation. We need to go one register window further * down to get at the %ls, and %is and we need to treat %os like %is * to pull them out of the topmost user frame. */ if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAKERESTORE)) { if (reg > R_O7) goto fake_restore; else reg += R_I0 - R_O0; } else if (reg <= R_O7) { return ((&rp->r_g1)[reg - 1]); } if (dtrace_getotherwin() > 0) return (dtrace_getreg_win(reg, 1)); mpcb = (struct machpcb *)((caddr_t)rp - REGOFF); if (curproc->p_model == DATAMODEL_NATIVE) { struct frame *fr = (void *)(rp->r_sp + STACK_BIAS); if (mpcb->mpcb_wbcnt > 0) { struct rwindow *rwin = (void *)mpcb->mpcb_wbuf; int i = mpcb->mpcb_wbcnt; do { i--; if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp) return (rwin[i].rw_local[reg - 16]); } while (i > 0); } DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); value = dtrace_fulword(&fr->fr_local[reg - 16]); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); } else { struct frame32 *fr = (void *)(caddr32_t)rp->r_sp; if (mpcb->mpcb_wbcnt > 0) { struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf; int i = mpcb->mpcb_wbcnt; do { i--; if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp) return (rwin[i].rw_local[reg - 16]); } while (i > 0); } DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); value = dtrace_fuword32(&fr->fr_local[reg - 16]); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); } return (value);fake_restore: ASSERT(R_L0 <= reg && reg <= R_I7); /* * We first look two user windows down to see if we can dig out * the register we're looking for. */ if (dtrace_getotherwin() > 1) return (dtrace_getreg_win(reg, 2)); /* * First we need to get the frame pointer and then we perform * the same computation as in the non-fake-o-restore case. */ mpcb = (struct machpcb *)((caddr_t)rp - REGOFF); if (dtrace_getotherwin() > 0) { fp = dtrace_getreg_win(R_FP, 1); goto got_fp; } if (curproc->p_model == DATAMODEL_NATIVE) { struct frame *fr = (void *)(rp->r_sp + STACK_BIAS); if (mpcb->mpcb_wbcnt > 0) { struct rwindow *rwin = (void *)mpcb->mpcb_wbuf; int i = mpcb->mpcb_wbcnt; do { i--; if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp) { fp = rwin[i].rw_fp; goto got_fp; } } while (i > 0); } DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); fp = dtrace_fulword(&fr->fr_savfp); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); if (cpu_core[CPU->cpu_id].cpuc_dtrace_flags & CPU_DTRACE_FAULT) return (0); } else { struct frame32 *fr = (void *)(caddr32_t)rp->r_sp; if (mpcb->mpcb_wbcnt > 0) { struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf; int i = mpcb->mpcb_wbcnt; do { i--; if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp) { fp = rwin[i].rw_fp; goto got_fp; } } while (i > 0); } DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); fp = dtrace_fuword32(&fr->fr_savfp); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); if (cpu_core[CPU->cpu_id].cpuc_dtrace_flags & CPU_DTRACE_FAULT) return (0); }got_fp: if (curproc->p_model == DATAMODEL_NATIVE) { struct frame *fr = (void *)(fp + STACK_BIAS); if (mpcb->mpcb_wbcnt > 0) { struct rwindow *rwin = (void *)mpcb->mpcb_wbuf; int i = mpcb->mpcb_wbcnt; do { i--; if ((long)mpcb->mpcb_spbuf[i] == fp) return (rwin[i].rw_local[reg - 16]); } while (i > 0); } DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); value = dtrace_fulword(&fr->fr_local[reg - 16]); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); } else { struct frame32 *fr = (void *)(caddr32_t)fp; if (mpcb->mpcb_wbcnt > 0) { struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf; int i = mpcb->mpcb_wbcnt; do { i--; if ((long)mpcb->mpcb_spbuf[i] == fp) return (rwin[i].rw_local[reg - 16]); } while (i > 0); } DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); value = dtrace_fuword32(&fr->fr_local[reg - 16]); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); } return (value);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -