Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
0004  * Copyright (C) 2013 Richard Weinberger <richard@nod.at>
0005  * Copyright (C) 2014 Google Inc., Author: Daniel Walter <dwalter@google.com>
0006  */
0007 
0008 #include <linux/kallsyms.h>
0009 #include <linux/kernel.h>
0010 #include <linux/sched.h>
0011 #include <linux/stacktrace.h>
0012 #include <linux/module.h>
0013 #include <linux/uaccess.h>
0014 #include <asm/stacktrace.h>
0015 
0016 void dump_trace(struct task_struct *tsk,
0017         const struct stacktrace_ops *ops,
0018         void *data)
0019 {
0020     int reliable = 0;
0021     unsigned long *sp, bp, addr;
0022     struct pt_regs *segv_regs = tsk->thread.segv_regs;
0023     struct stack_frame *frame;
0024 
0025     bp = get_frame_pointer(tsk, segv_regs);
0026     sp = get_stack_pointer(tsk, segv_regs);
0027 
0028     frame = (struct stack_frame *)bp;
0029     while (((long) sp & (THREAD_SIZE-1)) != 0) {
0030         addr = READ_ONCE_NOCHECK(*sp);
0031         if (__kernel_text_address(addr)) {
0032             reliable = 0;
0033             if ((unsigned long) sp == bp + sizeof(long)) {
0034                 frame = frame ? frame->next_frame : NULL;
0035                 bp = (unsigned long)frame;
0036                 reliable = 1;
0037             }
0038             ops->address(data, addr, reliable);
0039         }
0040         sp++;
0041     }
0042 }
0043 
0044 static void save_addr(void *data, unsigned long address, int reliable)
0045 {
0046     struct stack_trace *trace = data;
0047 
0048     if (!reliable)
0049         return;
0050     if (trace->nr_entries >= trace->max_entries)
0051         return;
0052 
0053     trace->entries[trace->nr_entries++] = address;
0054 }
0055 
0056 static const struct stacktrace_ops dump_ops = {
0057     .address = save_addr
0058 };
0059 
0060 static void __save_stack_trace(struct task_struct *tsk, struct stack_trace *trace)
0061 {
0062     dump_trace(tsk, &dump_ops, trace);
0063 }
0064 
0065 void save_stack_trace(struct stack_trace *trace)
0066 {
0067     __save_stack_trace(current, trace);
0068 }
0069 EXPORT_SYMBOL_GPL(save_stack_trace);
0070 
0071 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
0072 {
0073     __save_stack_trace(tsk, trace);
0074 }
0075 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);