18637c099SIngo Molnar /* 28637c099SIngo Molnar * kernel/stacktrace.c 38637c099SIngo Molnar * 48637c099SIngo Molnar * Stack trace management functions 58637c099SIngo Molnar * 68637c099SIngo Molnar * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <[email protected]> 78637c099SIngo Molnar */ 88637c099SIngo Molnar #include <linux/sched.h> 99212ddb5SIngo Molnar #include <linux/kernel.h> 109984de1aSPaul Gortmaker #include <linux/export.h> 118637c099SIngo Molnar #include <linux/kallsyms.h> 128637c099SIngo Molnar #include <linux/stacktrace.h> 138637c099SIngo Molnar 148637c099SIngo Molnar void print_stack_trace(struct stack_trace *trace, int spaces) 158637c099SIngo Molnar { 16a5a242dcSVegard Nossum int i; 178637c099SIngo Molnar 18bfeeeeb9SJohannes Berg if (WARN_ON(!trace->entries)) 19bfeeeeb9SJohannes Berg return; 20bfeeeeb9SJohannes Berg 218637c099SIngo Molnar for (i = 0; i < trace->nr_entries; i++) { 22a5a242dcSVegard Nossum printk("%*c", 1 + spaces, ' '); 23a5a242dcSVegard Nossum print_ip_sym(trace->entries[i]); 248637c099SIngo Molnar } 258637c099SIngo Molnar } 268594698eSIngo Molnar EXPORT_SYMBOL_GPL(print_stack_trace); 278637c099SIngo Molnar 28*9a92a6ceSJoonsoo Kim int snprint_stack_trace(char *buf, size_t size, 29*9a92a6ceSJoonsoo Kim struct stack_trace *trace, int spaces) 30*9a92a6ceSJoonsoo Kim { 31*9a92a6ceSJoonsoo Kim int i; 32*9a92a6ceSJoonsoo Kim unsigned long ip; 33*9a92a6ceSJoonsoo Kim int generated; 34*9a92a6ceSJoonsoo Kim int total = 0; 35*9a92a6ceSJoonsoo Kim 36*9a92a6ceSJoonsoo Kim if (WARN_ON(!trace->entries)) 37*9a92a6ceSJoonsoo Kim return 0; 38*9a92a6ceSJoonsoo Kim 39*9a92a6ceSJoonsoo Kim for (i = 0; i < trace->nr_entries; i++) { 40*9a92a6ceSJoonsoo Kim ip = trace->entries[i]; 41*9a92a6ceSJoonsoo Kim generated = snprintf(buf, size, "%*c[<%p>] %pS\n", 42*9a92a6ceSJoonsoo Kim 1 + spaces, ' ', (void *) ip, (void *) ip); 43*9a92a6ceSJoonsoo Kim 44*9a92a6ceSJoonsoo Kim total += generated; 45*9a92a6ceSJoonsoo Kim 46*9a92a6ceSJoonsoo Kim /* Assume that generated isn't a negative number */ 47*9a92a6ceSJoonsoo Kim if (generated >= size) { 48*9a92a6ceSJoonsoo Kim buf += size; 49*9a92a6ceSJoonsoo Kim size = 0; 50*9a92a6ceSJoonsoo Kim } else { 51*9a92a6ceSJoonsoo Kim buf += generated; 52*9a92a6ceSJoonsoo Kim size -= generated; 53*9a92a6ceSJoonsoo Kim } 54*9a92a6ceSJoonsoo Kim } 55*9a92a6ceSJoonsoo Kim 56*9a92a6ceSJoonsoo Kim return total; 57*9a92a6ceSJoonsoo Kim } 58*9a92a6ceSJoonsoo Kim EXPORT_SYMBOL_GPL(snprint_stack_trace); 59*9a92a6ceSJoonsoo Kim 609212ddb5SIngo Molnar /* 61c624d33fSMasami Hiramatsu * Architectures that do not implement save_stack_trace_tsk or 62c624d33fSMasami Hiramatsu * save_stack_trace_regs get this weak alias and a once-per-bootup warning 63c624d33fSMasami Hiramatsu * (whenever this facility is utilized - for example by procfs): 649212ddb5SIngo Molnar */ 659212ddb5SIngo Molnar __weak void 669212ddb5SIngo Molnar save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 679212ddb5SIngo Molnar { 689212ddb5SIngo Molnar WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n"); 699212ddb5SIngo Molnar } 70c624d33fSMasami Hiramatsu 71c624d33fSMasami Hiramatsu __weak void 72c624d33fSMasami Hiramatsu save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) 73c624d33fSMasami Hiramatsu { 74c624d33fSMasami Hiramatsu WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n"); 75c624d33fSMasami Hiramatsu } 76