1 /* 2 * kernel/stacktrace.c 3 * 4 * Stack trace management functions 5 * 6 * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <[email protected]> 7 */ 8 #include <linux/sched.h> 9 #include <linux/kernel.h> 10 #include <linux/export.h> 11 #include <linux/kallsyms.h> 12 #include <linux/stacktrace.h> 13 14 /** 15 * stack_trace_print - Print the entries in the stack trace 16 * @entries: Pointer to storage array 17 * @nr_entries: Number of entries in the storage array 18 * @spaces: Number of leading spaces to print 19 */ 20 void stack_trace_print(unsigned long *entries, unsigned int nr_entries, 21 int spaces) 22 { 23 unsigned int i; 24 25 if (WARN_ON(!entries)) 26 return; 27 28 for (i = 0; i < nr_entries; i++) 29 printk("%*c%pS\n", 1 + spaces, ' ', (void *)entries[i]); 30 } 31 EXPORT_SYMBOL_GPL(stack_trace_print); 32 33 /** 34 * stack_trace_snprint - Print the entries in the stack trace into a buffer 35 * @buf: Pointer to the print buffer 36 * @size: Size of the print buffer 37 * @entries: Pointer to storage array 38 * @nr_entries: Number of entries in the storage array 39 * @spaces: Number of leading spaces to print 40 * 41 * Return: Number of bytes printed. 42 */ 43 int stack_trace_snprint(char *buf, size_t size, unsigned long *entries, 44 unsigned int nr_entries, int spaces) 45 { 46 unsigned int generated, i, total = 0; 47 48 if (WARN_ON(!entries)) 49 return 0; 50 51 for (i = 0; i < nr_entries && size; i++) { 52 generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ', 53 (void *)entries[i]); 54 55 total += generated; 56 if (generated >= size) { 57 buf += size; 58 size = 0; 59 } else { 60 buf += generated; 61 size -= generated; 62 } 63 } 64 65 return total; 66 } 67 EXPORT_SYMBOL_GPL(stack_trace_snprint); 68 69 /* 70 * Architectures that do not implement save_stack_trace_*() 71 * get these weak aliases and once-per-bootup warnings 72 * (whenever this facility is utilized - for example by procfs): 73 */ 74 __weak void 75 save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 76 { 77 WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n"); 78 } 79 80 __weak void 81 save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) 82 { 83 WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n"); 84 } 85 86 __weak int 87 save_stack_trace_tsk_reliable(struct task_struct *tsk, 88 struct stack_trace *trace) 89 { 90 WARN_ONCE(1, KERN_INFO "save_stack_tsk_reliable() not implemented yet.\n"); 91 return -ENOSYS; 92 } 93 94 /** 95 * stack_trace_save - Save a stack trace into a storage array 96 * @store: Pointer to storage array 97 * @size: Size of the storage array 98 * @skipnr: Number of entries to skip at the start of the stack trace 99 * 100 * Return: Number of trace entries stored 101 */ 102 unsigned int stack_trace_save(unsigned long *store, unsigned int size, 103 unsigned int skipnr) 104 { 105 struct stack_trace trace = { 106 .entries = store, 107 .max_entries = size, 108 .skip = skipnr + 1, 109 }; 110 111 save_stack_trace(&trace); 112 return trace.nr_entries; 113 } 114 EXPORT_SYMBOL_GPL(stack_trace_save); 115 116 /** 117 * stack_trace_save_tsk - Save a task stack trace into a storage array 118 * @task: The task to examine 119 * @store: Pointer to storage array 120 * @size: Size of the storage array 121 * @skipnr: Number of entries to skip at the start of the stack trace 122 * 123 * Return: Number of trace entries stored 124 */ 125 unsigned int stack_trace_save_tsk(struct task_struct *task, 126 unsigned long *store, unsigned int size, 127 unsigned int skipnr) 128 { 129 struct stack_trace trace = { 130 .entries = store, 131 .max_entries = size, 132 .skip = skipnr + 1, 133 }; 134 135 save_stack_trace_tsk(task, &trace); 136 return trace.nr_entries; 137 } 138 139 /** 140 * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array 141 * @regs: Pointer to pt_regs to examine 142 * @store: Pointer to storage array 143 * @size: Size of the storage array 144 * @skipnr: Number of entries to skip at the start of the stack trace 145 * 146 * Return: Number of trace entries stored 147 */ 148 unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store, 149 unsigned int size, unsigned int skipnr) 150 { 151 struct stack_trace trace = { 152 .entries = store, 153 .max_entries = size, 154 .skip = skipnr, 155 }; 156 157 save_stack_trace_regs(regs, &trace); 158 return trace.nr_entries; 159 } 160 161 #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE 162 /** 163 * stack_trace_save_tsk_reliable - Save task stack with verification 164 * @tsk: Pointer to the task to examine 165 * @store: Pointer to storage array 166 * @size: Size of the storage array 167 * 168 * Return: An error if it detects any unreliable features of the 169 * stack. Otherwise it guarantees that the stack trace is 170 * reliable and returns the number of entries stored. 171 * 172 * If the task is not 'current', the caller *must* ensure the task is inactive. 173 */ 174 int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store, 175 unsigned int size) 176 { 177 struct stack_trace trace = { 178 .entries = store, 179 .max_entries = size, 180 }; 181 int ret = save_stack_trace_tsk_reliable(tsk, &trace); 182 183 return ret ? ret : trace.nr_entries; 184 } 185 #endif 186 187 #ifdef CONFIG_USER_STACKTRACE_SUPPORT 188 /** 189 * stack_trace_save_user - Save a user space stack trace into a storage array 190 * @store: Pointer to storage array 191 * @size: Size of the storage array 192 * 193 * Return: Number of trace entries stored 194 */ 195 unsigned int stack_trace_save_user(unsigned long *store, unsigned int size) 196 { 197 struct stack_trace trace = { 198 .entries = store, 199 .max_entries = size, 200 }; 201 202 save_stack_trace_user(&trace); 203 return trace.nr_entries; 204 } 205 #endif /* CONFIG_USER_STACKTRACE_SUPPORT */ 206