Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * arch/arm/kernel/return_address.c
0004  *
0005  * Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
0006  * for Pengutronix
0007  */
0008 #include <linux/export.h>
0009 #include <linux/ftrace.h>
0010 #include <linux/sched.h>
0011 
0012 #include <asm/stacktrace.h>
0013 
0014 struct return_address_data {
0015     unsigned int level;
0016     void *addr;
0017 };
0018 
0019 static int save_return_addr(struct stackframe *frame, void *d)
0020 {
0021     struct return_address_data *data = d;
0022 
0023     if (!data->level) {
0024         data->addr = (void *)frame->pc;
0025 
0026         return 1;
0027     } else {
0028         --data->level;
0029         return 0;
0030     }
0031 }
0032 
0033 void *return_address(unsigned int level)
0034 {
0035     struct return_address_data data;
0036     struct stackframe frame;
0037 
0038     data.level = level + 2;
0039     data.addr = NULL;
0040 
0041     frame.fp = (unsigned long)__builtin_frame_address(0);
0042     frame.sp = current_stack_pointer;
0043     frame.lr = (unsigned long)__builtin_return_address(0);
0044 here:
0045     frame.pc = (unsigned long)&&here;
0046 #ifdef CONFIG_KRETPROBES
0047     frame.kr_cur = NULL;
0048     frame.tsk = current;
0049 #endif
0050 
0051     walk_stackframe(&frame, save_return_addr, &data);
0052 
0053     if (!data.level)
0054         return data.addr;
0055     else
0056         return NULL;
0057 }
0058 
0059 EXPORT_SYMBOL_GPL(return_address);