return_address.c (1133B)
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 14struct return_address_data { 15 unsigned int level; 16 void *addr; 17}; 18 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 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); 44here: 45 frame.pc = (unsigned long)&&here; 46#ifdef CONFIG_KRETPROBES 47 frame.kr_cur = NULL; 48 frame.tsk = current; 49#endif 50 51 walk_stackframe(&frame, save_return_addr, &data); 52 53 if (!data.level) 54 return data.addr; 55 else 56 return NULL; 57} 58 59EXPORT_SYMBOL_GPL(return_address);