1 | // SPDX-License-Identifier: GPL-2.0-only |
---|---|
2 | /* |
3 | * arch/arm64/kernel/return_address.c |
4 | * |
5 | * Copyright (C) 2013 Linaro Limited |
6 | * Author: AKASHI Takahiro <takahiro.akashi@linaro.org> |
7 | */ |
8 | |
9 | #include <linux/export.h> |
10 | #include <linux/ftrace.h> |
11 | #include <linux/kprobes.h> |
12 | #include <linux/stacktrace.h> |
13 | |
14 | #include <asm/stack_pointer.h> |
15 | |
16 | struct return_address_data { |
17 | unsigned int level; |
18 | void *addr; |
19 | }; |
20 | |
21 | static bool save_return_addr(void *d, unsigned long pc) |
22 | { |
23 | struct return_address_data *data = d; |
24 | |
25 | if (!data->level) { |
26 | data->addr = (void *)pc; |
27 | return false; |
28 | } else { |
29 | --data->level; |
30 | return true; |
31 | } |
32 | } |
33 | NOKPROBE_SYMBOL(save_return_addr); |
34 | |
35 | void *return_address(unsigned int level) |
36 | { |
37 | struct return_address_data data; |
38 | |
39 | data.level = level + 2; |
40 | data.addr = NULL; |
41 | |
42 | arch_stack_walk(consume_entry: save_return_addr, cookie: &data, current, NULL); |
43 | |
44 | if (!data.level) |
45 | return data.addr; |
46 | else |
47 | return NULL; |
48 | } |
49 | EXPORT_SYMBOL_GPL(return_address); |
50 | NOKPROBE_SYMBOL(return_address); |
51 |