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