Commit | Line | Data |
---|---|---|
e3273c97 MD |
1 | /* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only) |
2 | * | |
3 | * wrapper/kallsyms.c | |
4 | * | |
5 | * Wrapper around kallsyms. Using kprobes to get its address when available. | |
6 | * | |
7 | * Can we mainline LTTng already so we don't have to waste our time doing this | |
8 | * kind of hack ? | |
9 | * | |
10 | * Copyright (C) 2020 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
11 | */ | |
12 | ||
13 | #include <linux/kprobes.h> | |
14 | #include <linux/module.h> | |
15 | #include <wrapper/kallsyms.h> | |
16 | ||
17 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)) | |
18 | ||
19 | #ifndef CONFIG_KPROBES | |
20 | # error "LTTng-modules requires CONFIG_KPROBES on kernels >= 5.7.0" | |
21 | #endif | |
22 | ||
23 | static | |
24 | unsigned long (*kallsyms_lookup_name_sym)(const char *name); | |
25 | ||
26 | static | |
27 | int dummy_kprobe_handler(struct kprobe *p, struct pt_regs *regs) | |
28 | { | |
29 | return 0; | |
30 | } | |
31 | ||
32 | static | |
33 | unsigned long do_get_kallsyms(void) | |
34 | { | |
35 | struct kprobe probe; | |
36 | int ret; | |
37 | unsigned long addr; | |
38 | ||
39 | memset(&probe, 0, sizeof(probe)); | |
40 | probe.pre_handler = dummy_kprobe_handler; | |
41 | probe.symbol_name = "kallsyms_lookup_name"; | |
42 | ret = register_kprobe(&probe); | |
43 | if (ret) | |
44 | return 0; | |
45 | addr = (unsigned long)probe.addr; | |
46 | #ifdef CONFIG_ARM | |
47 | #ifdef CONFIG_THUMB2_KERNEL | |
48 | if (addr) | |
49 | addr |= 1; /* set bit 0 in address for thumb mode */ | |
50 | #endif | |
51 | #endif | |
52 | unregister_kprobe(&probe); | |
53 | return addr; | |
54 | } | |
55 | ||
56 | unsigned long wrapper_kallsyms_lookup_name(const char *name) | |
57 | { | |
58 | if (!kallsyms_lookup_name_sym) { | |
59 | kallsyms_lookup_name_sym = (void *)do_get_kallsyms(); | |
60 | } | |
61 | if (kallsyms_lookup_name_sym) | |
62 | return kallsyms_lookup_name_sym(name); | |
63 | else { | |
64 | printk_once(KERN_WARNING "LTTng requires kallsyms_lookup_name\n"); | |
65 | return 0; | |
66 | } | |
67 | } | |
68 | EXPORT_SYMBOL_GPL(wrapper_kallsyms_lookup_name); | |
69 | ||
70 | #endif |