1 // SPDX-License-Identifier: GPL-2.0-only << 2 /* 1 /* 3 * kernel/stacktrace.c 2 * kernel/stacktrace.c 4 * 3 * 5 * Stack trace management functions 4 * Stack trace management functions 6 * 5 * 7 * Copyright (C) 2006 Red Hat, Inc., Ingo Mol 6 * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> 8 */ 7 */ 9 #include <linux/sched/task_stack.h> << 10 #include <linux/sched/debug.h> << 11 #include <linux/sched.h> 8 #include <linux/sched.h> 12 #include <linux/kernel.h> 9 #include <linux/kernel.h> 13 #include <linux/export.h> 10 #include <linux/export.h> 14 #include <linux/kallsyms.h> 11 #include <linux/kallsyms.h> 15 #include <linux/stacktrace.h> 12 #include <linux/stacktrace.h> 16 #include <linux/interrupt.h> << 17 13 18 /** !! 14 void print_stack_trace(struct stack_trace *trace, int spaces) 19 * stack_trace_print - Print the entries in th << 20 * @entries: Pointer to storage array << 21 * @nr_entries: Number of entries in the stora << 22 * @spaces: Number of leading spaces to pr << 23 */ << 24 void stack_trace_print(const unsigned long *en << 25 int spaces) << 26 { 15 { 27 unsigned int i; !! 16 int i; 28 17 29 if (WARN_ON(!entries)) !! 18 if (WARN_ON(!trace->entries)) 30 return; 19 return; 31 20 32 for (i = 0; i < nr_entries; i++) !! 21 for (i = 0; i < trace->nr_entries; i++) 33 printk("%*c%pS\n", 1 + spaces, !! 22 printk("%*c%pS\n", 1 + spaces, ' ', (void *)trace->entries[i]); 34 } 23 } 35 EXPORT_SYMBOL_GPL(stack_trace_print); !! 24 EXPORT_SYMBOL_GPL(print_stack_trace); 36 25 37 /** !! 26 int snprint_stack_trace(char *buf, size_t size, 38 * stack_trace_snprint - Print the entries in !! 27 struct stack_trace *trace, int spaces) 39 * @buf: Pointer to the print buffer << 40 * @size: Size of the print buffer << 41 * @entries: Pointer to storage array << 42 * @nr_entries: Number of entries in the stora << 43 * @spaces: Number of leading spaces to pr << 44 * << 45 * Return: Number of bytes printed. << 46 */ << 47 int stack_trace_snprint(char *buf, size_t size << 48 unsigned int nr_entrie << 49 { 28 { 50 unsigned int generated, i, total = 0; !! 29 int i; >> 30 int generated; >> 31 int total = 0; 51 32 52 if (WARN_ON(!entries)) !! 33 if (WARN_ON(!trace->entries)) 53 return 0; 34 return 0; 54 35 55 for (i = 0; i < nr_entries && size; i+ !! 36 for (i = 0; i < trace->nr_entries; i++) { 56 generated = snprintf(buf, size 37 generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ', 57 (void *)e !! 38 (void *)trace->entries[i]); 58 39 59 total += generated; 40 total += generated; >> 41 >> 42 /* Assume that generated isn't a negative number */ 60 if (generated >= size) { 43 if (generated >= size) { 61 buf += size; 44 buf += size; 62 size = 0; 45 size = 0; 63 } else { 46 } else { 64 buf += generated; 47 buf += generated; 65 size -= generated; 48 size -= generated; 66 } 49 } 67 } 50 } 68 51 69 return total; 52 return total; 70 } 53 } 71 EXPORT_SYMBOL_GPL(stack_trace_snprint); !! 54 EXPORT_SYMBOL_GPL(snprint_stack_trace); 72 << 73 #ifdef CONFIG_ARCH_STACKWALK << 74 << 75 struct stacktrace_cookie { << 76 unsigned long *store; << 77 unsigned int size; << 78 unsigned int skip; << 79 unsigned int len; << 80 }; << 81 << 82 static bool stack_trace_consume_entry(void *co << 83 { << 84 struct stacktrace_cookie *c = cookie; << 85 << 86 if (c->len >= c->size) << 87 return false; << 88 << 89 if (c->skip > 0) { << 90 c->skip--; << 91 return true; << 92 } << 93 c->store[c->len++] = addr; << 94 return c->len < c->size; << 95 } << 96 << 97 static bool stack_trace_consume_entry_nosched( << 98 { << 99 if (in_sched_functions(addr)) << 100 return true; << 101 return stack_trace_consume_entry(cooki << 102 } << 103 << 104 /** << 105 * stack_trace_save - Save a stack trace into << 106 * @store: Pointer to storage array << 107 * @size: Size of the storage array << 108 * @skipnr: Number of entries to skip at t << 109 * << 110 * Return: Number of trace entries stored. << 111 */ << 112 unsigned int stack_trace_save(unsigned long *s << 113 unsigned int ski << 114 { << 115 stack_trace_consume_fn consume_entry = << 116 struct stacktrace_cookie c = { << 117 .store = store, << 118 .size = size, << 119 .skip = skipnr + 1, << 120 }; << 121 << 122 arch_stack_walk(consume_entry, &c, cur << 123 return c.len; << 124 } << 125 EXPORT_SYMBOL_GPL(stack_trace_save); << 126 << 127 /** << 128 * stack_trace_save_tsk - Save a task stack tr << 129 * @tsk: The task to examine << 130 * @store: Pointer to storage array << 131 * @size: Size of the storage array << 132 * @skipnr: Number of entries to skip at t << 133 * << 134 * Return: Number of trace entries stored. << 135 */ << 136 unsigned int stack_trace_save_tsk(struct task_ << 137 unsigned int << 138 { << 139 stack_trace_consume_fn consume_entry = << 140 struct stacktrace_cookie c = { << 141 .store = store, << 142 .size = size, << 143 /* skip this function if they << 144 .skip = skipnr + (current == << 145 }; << 146 << 147 if (!try_get_task_stack(tsk)) << 148 return 0; << 149 << 150 arch_stack_walk(consume_entry, &c, tsk << 151 put_task_stack(tsk); << 152 return c.len; << 153 } << 154 EXPORT_SYMBOL_GPL(stack_trace_save_tsk); << 155 << 156 /** << 157 * stack_trace_save_regs - Save a stack trace << 158 * @regs: Pointer to pt_regs to examine << 159 * @store: Pointer to storage array << 160 * @size: Size of the storage array << 161 * @skipnr: Number of entries to skip at t << 162 * << 163 * Return: Number of trace entries stored. << 164 */ << 165 unsigned int stack_trace_save_regs(struct pt_r << 166 unsigned in << 167 { << 168 stack_trace_consume_fn consume_entry = << 169 struct stacktrace_cookie c = { << 170 .store = store, << 171 .size = size, << 172 .skip = skipnr, << 173 }; << 174 << 175 arch_stack_walk(consume_entry, &c, cur << 176 return c.len; << 177 } << 178 << 179 #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE << 180 /** << 181 * stack_trace_save_tsk_reliable - Save task s << 182 * @tsk: Pointer to the task to examine << 183 * @store: Pointer to storage array << 184 * @size: Size of the storage array << 185 * << 186 * Return: An error if it detects any unr << 187 * stack. Otherwise it guarantees << 188 * reliable and returns the numbe << 189 * << 190 * If the task is not 'current', the caller *m << 191 */ << 192 int stack_trace_save_tsk_reliable(struct task_ << 193 unsigned int << 194 { << 195 stack_trace_consume_fn consume_entry = << 196 struct stacktrace_cookie c = { << 197 .store = store, << 198 .size = size, << 199 }; << 200 int ret; << 201 << 202 /* << 203 * If the task doesn't have a stack (e << 204 * "reliably" empty. << 205 */ << 206 if (!try_get_task_stack(tsk)) << 207 return 0; << 208 << 209 ret = arch_stack_walk_reliable(consume << 210 put_task_stack(tsk); << 211 return ret ? ret : c.len; << 212 } << 213 #endif << 214 << 215 #ifdef CONFIG_USER_STACKTRACE_SUPPORT << 216 /** << 217 * stack_trace_save_user - Save a user space s << 218 * @store: Pointer to storage array << 219 * @size: Size of the storage array << 220 * << 221 * Return: Number of trace entries stored. << 222 */ << 223 unsigned int stack_trace_save_user(unsigned lo << 224 { << 225 stack_trace_consume_fn consume_entry = << 226 struct stacktrace_cookie c = { << 227 .store = store, << 228 .size = size, << 229 }; << 230 << 231 /* Trace user stack if not a kernel th << 232 if (current->flags & PF_KTHREAD) << 233 return 0; << 234 << 235 arch_stack_walk_user(consume_entry, &c << 236 << 237 return c.len; << 238 } << 239 #endif << 240 << 241 #else /* CONFIG_ARCH_STACKWALK */ << 242 55 243 /* 56 /* 244 * Architectures that do not implement save_st !! 57 * Architectures that do not implement save_stack_trace_tsk or 245 * get these weak aliases and once-per-bootup !! 58 * save_stack_trace_regs get this weak alias and a once-per-bootup warning 246 * (whenever this facility is utilized - for e 59 * (whenever this facility is utilized - for example by procfs): 247 */ 60 */ 248 __weak void 61 __weak void 249 save_stack_trace_tsk(struct task_struct *tsk, 62 save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 250 { 63 { 251 WARN_ONCE(1, KERN_INFO "save_stack_tra 64 WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n"); 252 } 65 } 253 66 254 __weak void 67 __weak void 255 save_stack_trace_regs(struct pt_regs *regs, st 68 save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) 256 { 69 { 257 WARN_ONCE(1, KERN_INFO "save_stack_tra 70 WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n"); 258 } 71 } 259 << 260 /** << 261 * stack_trace_save - Save a stack trace into << 262 * @store: Pointer to storage array << 263 * @size: Size of the storage array << 264 * @skipnr: Number of entries to skip at t << 265 * << 266 * Return: Number of trace entries stored << 267 */ << 268 unsigned int stack_trace_save(unsigned long *s << 269 unsigned int ski << 270 { << 271 struct stack_trace trace = { << 272 .entries = store, << 273 .max_entries = size, << 274 .skip = skipnr + 1, << 275 }; << 276 << 277 save_stack_trace(&trace); << 278 return trace.nr_entries; << 279 } << 280 EXPORT_SYMBOL_GPL(stack_trace_save); << 281 << 282 /** << 283 * stack_trace_save_tsk - Save a task stack tr << 284 * @task: The task to examine << 285 * @store: Pointer to storage array << 286 * @size: Size of the storage array << 287 * @skipnr: Number of entries to skip at t << 288 * << 289 * Return: Number of trace entries stored << 290 */ << 291 unsigned int stack_trace_save_tsk(struct task_ << 292 unsigned lon << 293 unsigned int << 294 { << 295 struct stack_trace trace = { << 296 .entries = store, << 297 .max_entries = size, << 298 /* skip this function if they << 299 .skip = skipnr + (current == << 300 }; << 301 << 302 save_stack_trace_tsk(task, &trace); << 303 return trace.nr_entries; << 304 } << 305 EXPORT_SYMBOL_GPL(stack_trace_save_tsk); << 306 << 307 /** << 308 * stack_trace_save_regs - Save a stack trace << 309 * @regs: Pointer to pt_regs to examine << 310 * @store: Pointer to storage array << 311 * @size: Size of the storage array << 312 * @skipnr: Number of entries to skip at t << 313 * << 314 * Return: Number of trace entries stored << 315 */ << 316 unsigned int stack_trace_save_regs(struct pt_r << 317 unsigned in << 318 { << 319 struct stack_trace trace = { << 320 .entries = store, << 321 .max_entries = size, << 322 .skip = skipnr, << 323 }; << 324 << 325 save_stack_trace_regs(regs, &trace); << 326 return trace.nr_entries; << 327 } << 328 << 329 #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE << 330 /** << 331 * stack_trace_save_tsk_reliable - Save task s << 332 * @tsk: Pointer to the task to examine << 333 * @store: Pointer to storage array << 334 * @size: Size of the storage array << 335 * << 336 * Return: An error if it detects any unr << 337 * stack. Otherwise it guarantees << 338 * reliable and returns the numbe << 339 * << 340 * If the task is not 'current', the caller *m << 341 */ << 342 int stack_trace_save_tsk_reliable(struct task_ << 343 unsigned int << 344 { << 345 struct stack_trace trace = { << 346 .entries = store, << 347 .max_entries = size, << 348 }; << 349 int ret = save_stack_trace_tsk_reliabl << 350 << 351 return ret ? ret : trace.nr_entries; << 352 } << 353 #endif << 354 << 355 #ifdef CONFIG_USER_STACKTRACE_SUPPORT << 356 /** << 357 * stack_trace_save_user - Save a user space s << 358 * @store: Pointer to storage array << 359 * @size: Size of the storage array << 360 * << 361 * Return: Number of trace entries stored << 362 */ << 363 unsigned int stack_trace_save_user(unsigned lo << 364 { << 365 struct stack_trace trace = { << 366 .entries = store, << 367 .max_entries = size, << 368 }; << 369 << 370 save_stack_trace_user(&trace); << 371 return trace.nr_entries; << 372 } << 373 #endif /* CONFIG_USER_STACKTRACE_SUPPORT */ << 374 << 375 #endif /* !CONFIG_ARCH_STACKWALK */ << 376 << 377 static inline bool in_irqentry_text(unsigned l << 378 { << 379 return (ptr >= (unsigned long)&__irqen << 380 ptr < (unsigned long)&__irqent << 381 (ptr >= (unsigned long)&__soft << 382 ptr < (unsigned long)&__softi << 383 } << 384 << 385 /** << 386 * filter_irq_stacks - Find first IRQ stack en << 387 * @entries: Pointer to stack trace array << 388 * @nr_entries: Number of entries in the stora << 389 * << 390 * Return: Number of trace entries until IRQ s << 391 */ << 392 unsigned int filter_irq_stacks(unsigned long * << 393 { << 394 unsigned int i; << 395 << 396 for (i = 0; i < nr_entries; i++) { << 397 if (in_irqentry_text(entries[i << 398 /* Include the irqentr << 399 return i + 1; << 400 } << 401 } << 402 return nr_entries; << 403 } << 404 EXPORT_SYMBOL_GPL(filter_irq_stacks); << 405 72
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.