コード例 #1
0
static unsigned long _stp_stack_unwind_one_kernel(struct context *c, unsigned depth)
{
	struct pt_regs *regs = NULL;
	struct unwind_frame_info *info = NULL;
	int ret;

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

		if (! c->kregs) {
			/* Even the current PC is unknown; so we have
			 * absolutely no data at any depth.
			 *
			 * Note that unlike _stp_stack_kernel_print(),
			 * we can't fall back to calling dump_trace()
			 * to obtain the backtrace -- since that
			 * returns a string, which we would have to
			 * tokenize. Callers that want to use the
			 * dump_trace() fallback should call
			 * _stp_stack_kernel_print() and do their own
			 * tokenization of the result. */
#if defined (__i386__) || defined (__x86_64__)
		        arch_unw_init_frame_info(&c->uwcontext_kernel.info, NULL, 0);
		        return UNW_PC(&c->uwcontext_kernel.info);
#else
			return 0;
#endif
		} else if (c->probe_type == stp_probe_type_kretprobe
			   && c->ips.krp.pi) {
			return (unsigned long)_stp_ret_addr_r(c->ips.krp.pi);
		} else {
			return REG_IP(c->kregs);
		}
	}

#ifdef STP_USE_DWARF_UNWINDER
	/* Otherwise, use the DWARF unwinder to unwind one step. */

	regs = c->kregs;

	info = &c->uwcontext_kernel.info;

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

	if (depth == 1) {
                /* First step of actual DWARF unwind;
		   need to clear uregs& set up uwcontext->info. */
		if (c->uregs == &c->uwcontext_kernel.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_kernel, 0);
	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), NULL)) {
		return 0;
	}

	return UNW_PC(info);
#else
	return 0;
#endif
}
コード例 #2
0
ファイル: stack.c プロジェクト: KnightKu/systemtap
static void _stp_stack_kernel_print(struct context *c, int sym_flags)
{
	struct pt_regs *regs = NULL;

	if (! c->kregs) {
		/* For the kernel we can use an inexact fallback.
		   When compiled with frame pointers we can do
		   a pretty good guess at the stack value,
		   otherwise let dump_stack guess it
		   (and skip some framework frames). */
#if defined(STAPCONF_KERNEL_STACKTRACE) || defined(STAPCONF_KERNEL_STACKTRACE_NO_BP)
		unsigned long sp;
		int skip;
#ifdef CONFIG_FRAME_POINTER
		sp  = *(unsigned long *) __builtin_frame_address (0);
		skip = 1; /* Skip just this frame. */
#else
		sp = 0;
		skip = 5; /* yes, that many framework frames. */
#endif
		_stp_stack_print_fallback(sp, sym_flags,
					  MAXBACKTRACE, skip);
#else
		if (sym_flags & _STP_SYM_SYMBOL)
			_stp_printf("<no kernel backtrace at %s>\n",
				    c->probe_point);
		else
			_stp_print("\n");
#endif
		return;
	} else {
		regs = c->kregs;
	}

	/* print the current address */
	if (c->probe_type == _STP_PROBE_HANDLER_KRETPROBE && c->ips.krp.pi) {
		if ((sym_flags & _STP_SYM_FULL) == _STP_SYM_FULL) {
			_stp_print("Returning from: ");
			_stp_print_addr((unsigned long)_stp_probe_addr_r(c->ips.krp.pi),
					sym_flags, NULL);
			_stp_print("Returning to  : ");
		}
		_stp_print_addr((unsigned long)_stp_ret_addr_r(c->ips.krp.pi),
				sym_flags, NULL);
	} else {
		_stp_print_addr(REG_IP(regs), sym_flags, NULL);
	}

	/* 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_kernel_print(regs, sym_flags, MAXBACKTRACE,
				       &c->uwcontext);
#else
	/* Arch specific fallback for kernel backtraces. */
	__stp_stack_print(regs, sym_flags, MAXBACKTRACE);
#endif
}