1 /* 1 2 * OpenRISC unwinder.c 3 * 4 * Reusable arch specific api for unwinding st 5 * 6 * Copyright (C) 2017 Stafford Horne <shorne@g 7 * 8 * This file is licensed under the terms of th 9 * version 2. This program is licensed "as is 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 a 27 * address. The frame pointer may be null if 28 * the frame pointer should point to a locatio 29 * top of the next frame up. 30 */ 31 static inline int or1k_frameinfo_valid(struct 32 { 33 return (frameinfo->fp == NULL || 34 (!kstack_end(frameinfo->fp) && 35 frameinfo->fp > &frameinfo->t 36 __kernel_text_address(frameinfo 37 } 38 39 /* 40 * Create a stack trace doing scanning which i 41 * get reliable stack traces by matching the p 42 * pointer with the top of the stack address e 43 * or1k_frameinfo. 44 * 45 * Ideally the stack parameter will be passed 46 * guaranteed. Therefore we scan each address 47 * of a return address. 48 * 49 * The OpenRISC stack frame looks something li 50 * location SP is held in r1 and location FP i 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_fra 58 * FP -> (previous top of stack) / 59 */ 60 void unwind_stack(void *data, unsigned long *s 61 void (*trace)(void *data, un 62 { 63 unsigned long *next_fp = NULL; 64 struct or1k_frameinfo *frameinfo = NUL 65 int reliable = 0; 66 67 while (!kstack_end(stack)) { 68 frameinfo = container_of(stack 69 struc 70 top); 71 72 if (__kernel_text_address(fram 73 if (or1k_frameinfo_val 74 (next_fp == NULL | 75 next_fp == &frame 76 reliable = 1; 77 next_fp = fram 78 } else 79 reliable = 0; 80 81 trace(data, frameinfo- 82 } 83 stack++; 84 } 85 } 86 87 #else /* CONFIG_FRAME_POINTER */ 88 89 /* 90 * Create a stack trace by doing a simple scan 91 * as return addresses. 92 */ 93 void unwind_stack(void *data, unsigned long *s 94 void (*trace)(void *data, u 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 106
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.