stacktrace.c (8632987380765dee716d460640aa58d58d52998e) | stacktrace.c (1614b2b11fab29dd4ff31ebba9d266961f5af69e) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Stack tracing support 4 * 5 * Copyright (C) 2012 ARM Ltd. 6 */ 7#include <linux/kernel.h> 8#include <linux/export.h> --- 24 unchanged lines hidden (view full) --- 33 */ 34 35 36void start_backtrace(struct stackframe *frame, unsigned long fp, 37 unsigned long pc) 38{ 39 frame->fp = fp; 40 frame->pc = pc; | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Stack tracing support 4 * 5 * Copyright (C) 2012 ARM Ltd. 6 */ 7#include <linux/kernel.h> 8#include <linux/export.h> --- 24 unchanged lines hidden (view full) --- 33 */ 34 35 36void start_backtrace(struct stackframe *frame, unsigned long fp, 37 unsigned long pc) 38{ 39 frame->fp = fp; 40 frame->pc = pc; |
41#ifdef CONFIG_FUNCTION_GRAPH_TRACER 42 frame->graph = 0; 43#endif | |
44#ifdef CONFIG_KRETPROBES 45 frame->kr_cur = NULL; 46#endif 47 48 /* 49 * Prime the first unwind. 50 * 51 * In unwind_frame() we'll check that the FP points to a valid stack, --- 59 unchanged lines hidden (view full) --- 111 * Record this frame record's values and location. The prev_fp and 112 * prev_type are only meaningful to the next unwind_frame() invocation. 113 */ 114 frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); 115 frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8)); 116 frame->prev_fp = fp; 117 frame->prev_type = info.type; 118 | 41#ifdef CONFIG_KRETPROBES 42 frame->kr_cur = NULL; 43#endif 44 45 /* 46 * Prime the first unwind. 47 * 48 * In unwind_frame() we'll check that the FP points to a valid stack, --- 59 unchanged lines hidden (view full) --- 108 * Record this frame record's values and location. The prev_fp and 109 * prev_type are only meaningful to the next unwind_frame() invocation. 110 */ 111 frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); 112 frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 8)); 113 frame->prev_fp = fp; 114 frame->prev_type = info.type; 115 |
116 frame->pc = ptrauth_strip_insn_pac(frame->pc); 117 |
|
119#ifdef CONFIG_FUNCTION_GRAPH_TRACER 120 if (tsk->ret_stack && | 118#ifdef CONFIG_FUNCTION_GRAPH_TRACER 119 if (tsk->ret_stack && |
121 (ptrauth_strip_insn_pac(frame->pc) == (unsigned long)return_to_handler)) { 122 struct ftrace_ret_stack *ret_stack; | 120 (frame->pc == (unsigned long)return_to_handler)) { 121 unsigned long orig_pc; |
123 /* 124 * This is a case where function graph tracer has 125 * modified a return address (LR) in a stack frame 126 * to hook a function return. 127 * So replace it to an original value. 128 */ | 122 /* 123 * This is a case where function graph tracer has 124 * modified a return address (LR) in a stack frame 125 * to hook a function return. 126 * So replace it to an original value. 127 */ |
129 ret_stack = ftrace_graph_get_ret_stack(tsk, frame->graph++); 130 if (WARN_ON_ONCE(!ret_stack)) | 128 orig_pc = ftrace_graph_ret_addr(tsk, NULL, frame->pc, 129 (void *)frame->fp); 130 if (WARN_ON_ONCE(frame->pc == orig_pc)) |
131 return -EINVAL; | 131 return -EINVAL; |
132 frame->pc = ret_stack->ret; | 132 frame->pc = orig_pc; |
133 } 134#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 135#ifdef CONFIG_KRETPROBES 136 if (is_kretprobe_trampoline(frame->pc)) 137 frame->pc = kretprobe_find_ret_addr(tsk, (void *)frame->fp, &frame->kr_cur); 138#endif 139 | 133 } 134#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 135#ifdef CONFIG_KRETPROBES 136 if (is_kretprobe_trampoline(frame->pc)) 137 frame->pc = kretprobe_find_ret_addr(tsk, (void *)frame->fp, &frame->kr_cur); 138#endif 139 |
140 frame->pc = ptrauth_strip_insn_pac(frame->pc); 141 | |
142 return 0; 143} 144NOKPROBE_SYMBOL(unwind_frame); 145 146void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame, 147 bool (*fn)(void *, unsigned long), void *data) 148{ 149 while (1) { --- 68 unchanged lines hidden (view full) --- 218} 219 220void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl) 221{ 222 dump_backtrace(NULL, tsk, loglvl); 223 barrier(); 224} 225 | 140 return 0; 141} 142NOKPROBE_SYMBOL(unwind_frame); 143 144void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame, 145 bool (*fn)(void *, unsigned long), void *data) 146{ 147 while (1) { --- 68 unchanged lines hidden (view full) --- 216} 217 218void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl) 219{ 220 dump_backtrace(NULL, tsk, loglvl); 221 barrier(); 222} 223 |
226#ifdef CONFIG_STACKTRACE 227 | |
228noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry, 229 void *cookie, struct task_struct *task, 230 struct pt_regs *regs) 231{ 232 struct stackframe frame; 233 234 if (regs) 235 start_backtrace(&frame, regs->regs[29], regs->pc); 236 else if (task == current) 237 start_backtrace(&frame, 238 (unsigned long)__builtin_frame_address(1), 239 (unsigned long)__builtin_return_address(0)); 240 else 241 start_backtrace(&frame, thread_saved_fp(task), 242 thread_saved_pc(task)); 243 244 walk_stackframe(task, &frame, consume_entry, cookie); 245} | 224noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry, 225 void *cookie, struct task_struct *task, 226 struct pt_regs *regs) 227{ 228 struct stackframe frame; 229 230 if (regs) 231 start_backtrace(&frame, regs->regs[29], regs->pc); 232 else if (task == current) 233 start_backtrace(&frame, 234 (unsigned long)__builtin_frame_address(1), 235 (unsigned long)__builtin_return_address(0)); 236 else 237 start_backtrace(&frame, thread_saved_fp(task), 238 thread_saved_pc(task)); 239 240 walk_stackframe(task, &frame, consume_entry, cookie); 241} |
246 247#endif | |