This source file includes following definitions.
- unwind_frame
- walk_stackframe
- save_trace
- __save_stack_trace
- save_stack_trace_regs
- save_stack_trace_tsk
- save_stack_trace
   1 
   2 #include <linux/export.h>
   3 #include <linux/sched.h>
   4 #include <linux/sched/debug.h>
   5 #include <linux/stacktrace.h>
   6 
   7 #include <asm/sections.h>
   8 #include <asm/stacktrace.h>
   9 #include <asm/traps.h>
  10 
  11 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 int notrace unwind_frame(struct stackframe *frame)
  29 {
  30         unsigned long high, low;
  31         unsigned long fp = frame->fp;
  32 
  33         
  34         low = frame->sp;
  35         high = ALIGN(low, THREAD_SIZE);
  36 
  37         
  38         if (fp < low + 12 || fp > high - 4)
  39                 return -EINVAL;
  40 
  41         
  42         frame->fp = *(unsigned long *)(fp - 12);
  43         frame->sp = *(unsigned long *)(fp - 8);
  44         frame->pc = *(unsigned long *)(fp - 4);
  45 
  46         return 0;
  47 }
  48 #endif
  49 
  50 void notrace walk_stackframe(struct stackframe *frame,
  51                      int (*fn)(struct stackframe *, void *), void *data)
  52 {
  53         while (1) {
  54                 int ret;
  55 
  56                 if (fn(frame, data))
  57                         break;
  58                 ret = unwind_frame(frame);
  59                 if (ret < 0)
  60                         break;
  61         }
  62 }
  63 EXPORT_SYMBOL(walk_stackframe);
  64 
  65 #ifdef CONFIG_STACKTRACE
  66 struct stack_trace_data {
  67         struct stack_trace *trace;
  68         unsigned int no_sched_functions;
  69         unsigned int skip;
  70 };
  71 
  72 static int save_trace(struct stackframe *frame, void *d)
  73 {
  74         struct stack_trace_data *data = d;
  75         struct stack_trace *trace = data->trace;
  76         struct pt_regs *regs;
  77         unsigned long addr = frame->pc;
  78 
  79         if (data->no_sched_functions && in_sched_functions(addr))
  80                 return 0;
  81         if (data->skip) {
  82                 data->skip--;
  83                 return 0;
  84         }
  85 
  86         trace->entries[trace->nr_entries++] = addr;
  87 
  88         if (trace->nr_entries >= trace->max_entries)
  89                 return 1;
  90 
  91         if (!in_entry_text(frame->pc))
  92                 return 0;
  93 
  94         regs = (struct pt_regs *)frame->sp;
  95 
  96         trace->entries[trace->nr_entries++] = regs->ARM_pc;
  97 
  98         return trace->nr_entries >= trace->max_entries;
  99 }
 100 
 101 
 102 static noinline void __save_stack_trace(struct task_struct *tsk,
 103         struct stack_trace *trace, unsigned int nosched)
 104 {
 105         struct stack_trace_data data;
 106         struct stackframe frame;
 107 
 108         data.trace = trace;
 109         data.skip = trace->skip;
 110         data.no_sched_functions = nosched;
 111 
 112         if (tsk != current) {
 113 #ifdef CONFIG_SMP
 114                 
 115 
 116 
 117 
 118 
 119                 return;
 120 #else
 121                 frame.fp = thread_saved_fp(tsk);
 122                 frame.sp = thread_saved_sp(tsk);
 123                 frame.lr = 0;           
 124                 frame.pc = thread_saved_pc(tsk);
 125 #endif
 126         } else {
 127                 
 128                 data.skip += 2;
 129                 frame.fp = (unsigned long)__builtin_frame_address(0);
 130                 frame.sp = current_stack_pointer;
 131                 frame.lr = (unsigned long)__builtin_return_address(0);
 132                 frame.pc = (unsigned long)__save_stack_trace;
 133         }
 134 
 135         walk_stackframe(&frame, save_trace, &data);
 136 }
 137 
 138 void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
 139 {
 140         struct stack_trace_data data;
 141         struct stackframe frame;
 142 
 143         data.trace = trace;
 144         data.skip = trace->skip;
 145         data.no_sched_functions = 0;
 146 
 147         frame.fp = regs->ARM_fp;
 148         frame.sp = regs->ARM_sp;
 149         frame.lr = regs->ARM_lr;
 150         frame.pc = regs->ARM_pc;
 151 
 152         walk_stackframe(&frame, save_trace, &data);
 153 }
 154 
 155 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 156 {
 157         __save_stack_trace(tsk, trace, 1);
 158 }
 159 EXPORT_SYMBOL(save_stack_trace_tsk);
 160 
 161 void save_stack_trace(struct stack_trace *trace)
 162 {
 163         __save_stack_trace(current, trace, 0);
 164 }
 165 EXPORT_SYMBOL_GPL(save_stack_trace);
 166 #endif