Esempio n. 1
0
int
pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
    struct trapframe *tf)
{
	uintptr_t *osp, *sp;
	int frames = 0;

	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);
	osp = NULL;

	for (; frames < maxsamples; frames++) {
		if (sp <= osp)
			break;
		osp = sp;
#ifdef __powerpc64__
		/* Check if 32-bit mode. */
		if (!(tf->srr1 & PSL_SF)) {
			cc[frames] = fuword32((uint32_t *)sp + 1);
			sp = (uintptr_t *)(uintptr_t)fuword32(sp);
		} else {
			cc[frames] = fuword(sp + 2);
			sp = (uintptr_t *)fuword(sp);
		}
#else
		cc[frames] = fuword32((uint32_t *)sp + 1);
		sp = (uintptr_t *)fuword32(sp);
#endif
	}

	return (frames);
}
Esempio n. 2
0
int
pmc_save_user_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
{
	int n;
	uint32_t instr;
	uintptr_t fp, oldfp, pc, r, sp;

	KASSERT(TRAPF_USERMODE(tf), ("[x86,%d] Not a user trap frame tf=%p",
	    __LINE__, (void *) tf));

	pc = PMC_TRAPFRAME_TO_PC(tf);
	oldfp = fp = PMC_TRAPFRAME_TO_FP(tf);
	sp = PMC_TRAPFRAME_TO_USER_SP(tf);

	*cc++ = pc; n = 1;

	r = fp + sizeof(uintptr_t); /* points to return address */

	if (!PMC_IN_USERSPACE(pc))
		return (n);

	if (copyin((void *) pc, &instr, sizeof(instr)) != 0)
		return (n);

	if (PMC_AT_FUNCTION_PROLOGUE_PUSH_BP(instr) ||
	    PMC_AT_FUNCTION_EPILOGUE_RET(instr)) { /* ret */
		if (copyin((void *) sp, &pc, sizeof(pc)) != 0)
			return (n);
	} else if (PMC_AT_FUNCTION_PROLOGUE_MOV_SP_BP(instr)) {
		sp += sizeof(uintptr_t);
		if (copyin((void *) sp, &pc, sizeof(pc)) != 0)
			return (n);
	} else if (copyin((void *) r, &pc, sizeof(pc)) != 0 ||
	    copyin((void *) fp, &fp, sizeof(fp)) != 0)
		return (n);

	for (; n < nframes;) {
		if (pc == 0 || !PMC_IN_USERSPACE(pc))
			break;

		*cc++ = pc; n++;

		if (fp < oldfp)
			break;

		r = fp + sizeof(uintptr_t); /* address of return address */
		oldfp = fp;

		if (copyin((void *) r, &pc, sizeof(pc)) != 0 ||
		    copyin((void *) fp, &fp, sizeof(fp)) != 0)
			break;
	}

	return (n);
}
Esempio n. 3
0
int
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
    struct trapframe *tf)
{
	uintptr_t pc, r, stackstart, stackend, fp;
	struct thread *td;
	int count;

	KASSERT(TRAPF_USERMODE(tf) == 0,("[arm,%d] not a kernel backtrace",
	    __LINE__));

	pc = PMC_TRAPFRAME_TO_PC(tf);
	*cc++ = pc;

	if ((td = curthread) == NULL)
		return (1);

	if (maxsamples <= 1)
		return (1);

	stackstart = (uintptr_t) td->td_kstack;
	stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;
	fp = PMC_TRAPFRAME_TO_FP(tf);

	if (!PMC_IN_KERNEL(pc) ||
	    !PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
		return (1);

	for (count = 1; count < maxsamples; count++) {
		/* Use saved lr as pc. */
		r = fp - sizeof(uintptr_t);
		if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
			break;
		pc = *(uintptr_t *)r;
		if (!PMC_IN_KERNEL(pc))
			break;

		*cc++ = pc;

		/* Switch to next frame up */
		r = fp - 3 * sizeof(uintptr_t);
		if (!PMC_IN_KERNEL_STACK(r, stackstart, stackend))
			break;
		fp = *(uintptr_t *)r;
		if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
			break;
	}

	return (count);
}
Esempio n. 4
0
int
pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
    struct trapframe *tf)
{
	uintptr_t pc, r, oldfp, fp;
	struct thread *td;
	int count;

	KASSERT(TRAPF_USERMODE(tf), ("[x86,%d] Not a user trap frame tf=%p",
	    __LINE__, (void *) tf));

	pc = PMC_TRAPFRAME_TO_PC(tf);
	*cc++ = pc;

	if ((td = curthread) == NULL)
		return (1);

	if (maxsamples <= 1)
		return (1);

	oldfp = fp = PMC_TRAPFRAME_TO_FP(tf);

	if (!PMC_IN_USERSPACE(pc) ||
	    !PMC_IN_USERSPACE(fp))
		return (1);

