Example #1
0
void
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
    uint32_t *intrpc)
{
	int depth = 0;
	uintptr_t osp, sp;
	vm_offset_t callpc;
	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;

	osp = PAGE_SIZE;
	if (intrpc != 0)
		pcstack[depth++] = (pc_t) intrpc;

	aframes++;

	sp = dtrace_getfp();

	while (depth < pcstack_limit) {
		if (sp <= osp)
			break;

		if (!dtrace_sp_inkernel(sp))
			break;
		callpc = dtrace_get_pc(sp);

		if (aframes > 0) {
			aframes--;
			if ((aframes == 0) && (caller != 0)) {
				pcstack[depth++] = caller;
			}
		}
		else {
			pcstack[depth++] = callpc;
		}

		osp = sp;
		sp = dtrace_next_sp(sp);
	}

	for (; depth < pcstack_limit; depth++) {
		pcstack[depth] = 0;
	}
}
Example #2
0
void
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
    uint32_t *intrpc)
{
	int depth = 0;
	register_t sp;
	vm_offset_t callpc;
	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;

	if (intrpc != 0)
		pcstack[depth++] = (pc_t) intrpc;

	aframes++;

	sp = dtrace_getfp();

	while (depth < pcstack_limit) {
		if (!INKERNEL((long) sp))
			break;

		callpc = *(uintptr_t *)(sp + RETURN_OFFSET);

		if (!INKERNEL(callpc))
			break;

		if (aframes > 0) {
			aframes--;
			if ((aframes == 0) && (caller != 0)) {
				pcstack[depth++] = caller;
			}
		}
		else {
			pcstack[depth++] = callpc;
		}

		sp = *(uintptr_t*)sp;
	}

	for (; depth < pcstack_limit; depth++) {
		pcstack[depth] = 0;
	}
}
Example #3
0
/*ARGSUSED*/
int
dtrace_getstackdepth(int aframes)
{
# if 1
    TODO();
    return 0;
# else
    struct frame *fp = (struct frame *)dtrace_getfp();
    struct frame *nextfp, *minfp, *stacktop;
    int depth = 0;
    int is_intr = 0;
    int on_intr;
    uintptr_t pc;

    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;

    aframes++;

    for (;;) {
        depth++;

        if (is_intr) {
            struct regs *rp = (struct regs *)fp;
            nextfp = (struct frame *)rp->r_fp;
            pc = rp->r_pc;
        } else {
            nextfp = (struct frame *)fp->fr_savfp;
            pc = fp->fr_savpc;
        }

        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;
            }
            break;
        }

        is_intr = pc - (uintptr_t)_interrupt < _interrupt_size ||
                  pc - (uintptr_t)_allsyscalls < _allsyscalls_size ||
                  pc - (uintptr_t)_cmntrap < _cmntrap_size;

        fp = nextfp;
        minfp = fp;
    }

    if (depth <= aframes)
        return (0);

    return (depth - aframes);
