예제 #1
0
파일: stack.c 프로젝트: KnightKu/systemtap
static void _stp_stack_user_print(struct context *c, int sym_flags)
{
	struct pt_regs *regs = NULL;
	int uregs_valid = 0;
	struct uretprobe_instance *ri = NULL;

	if (c->probe_type == _STP_PROBE_HANDLER_URETPROBE)
		ri = c->ips.ri;
#ifdef STAPCONF_UPROBE_GET_PC
	else if (c->probe_type == _STP_PROBE_HANDLER_UPROBE)
		ri = GET_PC_URETPROBE_NONE;
#endif

	regs = _stp_get_uregs(c);
	uregs_valid = c->probe_flags & _STP_PROBE_STATE_FULL_UREGS;

	if (! current->mm || ! regs) {
		if (sym_flags & _STP_SYM_SYMBOL)
			_stp_printf("<no user backtrace at %s>\n",
				    c->probe_point);
		else
			_stp_print("\n");
		return;
	}

	/* print the current address */
#ifdef STAPCONF_UPROBE_GET_PC
	if (c->probe_type == _STP_PROBE_HANDLER_URETPROBE && ri) {
		if ((sym_flags & _STP_SYM_FULL) == _STP_SYM_FULL) {
			_stp_print("Returning from: ");
			/* ... otherwise this dereference fails */
			_stp_print_addr(ri->rp->u.vaddr, sym_flags, current);
			_stp_print("Returning to  : ");
			_stp_print_addr(ri->ret_addr, sym_flags, current);
		} else
			_stp_print_addr(ri->ret_addr, sym_flags, current);
	} else {
		_stp_print_addr(REG_IP(regs), sym_flags, current);
	}
#else
	_stp_print_addr(REG_IP(regs), sym_flags, current);
#endif

	/* print rest of stack... */
#ifdef STP_USE_DWARF_UNWINDER
	if (c->uregs == &c->uwcontext.info.regs) {
		/* Unwinder needs the reg state, clear uregs ref. */
		c->uregs = NULL;
		c->probe_flags &= ~_STP_PROBE_STATE_FULL_UREGS;
	}
	__stp_dwarf_stack_user_print(regs, sym_flags, MAXBACKTRACE,
				     &c->uwcontext, ri, uregs_valid);
#else
	/* User stack traces only supported for arches with dwarf unwinder. */
	if (sym_flags & _STP_SYM_SYMBOL)
		_stp_printf("<no user backtrace support on arch>\n");
	else
		_stp_print("\n");
#endif
}
예제 #2
0
static void _stp_stack_user_print(struct context *c, int sym_flags)
{
	struct pt_regs *regs = NULL;
	struct uretprobe_instance *ri = NULL;
	unsigned n; unsigned long l;

	if (c->probe_type == stp_probe_type_uretprobe)
		ri = c->ips.ri;
#ifdef STAPCONF_UPROBE_GET_PC
	else if (c->probe_type == stp_probe_type_uprobe)
		ri = GET_PC_URETPROBE_NONE;
#endif

	regs = _stp_get_uregs(c);

	if (! current->mm || ! regs) {
		if (sym_flags & _STP_SYM_SYMBOL)
			_stp_printf("<no user backtrace at %s>\n",
				    c->probe_point);
		else
			_stp_print("\n");
		return;
	}

	/* print the current address */
#ifdef STAPCONF_UPROBE_GET_PC
	if (c->probe_type == stp_probe_type_uretprobe && ri) {
		if ((sym_flags & _STP_SYM_FULL) == _STP_SYM_FULL) {
			_stp_print("Returning from: ");
			/* ... otherwise this dereference fails */
			_stp_print_addr(ri->rp->u.vaddr, sym_flags, current);
			_stp_print("Returning to  : ");
		}
	}
#endif
	_stp_print_addr(_stp_stack_user_get(c, 0), sym_flags, current);

	/* print rest of stack... */
#ifdef STP_USE_DWARF_UNWINDER
	for (n = 1; n < MAXBACKTRACE; n++) {
		l = _stp_stack_user_get(c, n);
		if (l == 0) break; // No user space fallback available
		_stp_print_addr(l, sym_flags, current);
	}
#else
	/* User stack traces only supported for arches with dwarf unwinder. */
	if (sym_flags & _STP_SYM_SYMBOL)
		_stp_printf("<no user backtrace support on arch>\n");
	else
		_stp_print("\n");
#endif
}
예제 #3
0
static unsigned long _stp_stack_unwind_one_user(struct context *c, unsigned depth)
{
	struct pt_regs *regs = NULL;
	int uregs_valid = 0;
	struct uretprobe_instance *ri = NULL;
	struct unwind_frame_info *info = NULL;
	int ret;
#ifdef STAPCONF_UPROBE_GET_PC
	unsigned long maybe_pc;
#endif

	if (c->probe_type == stp_probe_type_uretprobe)
		ri = c->ips.ri;
#ifdef STAPCONF_UPROBE_GET_PC
	else if (c->probe_type == stp_probe_type_uprobe)
		ri = GET_PC_URETPROBE_NONE;
#endif

	/* XXX: The computation that gives this is cached, so calling
	 * _stp_get_uregs multiple times is okay... probably. */
	regs = _stp_get_uregs(c);
	uregs_valid = c->full_uregs_p;

	if (! current->mm || ! regs)
		return 0; // no user backtrace at this probe point

	if (depth == 0) { /* Start by fetching the current PC. */
		dbug_unwind(1, "STARTING user unwind\n");

#ifdef STAPCONF_UPROBE_GET_PC
		if (c->probe_type == stp_probe_type_uretprobe && ri) {
			return ri->ret_addr;
		} else {
			return REG_IP(regs);
		}
#else
		return REG_IP(regs);
#endif
	}

#ifdef STP_USE_DWARF_UNWINDER
	info = &c->uwcontext_user.info;

	dbug_unwind(1, "CONTINUING user unwind to depth %d\n", depth);

	if (depth == 1) { /* need to clear uregs & set up uwcontext->info */
		if (c->uregs == &c->uwcontext_user.info.regs) {
			dbug_unwind(1, "clearing uregs\n");
			/* Unwinder needs the reg state, clear uregs ref. */
			c->uregs = NULL;
			c->full_uregs_p = 0;
		}

		arch_unw_init_frame_info(info, regs, 0);
	}

	ret = unwind(&c->uwcontext_user, 1);
#ifdef STAPCONF_UPROBE_GET_PC
	maybe_pc = 0;
	if (ri) {
		maybe_pc = uprobe_get_pc(ri, UNW_PC(info), UNW_SP(info));
		if (!maybe_pc)
			printk("SYSTEMTAP ERROR: uprobe_get_return returned 0\n");
		else
			UNW_PC(info) = maybe_pc;
	}
#endif
	dbug_unwind(1, "ret=%d PC=%llx SP=%llx\n", ret,
		    (unsigned long long) UNW_PC(info), (unsigned long long) UNW_SP(info));

	/* check if unwind hit an error */
	if (ret || ! _stp_valid_pc_addr(UNW_PC(info), current)) {
		return 0;
	}

	return UNW_PC(info);
#else
	/* User stack traces only supported for arches with dwarf unwinder. */
	return 0;
#endif
}