	for (count = 1; count < maxsamples; count++) {
		/* Use saved lr as pc. */
		r = fp - sizeof(uintptr_t);
		if (copyin((void *)r, &pc, sizeof(pc)) != 0)
			break;
		if (!PMC_IN_USERSPACE(pc))
			break;

		*cc++ = pc;

		/* Switch to next frame up */
		oldfp = fp;
		r = fp - 3 * sizeof(uintptr_t);
		if (copyin((void *)r, &fp, sizeof(fp)) != 0)
			break;
		if (fp < oldfp || !PMC_IN_USERSPACE(fp))
			break;
	}

	return (count);
}
Esempio n. 5
0
int
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
    struct trapframe *tf)
{
	int frames = 0;
	uintptr_t *sp;

	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);

	for (frames = 1; frames < maxsamples; frames++) {
		if (!INKERNEL(sp))
			break;
		cc[frames++] = sp[1];
		sp = (uintptr_t *)*sp;
	}
	return (frames);
}
Esempio n. 6
0
int
pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
    struct trapframe *tf)
{
	uintptr_t *sp;
	int frames = 0;

	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);

	for (frames = 1; frames < maxsamples; frames++) {
		if (!INUSER(sp))
			break;
		cc[frames++] = fuword(sp + 1);
		sp = (uintptr_t *)fuword(sp);
	}
	return (frames);
}
Esempio n. 7
0
int
pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
    struct trapframe *tf)
{
	uintptr_t *osp, *sp;
	uintptr_t pc;
	int frames = 0;

	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);
	osp = (uintptr_t *)PAGE_SIZE;

	for (; frames < maxsamples; frames++) {
		if (sp <= osp)
			break;
	    #ifdef __powerpc64__
		pc = sp[2];
	    #else
		pc = sp[1];
	    #endif
		if ((pc & 3) || (pc < 0x100))
			break;

		/*
		 * trapexit() and asttrapexit() are sentinels
		 * for kernel stack tracing.
		 * */
		if (pc + OFFSET == (uintptr_t) &trapexit ||
		    pc + OFFSET == (uintptr_t) &asttrapexit)
			break;

		cc[frames] = pc;
		osp = sp;
		sp = (uintptr_t *)*sp;
	}
	return (frames);
}
Esempio n. 8
0
int
pmc_save_kernel_callchain(uintptr_t *cc, int nframes, struct trapframe *tf)
{
	int n;
	uint32_t instr;
	uintptr_t fp, pc, r, sp, stackstart, stackend;
	struct thread *td;

	KASSERT(TRAPF_USERMODE(tf) == 0,("[x86,%d] not a kernel backtrace",
	    __LINE__));

	td = curthread;
	pc = PMC_TRAPFRAME_TO_PC(tf);
	fp = PMC_TRAPFRAME_TO_FP(tf);
	sp = PMC_TRAPFRAME_TO_KERNEL_SP(tf);

	*cc++ = pc;
	r = fp + sizeof(uintptr_t); /* points to return address */

	if (nframes <= 1)
		return (1);

	stackstart = (uintptr_t) td->td_kstack;
	stackend = (uintptr_t) td->td_kstack + td->td_kstack_pages * PAGE_SIZE;

	if (PMC_IN_TRAP_HANDLER(pc) ||
	    !PMC_IN_KERNEL(pc) ||
	    !PMC_IN_KERNEL_STACK(r, stackstart, stackend) ||
	    !PMC_IN_KERNEL_STACK(sp, stackstart, stackend) ||
	    !PMC_IN_KERNEL_STACK(fp, stackstart, stackend))
		return (1);

	instr = *(uint32_t *) pc;

	/*
	 * Determine whether the interrupted function was in the
	 * processing of either laying down its stack frame or taking
	 * it off.
	 *
	 * If we haven't started laying down a stack frame, or are
	 * just about to return, then our caller's address is at
	 * *sp, and we don't have a frame to unwind.
	 */
	if (PMC_AT_FUNCTION_PROLOGUE_PUSH_BP(instr) ||
	    PMC_AT_FUNCTION_EPILOGUE_RET(instr))
		pc = *(uintptr_t *) sp;
	else if (PMC_AT_FUNCTION_PROLOGUE_MOV_SP_BP(instr)) {
		/*
		 * The code was midway through laying down a frame.
		 * At this point sp[0] has a frame back pointer,
		 * and the caller's address is therefore at sp[1].
		 */
		sp += sizeof(uintptr_t);
		if (!PMC_IN_KERNEL_STACK(sp, stackstart, stackend))
			return (1);
		pc = *(uintptr_t *) sp;
	} else {
		/*
		 * Not in the function prologue or epilogue.
		 */
		pc = *(uintptr_t *) r;
		fp = *(uintptr_t *) fp;
	}

	for (n = 1; n < nframes; n++) {
		*cc++ = pc;

		if (PMC_IN_TRAP_HANDLER(pc))
			break;

		r = fp + sizeof(uintptr_t);
		if (!PMC_IN_KERNEL_STACK(fp, stackstart, stackend) ||
		    !PMC_IN_KERNEL_STACK(r, stackstart, stackend))
			break;
		pc = *(uintptr_t *) r;
		fp = *(uintptr_t *) fp;
	}

	return (n);
}