# endif
}
Example #4
0
/*ARGSUSED*/
uint64_t
dtrace_getarg(int arg, int aframes)
{
    uintptr_t val;
    struct frame *fp;
    uintptr_t *stack;
    int i;

#if defined(__amd64)
    /***********************************************/
    /*   First 6 args in a register.	       */
    /***********************************************/
    int inreg = 5;
    /*int inreg = offsetof(struct regs, r_r9) / sizeof (greg_t);*/
#endif

    DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
    fp = (struct frame *)dtrace_getfp();
    DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
//printk("dtrace_getarg: fp=%p %p\n", fp, fp->fr_savfp);

//printk("arg=%d aframes=%d\n", arg, aframes);

    for (i = 1; i <= aframes; i++) {
        pc_t savpc;
        DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
        fp = (struct frame *)(fp->fr_savfp);
        savpc = fp->fr_savpc;
        DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
//printk("fp=%p savpc=%p\n", fp, savpc);
        if (savpc == (pc_t)dtrace_invop_callsite) {
#if !defined(__amd64)
            /*
             * If we pass through the invalid op handler, we will
             * use the pointer that it passed to the stack as the
             * second argument to dtrace_invop() as the pointer to
             * the stack.  When using this stack, we must step
             * beyond the EIP/RIP that was pushed when the trap was
             * taken -- hence the "+ 1" below.
             */
            stack = ((uintptr_t **)&fp[1])[1] + 1;
#else
            /*
             * In the case of amd64, we will use the pointer to the
             * regs structure that was pushed when we took the
             * trap.  To get this structure, we must increment
             * beyond the frame structure, and then again beyond
             * the calling RIP stored in dtrace_invop().  If the
             * argument that we're seeking is passed on the stack,
             * we'll pull the true stack pointer out of the saved
             * registers and decrement our argument by the number
             * of arguments passed in registers; if the argument
             * we're seeking is passed in regsiters, we can just
             * load it directly.
             */
            struct regs *rp = (struct regs *)((uintptr_t)&fp[1] +
                                              sizeof (uintptr_t));

            if (arg <= inreg) {
                stack = (uintptr_t *)&rp->r_rdi;
            } else {
                stack = (uintptr_t *)(rp->r_rsp);
                arg -= inreg;
            }
#endif
            goto load;
        }

    }

    /*
     * We know that we did not come through a trap to get into
     * dtrace_probe() -- the provider simply called dtrace_probe()
     * directly.  As this is the case, we need to shift the argument
     * that we're looking for:  the probe ID is the first argument to
     * dtrace_probe(), so the argument n will actually be found where
     * one would expect to find argument (n + 1).
     */
    arg++;

#if defined(__amd64)
    if (arg <= inreg) {
        /*
         * This shouldn't happen.  If the argument is passed in a
         * register then it should have been, well, passed in a
         * register...
         */
        DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
        return (0);
    }

    arg -= (inreg + 1);
#endif
    stack = (uintptr_t *)&fp[1];

load:
    DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
    val = stack[arg];
    DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
    return (val);
}
Example #5
0
/*ARGSUSED*/
uint64_t
sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes)
{
	uintptr_t val;
	struct frame *fp = (struct frame *)dtrace_getfp();
	uintptr_t *stack = NULL;
	int i;
#if defined(__amd64)
	/*
	 * A total of 6 arguments are passed via registers; any argument with
	 * index of 5 or lower is therefore in a register.
	 */
	int inreg = 5;
#endif

/*	for (i = 1; i <= aframes+2; i++) {
		fp = (struct frame *)(fp->fr_savfp);
printk("stk %d: %p: %p %p %p %p\n%p %p %p\n", i, fp, ((long *) fp)[0], ((long *) fp)[1], ((long *) fp)[2], ((long *) fp)[3], 
((long *) fp)[4],
((long *) fp)[5],
((long *) fp)[6],
((long *) fp)[7]
);
	}
fp = dtrace_getfp();
*/

	for (i = 1; i <= aframes; i++) {
//printk("i=%d fp=%p aframes=%d pc:%p\n", i, fp, aframes, fp->fr_savpc);
		fp = (struct frame *)(fp->fr_savfp);
#if defined(linux)
		/***********************************************/
		/*   Temporary hack - not sure which stack we  */
		/*   have here and it is faultiing us.	       */
		/***********************************************/
		if (fp == NULL)
			return 0;
#endif

		if (fp->fr_savpc == (pc_t)dtrace_invop_callsite) {
#if !defined(__amd64)
			/*
			 * If we pass through the invalid op handler, we will
			 * use the pointer that it passed to the stack as the
			 * second argument to dtrace_invop() as the pointer to
			 * the stack.
			 */
			stack = ((uintptr_t **)&fp[1])[1];
#else
			/*
			 * In the case of amd64, we will use the pointer to the
			 * regs structure that was pushed when we took the
			 * trap.  To get this structure, we must increment
			 * beyond the frame structure.  If the argument that
			 * we're seeking is passed on the stack, we'll pull
			 * the true stack pointer out of the saved registers
			 * and decrement our argument by the number of
			 * arguments passed in registers; if the argument
			 * we're seeking is passed in regsiters, we can just
			 * load it directly.
			 */
			struct regs *rp = (struct regs *)((uintptr_t)&fp[1] +
			    sizeof (uintptr_t));

			if (argno <= inreg) {
				stack = (uintptr_t *)&rp->r_rdi;
			} else {
				stack = (uintptr_t *)(rp->r_rsp);
				argno -= (inreg + 1);
			}
#endif
			goto load;
		}
	}
//printk("stack %d: %p %p %p %p\n", i, ((long *) fp)[0], ((long *) fp)[1], ((long *) fp)[2], ((long *) fp)[3], ((long *) fp)[4]);

	/*
	 * We know that we did not come through a trap to get into
	 * dtrace_probe() -- the provider simply called dtrace_probe()
	 * directly.  As this is the case, we need to shift the argument
	 * that we're looking for:  the probe ID is the first argument to
	 * dtrace_probe(), so the argument n will actually be found where
	 * one would expect to find argument (n + 1).
	 */
	argno++;

#if defined(__amd64)
	if (argno <= inreg) {
		/*
		 * This shouldn't happen.  If the argument is passed in a
		 * register then it should have been, well, passed in a
		 * register...
		 */
		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
		return (0);
	}

	argno -= (inreg + 1);
#endif
	stack = (uintptr_t *)&fp[1];

load:
	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
	val = stack[argno];
	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
printk("sdt_getarg#%d: %lx aframes=%d\n", argno, val, aframes);

	return (val);
}
Example #6
0
void
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
    uint32_t *intrpc)
{
	struct frame *fp = (struct frame *)dtrace_getfp();
	struct frame *nextfp, *minfp, *stacktop;
	int depth = 0;
	int last = 0;
	uintptr_t pc;
	uintptr_t caller = CPU->cpu_dtrace_caller;
	int on_intr;

	if ((on_intr = CPU_ON_INTR(CPU)) != 0)
		stacktop = (struct frame *)dtrace_get_cpu_int_stack_top();
	else
		stacktop = (struct frame *)(dtrace_get_kernel_stack(current_thread()) + KERNEL_STACK_SIZE);

	minfp = fp;

	aframes++;

	if (intrpc != NULL && depth < pcstack_limit)
		pcstack[depth++] = (pc_t)intrpc;

	while (depth < pcstack_limit) {
		nextfp = *(struct frame **)fp;
		pc = *(uintptr_t *)(((uint32_t)fp) + RETURN_OFFSET);

		if (nextfp <= minfp || nextfp >= stacktop) {
			if (on_intr) {
				/*
				 * Hop from interrupt stack to thread stack.
				 */
				vm_offset_t kstack_base = dtrace_get_kernel_stack(current_thread());

				minfp = (struct frame *)kstack_base;
				stacktop = (struct frame *)(kstack_base + KERNEL_STACK_SIZE);

				on_intr = 0;
				continue;
			}
			/*
			 * This is the last frame we can process; indicate
			 * that we should return after processing this frame.
			 */
			last = 1;
		}

		if (aframes > 0) {
			if (--aframes == 0 && caller != 0) {
				/*
				 * We've just run out of artificial frames,
				 * and we have a valid caller -- fill it in
				 * now.
				 */
				ASSERT(depth < pcstack_limit);
				pcstack[depth++] = (pc_t)caller;
				caller = 0;
			}
		} else {
			if (depth < pcstack_limit)
				pcstack[depth++] = (pc_t)pc;
		}

		if (last) {
			while (depth < pcstack_limit)
				pcstack[depth++] = 0;
			return;
		}

		fp = nextfp;
		minfp = fp;
	}
}
Example #7
0
/*ARGSUSED*/
uint64_t
dtrace_getarg(int arg, int aframes)
{
	uintptr_t val;
	uintptr_t *fp = (uintptr_t *)dtrace_getfp();
	uintptr_t *stack;
	int i;

	/*
	 * A total of 8 arguments are passed via registers; any argument with
	 * index of 7 or lower is therefore in a register.
	 */
	int inreg = 7;

	for (i = 1; i <= aframes; i++) {
		fp = (uintptr_t *)*fp;

		/*
		 * On ppc32 AIM, and booke, trapexit() is the immediately following
		 * label.  On ppc64 AIM trapexit() follows a nop.
		 */
#ifdef __powerpc64__
		if ((long)(fp[2]) + 4 == (long)trapexit) {
#else
		if ((long)(fp[1]) == (long)trapexit) {
#endif
			/*
			 * In the case of powerpc, we will use the pointer to the regs
			 * structure that was pushed when we took the trap.  To get this
			 * structure, we must increment beyond the frame structure.  If the
			 * argument that we're seeking is passed on the stack, we'll pull
			 * the true stack pointer out of the saved registers and decrement
			 * our argument by the number of arguments passed in registers; if
			 * the argument we're seeking is passed in regsiters, we can just
			 * load it directly.
			 */
#ifdef __powerpc64__
			struct reg *rp = (struct reg *)((uintptr_t)fp[0] + 48);
#else
			struct reg *rp = (struct reg *)((uintptr_t)fp[0] + 8);
#endif

			if (arg <= inreg) {
				stack = &rp->fixreg[3];
			} else {
				stack = (uintptr_t *)(rp->fixreg[1]);
				arg -= inreg;
			}
			goto load;
		}

	}

	/*
	 * We know that we did not come through a trap to get into
	 * dtrace_probe() -- the provider simply called dtrace_probe()
	 * directly.  As this is the case, we need to shift the argument
	 * that we're looking for:  the probe ID is the first argument to
	 * dtrace_probe(), so the argument n will actually be found where
	 * one would expect to find argument (n + 1).
	 */
	arg++;

	if (arg <= inreg) {
		/*
		 * This shouldn't happen.  If the argument is passed in a
		 * register then it should have been, well, passed in a
		 * register...
		 */
		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
		return (0);
	}

	arg -= (inreg + 1);
	stack = fp + 2;

load:
	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
	val = stack[arg];
	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);

	return (val);
}

int
dtrace_getstackdepth(int aframes)
{
	int depth = 0;
	uintptr_t osp, sp;
	vm_offset_t callpc;

	osp = PAGE_SIZE;
	aframes++;
	sp = dtrace_getfp();
	depth++;
	for(;;) {
		if (sp <= osp)
			break;

		if (!dtrace_sp_inkernel(sp))
			break;

		if (aframes == 0)
			depth++;
		else
			aframes--;
		osp = sp;
		sp = dtrace_next_sp(sp);
	}
	if (depth < aframes)
		return (0);

	return (depth);
}