root/arch/openrisc/kernel/unwinder.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. or1k_frameinfo_valid
  2. unwind_stack
  3. unwind_stack

   1 /*
   2  * OpenRISC unwinder.c
   3  *
   4  * Reusable arch specific api for unwinding stacks.
   5  *
   6  * Copyright (C) 2017 Stafford Horne <shorne@gmail.com>
   7  *
   8  * This file is licensed under the terms of the GNU General Public License
   9  * version 2.  This program is licensed "as is" without any warranty of any
  10  * kind, whether express or implied.
  11  */
  12 
  13 #include <linux/sched/task_stack.h>
  14 #include <linux/kernel.h>
  15 
  16 #include <asm/unwinder.h>
  17 
  18 #ifdef CONFIG_FRAME_POINTER
  19 struct or1k_frameinfo {
  20         unsigned long *fp;
  21         unsigned long ra;
  22         unsigned long top;
  23 };
  24 
  25 /*
  26  * Verify a frameinfo structure.  The return address should be a valid text
  27  * address.  The frame pointer may be null if its the last frame, otherwise
  28  * the frame pointer should point to a location in the stack after the the
  29  * top of the next frame up.
  30  */
  31 static inline int or1k_frameinfo_valid(struct or1k_frameinfo *frameinfo)
  32 {
  33         return (frameinfo->fp == NULL ||
  34                 (!kstack_end(frameinfo->fp) &&
  35                  frameinfo->fp > &frameinfo->top)) &&
  36                __kernel_text_address(frameinfo->ra);
  37 }
  38 
  39 /*
  40  * Create a stack trace doing scanning which is frame pointer aware. We can
  41  * get reliable stack traces by matching the previously found frame
  42  * pointer with the top of the stack address every time we find a valid
  43  * or1k_frameinfo.
  44  *
  45  * Ideally the stack parameter will be passed as FP, but it can not be
  46  * guaranteed.  Therefore we scan each address looking for the first sign
  47  * of a return address.
  48  *
  49  * The OpenRISC stack frame looks something like the following.  The
  50  * location SP is held in r1 and location FP is held in r2 when frame pointers
  51  * enabled.
  52  *
  53  * SP   -> (top of stack)
  54  *      -  (callee saved registers)
  55  *      -  (local variables)
  56  * FP-8 -> previous FP             \
  57  * FP-4 -> return address          |- or1k_frameinfo
  58  * FP   -> (previous top of stack) /
  59  */
  60 void unwind_stack(void *data, unsigned long *stack,
  61                   void (*trace)(void *data, unsigned long addr, int reliable))
  62 {
  63         unsigned long *next_fp = NULL;
  64         struct or1k_frameinfo *frameinfo = NULL;
  65         int reliable = 0;
  66 
  67         while (!kstack_end(stack)) {
  68                 frameinfo = container_of(stack,
  69                                          struct or1k_frameinfo,
  70                                          top);
  71 
  72                 if (__kernel_text_address(frameinfo->ra)) {
  73                         if (or1k_frameinfo_valid(frameinfo) &&
  74                             (next_fp == NULL ||
  75                              next_fp == &frameinfo->top)) {
  76                                 reliable = 1;
  77                                 next_fp = frameinfo->fp;
  78                         } else
  79                                 reliable = 0;
  80 
  81                         trace(data, frameinfo->ra, reliable);
  82                 }
  83                 stack++;
  84         }
  85 }
  86 
  87 #else /* CONFIG_FRAME_POINTER */
  88 
  89 /*
  90  * Create a stack trace by doing a simple scan treating all text addresses
  91  * as return addresses.
  92  */
  93 void unwind_stack(void *data, unsigned long *stack,
  94                    void (*trace)(void *data, unsigned long addr, int reliable))
  95 {
  96         unsigned long addr;
  97 
  98         while (!kstack_end(stack)) {
  99                 addr = *stack++;
 100                 if (__kernel_text_address(addr))
 101                         trace(data, addr, 0);
 102         }
 103 }
 104 #endif /* CONFIG_FRAME_POINTER */
 105 

/* [<][>][^][v][top][bottom][index][help] */