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 }
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 }
static void __stp_dwarf_stack_user_print(struct pt_regs *regs, int verbose, int levels, struct unwind_context *uwcontext, struct uretprobe_instance *ri, int uregs_valid) { struct unwind_frame_info *info = &uwcontext->info; arch_unw_init_frame_info(info, regs, ! uregs_valid); while (levels) { int ret = unwind(uwcontext, 1); #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_valid_pc_addr(UNW_PC(info), current)) { _stp_print_addr(UNW_PC(info), verbose, current); levels--; continue; } /* If an error happened or the PC becomes invalid, then * we are done, _stp_stack_print_fallback is only for * kernel space. */ return; } }
static void __stp_dwarf_stack_kernel_print(struct pt_regs *regs, int verbose, int levels, struct unwind_context *uwcontext) { struct unwind_frame_info *info = &uwcontext->info; arch_unw_init_frame_info(info, regs, 0); while (levels) { int ret = unwind(uwcontext, 0); dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(info), UNW_SP(info)); if (ret == 0 && _stp_valid_pc_addr(UNW_PC(info), NULL)) { _stp_print_addr(UNW_PC(info), verbose, NULL); levels--; if (UNW_PC(info) != _stp_kretprobe_trampoline) continue; } /* If an error happened or we hit a kretprobe trampoline, * and the current pc frame address is still valid kernel * address 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)) _stp_stack_print_fallback(UNW_SP(info), verbose, levels, 0); return; } }
static void print_stack_address(void *data, unsigned long addr, int reliable) { struct print_stack_data *sdata = data; if (sdata->skip > 0) sdata->skip--; else if (sdata->levels > 0) { _stp_print_addr(addr, sdata->flags | (reliable ? 0 :_STP_SYM_INEXACT), NULL); sdata->levels--; } }
static void _stp_stack_print_fallback(unsigned long stack, int verbose, int levels) { unsigned long addr; while (levels && stack & (THREAD_SIZE - 1)) { if (unlikely(_stp_read_address(addr, (unsigned long *)stack, KERNEL_DS))) { /* cannot access stack. give up. */ return; } _stp_print_addr(addr, verbose | _STP_SYM_INEXACT, NULL); levels--; stack++; } }
static void print_stack_address(void *data, unsigned long addr, int reliable) #endif { struct print_stack_data *sdata = data; if (sdata->skip > 0) sdata->skip--; else if (sdata->levels > 0) { _stp_print_addr(addr, sdata->flags | (reliable ? 0 :_STP_SYM_INEXACT), NULL); sdata->levels--; } #ifdef STAPCONF_STACKTRACE_OPS_INT_ADDRESS return 0; #endif }
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 }
static void _stp_stack_kernel_print(struct context *c, int sym_flags) { unsigned n, remaining; unsigned long l; /* print the current address */ if (c->probe_type == stp_probe_type_kretprobe && c->ips.krp.pi && (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(_stp_stack_kernel_get(c, 0), sym_flags, NULL); #ifdef STP_USE_DWARF_UNWINDER for (n = 1; n < MAXBACKTRACE; n++) { l = _stp_stack_kernel_get(c, n); if (l == 0) { remaining = MAXBACKTRACE - n; _stp_stack_print_fallback(UNW_SP(&c->uwcontext_kernel.info), sym_flags, remaining, 0); break; } else { _stp_print_addr(l, sym_flags, NULL); } } #else if (! c->kregs) { /* This is a fatal block for _stp_stack_kernel_get, * but when printing a backtrace we can use this * 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 /* Arch specific fallback for kernel backtraces. */ __stp_stack_print(c->kregs, sym_flags, MAXBACKTRACE); #endif }
static void _stp_stack_print_fallback(unsigned long s, int v, int l, int k) { /* Don't guess, just give up. */ _stp_print_addr(0, v | _STP_SYM_INEXACT, NULL); }
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 }