Exemple #1
0
static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels,
                              struct task_struct *tsk,
			      struct uretprobe_instance *ri, int uregs_valid)
{
#ifdef STP_USE_DWARF_UNWINDER
        int start_levels = levels;
	// FIXME: large stack allocation
	struct unwind_frame_info info;
	int sanitize = tsk && ! uregs_valid;
	arch_unw_init_frame_info(&info, regs, sanitize);

	while (levels && (tsk || !arch_unw_user_mode(&info))) {
		int ret = unwind(&info, tsk);
#ifdef STAPCONF_UPROBE_GET_PC
                unsigned long 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=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info));
		if (ret == 0) {
			_stp_print_addr(UNW_PC(&info), verbose, tsk);
			levels--;
			if (UNW_PC(&info) != _stp_kretprobe_trampoline)
			  continue;
		}
		/* If an error happened or we hit a kretprobe trampoline,
		 * use fallback backtrace, unless user task backtrace.
		 * FIXME: is there a way to unwind across kretprobe
		 * trampolines? PR9999. */
		if ((ret < 0
		     || UNW_PC(&info) == _stp_kretprobe_trampoline)
		    && ! (tsk || arch_unw_user_mode(&info)))
			_stp_stack_print_fallback(UNW_SP(&info), verbose, levels);
		return;
	}
#else /* ! STP_USE_DWARF_UNWINDER */
	_stp_stack_print_fallback(REG_SP(regs), verbose, levels);
#endif
}
Exemple #2
0
static int asmlinkage dump_trace_unwind(struct unwind_frame_info *info,
					const struct stacktrace_ops *ops,
					void *data)
{
	int n = 0;
#ifdef CONFIG_STACK_UNWIND
	unsigned long sp = UNW_SP(info);

	if (arch_unw_user_mode(info))
		return -1;
	while (unwind(info) == 0 && UNW_PC(info)) {
		n++;
		ops->address(data, UNW_PC(info), 1);
		if (arch_unw_user_mode(info))
			break;
		if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
		    && sp > UNW_SP(info))
			break;
		sp = UNW_SP(info);
	}
#endif
	return n;
}
Exemple #3
0
int try_stack_unwind(struct task_struct *task, struct pt_regs *regs,
		     unsigned long **stack, unsigned long *bp,
		     const struct stacktrace_ops *ops, void *data)
{
#ifdef CONFIG_STACK_UNWIND
	int unw_ret = 0;
	struct unwind_frame_info info;
	if (call_trace < 0)
		return 0;

	if (regs) {
		if (unwind_init_frame_info(&info, task, regs) == 0)
			unw_ret = dump_trace_unwind(&info, ops, data);
	} else if (task == current)
		unw_ret = unwind_init_running(&info, dump_trace_unwind, ops, data);
#ifdef CONFIG_SMP
	else if (task->on_cpu)
		/* nothing */;
#endif
	else if (unwind_init_blocked(&info, task) == 0)
		unw_ret = dump_trace_unwind(&info, ops, data);
	if (unw_ret > 0) {
		if (call_trace == 1 && !arch_unw_user_mode(&info)) {
			ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
					    UNW_PC(&info));
			if (UNW_SP(&info) >= PAGE_OFFSET) {
				ops->warning(data, "Leftover inexact backtrace:\n");
				*stack = (void *)UNW_SP(&info);
				*bp = UNW_FP(&info);
				return 0;
			}
		} else if (call_trace >= 1)
			return -1;
		ops->warning(data, "Full inexact backtrace again:\n");
	} else
		ops->warning(data, "Inexact backtrace:\n");
#endif
	return 0;
}