linux/arch/sh/kernel/stacktrace.c
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/stacktrace.c
   3 *
   4 * Stack trace management functions
   5 *
   6 *  Copyright (C) 2006 - 2008  Paul Mundt
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/sched.h>
  13#include <linux/sched/debug.h>
  14#include <linux/stacktrace.h>
  15#include <linux/thread_info.h>
  16#include <linux/module.h>
  17#include <asm/unwinder.h>
  18#include <asm/ptrace.h>
  19#include <asm/stacktrace.h>
  20
  21static int save_stack_stack(void *data, char *name)
  22{
  23        return 0;
  24}
  25
  26/*
  27 * Save stack-backtrace addresses into a stack_trace buffer.
  28 */
  29static void save_stack_address(void *data, unsigned long addr, int reliable)
  30{
  31        struct stack_trace *trace = data;
  32
  33        if (!reliable)
  34                return;
  35
  36        if (trace->skip > 0) {
  37                trace->skip--;
  38                return;
  39        }
  40
  41        if (trace->nr_entries < trace->max_entries)
  42                trace->entries[trace->nr_entries++] = addr;
  43}
  44
  45static const struct stacktrace_ops save_stack_ops = {
  46        .stack = save_stack_stack,
  47        .address = save_stack_address,
  48};
  49
  50void save_stack_trace(struct stack_trace *trace)
  51{
  52        unsigned long *sp = (unsigned long *)current_stack_pointer;
  53
  54        unwind_stack(current, NULL, sp,  &save_stack_ops, trace);
  55        if (trace->nr_entries < trace->max_entries)
  56                trace->entries[trace->nr_entries++] = ULONG_MAX;
  57}
  58EXPORT_SYMBOL_GPL(save_stack_trace);
  59
  60static void
  61save_stack_address_nosched(void *data, unsigned long addr, int reliable)
  62{
  63        struct stack_trace *trace = (struct stack_trace *)data;
  64
  65        if (!reliable)
  66                return;
  67
  68        if (in_sched_functions(addr))
  69                return;
  70
  71        if (trace->skip > 0) {
  72                trace->skip--;
  73                return;
  74        }
  75
  76        if (trace->nr_entries < trace->max_entries)
  77                trace->entries[trace->nr_entries++] = addr;
  78}
  79
  80static const struct stacktrace_ops save_stack_ops_nosched = {
  81        .stack = save_stack_stack,
  82        .address = save_stack_address_nosched,
  83};
  84
  85void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  86{
  87        unsigned long *sp = (unsigned long *)tsk->thread.sp;
  88
  89        unwind_stack(current, NULL, sp,  &save_stack_ops_nosched, trace);
  90        if (trace->nr_entries < trace->max_entries)
  91                trace->entries[trace->nr_entries++] = ULONG_MAX;
  92}
  93EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
  94