~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/kernel/stacktrace.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /kernel/stacktrace.c (Version linux-6.12-rc7) and /kernel/stacktrace.c (Version linux-4.15.18)


  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_*()
245  * get these weak aliases and once-per-bootup      58  * get these weak aliases and once-per-bootup warnings
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                                                    72 
260 /**                                            !!  73 __weak int
261  * stack_trace_save - Save a stack trace into  !!  74 save_stack_trace_tsk_reliable(struct task_struct *tsk,
262  * @store:      Pointer to storage array       !!  75                               struct stack_trace *trace)
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 {                                                  76 {
365         struct stack_trace trace = {           !!  77         WARN_ONCE(1, KERN_INFO "save_stack_tsk_reliable() not implemented yet.\n");
366                 .entries        = store,       !!  78         return -ENOSYS;
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 }                                                  79 }
404 EXPORT_SYMBOL_GPL(filter_irq_stacks);          << 
405                                                    80 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php