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