1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * arch/arm/kernel/return_address.c 4 * 5 * Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> 6 * for Pengutronix 7 */ 8 #include <linux/export.h> 9 #include <linux/ftrace.h> 10 #include <linux/sched.h> 11 12 #include <asm/stacktrace.h> 13 14 struct return_address_data { 15 unsigned int level; 16 void *addr; 17 }; 18 save_return_addr(struct stackframe * frame,void * d)19static int save_return_addr(struct stackframe *frame, void *d) 20 { 21 struct return_address_data *data = d; 22 23 if (!data->level) { 24 data->addr = (void *)frame->pc; 25 26 return 1; 27 } else { 28 --data->level; 29 return 0; 30 } 31 } 32 return_address(unsigned int level)33void *return_address(unsigned int level) 34 { 35 struct return_address_data data; 36 struct stackframe frame; 37 38 data.level = level + 2; 39 data.addr = NULL; 40 41 frame.fp = (unsigned long)__builtin_frame_address(0); 42 frame.sp = current_stack_pointer; 43 frame.lr = (unsigned long)__builtin_return_address(0); 44 here: 45 frame.pc = (unsigned long)&&here; 46 #ifdef CONFIG_KRETPROBES 47 frame.kr_cur = NULL; 48 frame.tsk = current; 49 #endif 50 frame.ex_frame = false; 51 52 walk_stackframe(&frame, save_return_addr, &data); 53 54 if (!data.level) 55 return data.addr; 56 else 57 return NULL; 58 } 59 60 EXPORT_SYMBOL_GPL(return_address); 61