0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/export.h>
0010 #include <linux/ftrace.h>
0011 #include <linux/kprobes.h>
0012 #include <linux/stacktrace.h>
0013
0014 #include <asm/stack_pointer.h>
0015
0016 struct return_address_data {
0017 unsigned int level;
0018 void *addr;
0019 };
0020
0021 static bool save_return_addr(void *d, unsigned long pc)
0022 {
0023 struct return_address_data *data = d;
0024
0025 if (!data->level) {
0026 data->addr = (void *)pc;
0027 return false;
0028 } else {
0029 --data->level;
0030 return true;
0031 }
0032 }
0033 NOKPROBE_SYMBOL(save_return_addr);
0034
0035 void *return_address(unsigned int level)
0036 {
0037 struct return_address_data data;
0038
0039 data.level = level + 2;
0040 data.addr = NULL;
0041
0042 arch_stack_walk(save_return_addr, &data, current, NULL);
0043
0044 if (!data.level)
0045 return data.addr;
0046 else
0047 return NULL;
0048 }
0049 EXPORT_SYMBOL_GPL(return_address);
0050 NOKPROBE_SYMBOL(return_address);