LCOV - code coverage report
Current view: top level - kernel - stacktrace.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 45 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 8 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * kernel/stacktrace.c
       4             :  *
       5             :  * Stack trace management functions
       6             :  *
       7             :  *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
       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 the stack trace
      20             :  * @entries:    Pointer to storage array
      21             :  * @nr_entries: Number of entries in the storage array
      22             :  * @spaces:     Number of leading spaces to print
      23             :  */
      24           0 : void stack_trace_print(const unsigned long *entries, unsigned int nr_entries,
      25             :                        int spaces)
      26             : {
      27             :         unsigned int i;
      28             : 
      29           0 :         if (WARN_ON(!entries))
      30             :                 return;
      31             : 
      32           0 :         for (i = 0; i < nr_entries; i++)
      33           0 :                 printk("%*c%pS\n", 1 + spaces, ' ', (void *)entries[i]);
      34             : }
      35             : EXPORT_SYMBOL_GPL(stack_trace_print);
      36             : 
      37             : /**
      38             :  * stack_trace_snprint - Print the entries in the stack trace into a buffer
      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 storage array
      43             :  * @spaces:     Number of leading spaces to print
      44             :  *
      45             :  * Return: Number of bytes printed.
      46             :  */
      47           0 : int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries,
      48             :                         unsigned int nr_entries, int spaces)
      49             : {
      50           0 :         unsigned int generated, i, total = 0;
      51             : 
      52           0 :         if (WARN_ON(!entries))
      53             :                 return 0;
      54             : 
      55           0 :         for (i = 0; i < nr_entries && size; i++) {
      56           0 :                 generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ',
      57           0 :                                      (void *)entries[i]);
      58             : 
      59           0 :                 total += generated;
      60           0 :                 if (generated >= size) {
      61           0 :                         buf += size;
      62           0 :                         size = 0;
      63             :                 } else {
      64           0 :                         buf += generated;
      65           0 :                         size -= generated;
      66             :                 }
      67             :         }
      68             : 
      69           0 :         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 *cookie, unsigned long addr)
      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(void *cookie, unsigned long addr)
      98             : {
      99             :         if (in_sched_functions(addr))
     100             :                 return true;
     101             :         return stack_trace_consume_entry(cookie, addr);
     102             : }
     103             : 
     104             : /**
     105             :  * stack_trace_save - Save a stack trace into a storage array
     106             :  * @store:      Pointer to storage array
     107             :  * @size:       Size of the storage array
     108             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     109             :  *
     110             :  * Return: Number of trace entries stored.
     111             :  */
     112             : unsigned int stack_trace_save(unsigned long *store, unsigned int size,
     113             :                               unsigned int skipnr)
     114             : {
     115             :         stack_trace_consume_fn consume_entry = stack_trace_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, current, NULL);
     123             :         return c.len;
     124             : }
     125             : EXPORT_SYMBOL_GPL(stack_trace_save);
     126             : 
     127             : /**
     128             :  * stack_trace_save_tsk - Save a task stack trace into a storage array
     129             :  * @task:       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 the start of the stack trace
     133             :  *
     134             :  * Return: Number of trace entries stored.
     135             :  */
     136             : unsigned int stack_trace_save_tsk(struct task_struct *tsk, unsigned long *store,
     137             :                                   unsigned int size, unsigned int skipnr)
     138             : {
     139             :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry_nosched;
     140             :         struct stacktrace_cookie c = {
     141             :                 .store  = store,
     142             :                 .size   = size,
     143             :                 /* skip this function if they are tracing us */
     144             :                 .skip   = skipnr + (current == tsk),
     145             :         };
     146             : 
     147             :         if (!try_get_task_stack(tsk))
     148             :                 return 0;
     149             : 
     150             :         arch_stack_walk(consume_entry, &c, tsk, NULL);
     151             :         put_task_stack(tsk);
     152             :         return c.len;
     153             : }
     154             : 
     155             : /**
     156             :  * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array
     157             :  * @regs:       Pointer to pt_regs to examine
     158             :  * @store:      Pointer to storage array
     159             :  * @size:       Size of the storage array
     160             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     161             :  *
     162             :  * Return: Number of trace entries stored.
     163             :  */
     164             : unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
     165             :                                    unsigned int size, unsigned int skipnr)
     166             : {
     167             :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
     168             :         struct stacktrace_cookie c = {
     169             :                 .store  = store,
     170             :                 .size   = size,
     171             :                 .skip   = skipnr,
     172             :         };
     173             : 
     174             :         arch_stack_walk(consume_entry, &c, current, regs);
     175             :         return c.len;
     176             : }
     177             : 
     178             : #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
     179             : /**
     180             :  * stack_trace_save_tsk_reliable - Save task stack with verification
     181             :  * @tsk:        Pointer to the task to examine
     182             :  * @store:      Pointer to storage array
     183             :  * @size:       Size of the storage array
     184             :  *
     185             :  * Return:      An error if it detects any unreliable features of the
     186             :  *              stack. Otherwise it guarantees that the stack trace is
     187             :  *              reliable and returns the number of entries stored.
     188             :  *
     189             :  * If the task is not 'current', the caller *must* ensure the task is inactive.
     190             :  */
     191             : int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store,
     192             :                                   unsigned int size)
     193             : {
     194             :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
     195             :         struct stacktrace_cookie c = {
     196             :                 .store  = store,
     197             :                 .size   = size,
     198             :         };
     199             :         int ret;
     200             : 
     201             :         /*
     202             :          * If the task doesn't have a stack (e.g., a zombie), the stack is
     203             :          * "reliably" empty.
     204             :          */
     205             :         if (!try_get_task_stack(tsk))
     206             :                 return 0;
     207             : 
     208             :         ret = arch_stack_walk_reliable(consume_entry, &c, tsk);
     209             :         put_task_stack(tsk);
     210             :         return ret ? ret : c.len;
     211             : }
     212             : #endif
     213             : 
     214             : #ifdef CONFIG_USER_STACKTRACE_SUPPORT
     215             : /**
     216             :  * stack_trace_save_user - Save a user space stack trace into a storage array
     217             :  * @store:      Pointer to storage array
     218             :  * @size:       Size of the storage array
     219             :  *
     220             :  * Return: Number of trace entries stored.
     221             :  */
     222             : unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
     223             : {
     224             :         stack_trace_consume_fn consume_entry = stack_trace_consume_entry;
     225             :         struct stacktrace_cookie c = {
     226             :                 .store  = store,
     227             :                 .size   = size,
     228             :         };
     229             : 
     230             :         /* Trace user stack if not a kernel thread */
     231             :         if (current->flags & PF_KTHREAD)
     232             :                 return 0;
     233             : 
     234             :         arch_stack_walk_user(consume_entry, &c, task_pt_regs(current));
     235             : 
     236             :         return c.len;
     237             : }
     238             : #endif
     239             : 
     240             : #else /* CONFIG_ARCH_STACKWALK */
     241             : 
     242             : /*
     243             :  * Architectures that do not implement save_stack_trace_*()
     244             :  * get these weak aliases and once-per-bootup warnings
     245             :  * (whenever this facility is utilized - for example by procfs):
     246             :  */
     247             : __weak void
     248           0 : save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
     249             : {
     250           0 :         WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n");
     251           0 : }
     252             : 
     253             : __weak void
     254           0 : save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
     255             : {
     256           0 :         WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n");
     257           0 : }
     258             : 
     259             : /**
     260             :  * stack_trace_save - Save a stack trace into a storage array
     261             :  * @store:      Pointer to storage array
     262             :  * @size:       Size of the storage array
     263             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     264             :  *
     265             :  * Return: Number of trace entries stored
     266             :  */
     267           0 : unsigned int stack_trace_save(unsigned long *store, unsigned int size,
     268             :                               unsigned int skipnr)
     269             : {
     270           0 :         struct stack_trace trace = {
     271             :                 .entries        = store,
     272             :                 .max_entries    = size,
     273           0 :                 .skip           = skipnr + 1,
     274             :         };
     275             : 
     276           0 :         save_stack_trace(&trace);
     277           0 :         return trace.nr_entries;
     278             : }
     279             : EXPORT_SYMBOL_GPL(stack_trace_save);
     280             : 
     281             : /**
     282             :  * stack_trace_save_tsk - Save a task stack trace into a storage array
     283             :  * @task:       The task to examine
     284             :  * @store:      Pointer to storage array
     285             :  * @size:       Size of the storage array
     286             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     287             :  *
     288             :  * Return: Number of trace entries stored
     289             :  */
     290           0 : unsigned int stack_trace_save_tsk(struct task_struct *task,
     291             :                                   unsigned long *store, unsigned int size,
     292             :                                   unsigned int skipnr)
     293             : {
     294           0 :         struct stack_trace trace = {
     295             :                 .entries        = store,
     296             :                 .max_entries    = size,
     297             :                 /* skip this function if they are tracing us */
     298           0 :                 .skip   = skipnr + (current == task),
     299             :         };
     300             : 
     301           0 :         save_stack_trace_tsk(task, &trace);
     302           0 :         return trace.nr_entries;
     303             : }
     304             : 
     305             : /**
     306             :  * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array
     307             :  * @regs:       Pointer to pt_regs to examine
     308             :  * @store:      Pointer to storage array
     309             :  * @size:       Size of the storage array
     310             :  * @skipnr:     Number of entries to skip at the start of the stack trace
     311             :  *
     312             :  * Return: Number of trace entries stored
     313             :  */
     314           0 : unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store,
     315             :                                    unsigned int size, unsigned int skipnr)
     316             : {
     317           0 :         struct stack_trace trace = {
     318             :                 .entries        = store,
     319             :                 .max_entries    = size,
     320             :                 .skip           = skipnr,
     321             :         };
     322             : 
     323           0 :         save_stack_trace_regs(regs, &trace);
     324           0 :         return trace.nr_entries;
     325             : }
     326             : 
     327             : #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE
     328             : /**
     329             :  * stack_trace_save_tsk_reliable - Save task stack with verification
     330             :  * @tsk:        Pointer to the task to examine
     331             :  * @store:      Pointer to storage array
     332             :  * @size:       Size of the storage array
     333             :  *
     334             :  * Return:      An error if it detects any unreliable features of the
     335             :  *              stack. Otherwise it guarantees that the stack trace is
     336             :  *              reliable and returns the number of entries stored.
     337             :  *
     338             :  * If the task is not 'current', the caller *must* ensure the task is inactive.
     339             :  */
     340             : int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store,
     341             :                                   unsigned int size)
     342             : {
     343             :         struct stack_trace trace = {
     344             :                 .entries        = store,
     345             :                 .max_entries    = size,
     346             :         };
     347             :         int ret = save_stack_trace_tsk_reliable(tsk, &trace);
     348             : 
     349             :         return ret ? ret : trace.nr_entries;
     350             : }
     351             : #endif
     352             : 
     353             : #ifdef CONFIG_USER_STACKTRACE_SUPPORT
     354             : /**
     355             :  * stack_trace_save_user - Save a user space stack trace into a storage array
     356             :  * @store:      Pointer to storage array
     357             :  * @size:       Size of the storage array
     358             :  *
     359             :  * Return: Number of trace entries stored
     360             :  */
     361             : unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
     362             : {
     363             :         struct stack_trace trace = {
     364             :                 .entries        = store,
     365             :                 .max_entries    = size,
     366             :         };
     367             : 
     368             :         save_stack_trace_user(&trace);
     369             :         return trace.nr_entries;
     370             : }
     371             : #endif /* CONFIG_USER_STACKTRACE_SUPPORT */
     372             : 
     373             : #endif /* !CONFIG_ARCH_STACKWALK */
     374             : 
     375             : static inline bool in_irqentry_text(unsigned long ptr)
     376             : {
     377           0 :         return (ptr >= (unsigned long)&__irqentry_text_start &&
     378           0 :                 ptr < (unsigned long)&__irqentry_text_end) ||
     379           0 :                 (ptr >= (unsigned long)&__softirqentry_text_start &&
     380           0 :                  ptr < (unsigned long)&__softirqentry_text_end);
     381             : }
     382             : 
     383             : /**
     384             :  * filter_irq_stacks - Find first IRQ stack entry in trace
     385             :  * @entries:    Pointer to stack trace array
     386             :  * @nr_entries: Number of entries in the storage array
     387             :  *
     388             :  * Return: Number of trace entries until IRQ stack starts.
     389             :  */
     390           0 : unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries)
     391             : {
     392             :         unsigned int i;
     393             : 
     394           0 :         for (i = 0; i < nr_entries; i++) {
     395           0 :                 if (in_irqentry_text(entries[i])) {
     396             :                         /* Include the irqentry function into the stack. */
     397           0 :                         return i + 1;
     398             :                 }
     399             :         }
     400             :         return nr_entries;
     401             : }
     402             : EXPORT_SYMBOL_GPL(filter_irq_stacks);

Generated by: LCOV version 1.14