~ [ 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.19.322)


** Warning: Cannot open xref database.

  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  * kernel/stacktrace.c                            
  4  *                                                
  5  * Stack trace management functions               
  6  *                                                
  7  *  Copyright (C) 2006 Red Hat, Inc., Ingo Mol    
  8  */                                               
  9 #include <linux/sched/task_stack.h>               
 10 #include <linux/sched/debug.h>                    
 11 #include <linux/sched.h>                          
 12 #include <linux/kernel.h>                         
 13 #include <linux/export.h>                         
 14 #include <linux/kallsyms.h>                       
 15 #include <linux/stacktrace.h>                     
 16 #include <linux/interrupt.h>                      
 17                                                   
 18 /**                                               
 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 {                                                 
 27         unsigned int i;                           
 28                                                   
 29         if (WARN_ON(!entries))                    
 30                 return;                           
 31                                                   
 32         for (i = 0; i < nr_entries; i++)          
 33                 printk("%*c%pS\n", 1 + spaces,    
 34 }                                                 
 35 EXPORT_SYMBOL_GPL(stack_trace_print);             
 36                                                   
 37 /**                                               
 38  * stack_trace_snprint - Print the entries in     
 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 {                                                 
 50         unsigned int generated, i, total = 0;     
 51                                                   
 52         if (WARN_ON(!entries))                    
 53                 return 0;                         
 54                                                   
 55         for (i = 0; i < nr_entries && size; i+    
 56                 generated = snprintf(buf, size    
 57                                      (void *)e    
 58                                                   
 59                 total += generated;               
 60                 if (generated >= size) {          
 61                         buf += size;              
 62                         size = 0;                 
 63                 } else {                          
 64                         buf += generated;         
 65                         size -= generated;        
 66                 }                                 
 67         }                                         
 68                                                   
 69         return total;                             
 70 }                                                 
 71 EXPORT_SYMBOL_GPL(stack_trace_snprint);           
 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                                                   
243 /*                                                
244  * Architectures that do not implement save_st    
245  * get these weak aliases and once-per-bootup     
246  * (whenever this facility is utilized - for e    
247  */                                               
248 __weak void                                       
249 save_stack_trace_tsk(struct task_struct *tsk,     
250 {                                                 
251         WARN_ONCE(1, KERN_INFO "save_stack_tra    
252 }                                                 
253                                                   
254 __weak void                                       
255 save_stack_trace_regs(struct pt_regs *regs, st    
256 {                                                 
257         WARN_ONCE(1, KERN_INFO "save_stack_tra    
258 }                                                 
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                                                   

~ [ 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