fix: lookup_fd_rcu replaced by lookup_fdget_rcu in linux 6.7.0-rc1
[lttng-modules.git] / src / wrapper / kallsyms.c
... / ...
CommitLineData
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 (LTTNG_LINUX_VERSION_CODE >= LTTNG_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#ifdef LTTNG_CONFIG_PPC64_ELF_ABI_V1
24#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,18,0))
25#include <asm/elf.h>
26
27#define LTTNG_FUNC_DESC_TYPE struct func_desc
28#define LTTNG_FUNC_DESC_ADDR_NAME addr
29
30#else
31
32#include <asm/types.h>
33
34#define LTTNG_FUNC_DESC_TYPE func_descr_t
35#define LTTNG_FUNC_DESC_ADDR_NAME entry
36#endif
37
38static
39LTTNG_FUNC_DESC_TYPE kallsyms_lookup_name_func_desc;
40#endif
41
42static
43unsigned long (*kallsyms_lookup_name_sym)(const char *name);
44
45static
46int dummy_kprobe_handler(struct kprobe *p, struct pt_regs *regs)
47{
48 return 0;
49}
50
51static
52unsigned long do_get_kallsyms(void)
53{
54 struct kprobe probe;
55 int ret;
56 unsigned long addr;
57
58 memset(&probe, 0, sizeof(probe));
59 probe.pre_handler = dummy_kprobe_handler;
60 probe.symbol_name = "kallsyms_lookup_name";
61#ifdef LTTNG_CONFIG_PPC64_ELF_ABI_V2
62 /*
63 * With powerpc64 ABIv2, we need the global entry point of
64 * kallsyms_lookup_name to call it later, while kprobe_register would
65 * automatically adjust the global entry point to the local entry point,
66 * when a kprobe was registered at a function entry. So we add 4 bytes
67 * which is the length of one instruction to kallsyms_lookup_name to
68 * avoid the adjustment.
69 */
70 probe.offset = 4;
71#endif
72 ret = register_kprobe(&probe);
73 if (ret)
74 return 0;
75#ifdef LTTNG_CONFIG_PPC64_ELF_ABI_V2
76 /* Substract 4 bytes to get what we originally want */
77 addr = (unsigned long)(((char *)probe.addr) - 4);
78#elif defined(LTTNG_CONFIG_PPC64_ELF_ABI_V1)
79 /*
80 * Build a function descriptor from the address of
81 * 'kallsyms_lookup_name' returned by kprobe and the toc of
82 * 'sprint_symbol' which is in the same compile unit and exported. I
83 * hate this on so many levels but it works.
84 */
85 kallsyms_lookup_name_func_desc.LTTNG_FUNC_DESC_ADDR_NAME = (unsigned long) probe.addr;
86 kallsyms_lookup_name_func_desc.toc = ((LTTNG_FUNC_DESC_TYPE *) &sprint_symbol)->toc;
87 addr = (unsigned long) &kallsyms_lookup_name_func_desc;
88#else
89 addr = (unsigned long)probe.addr;
90#endif
91#ifdef CONFIG_ARM
92#ifdef CONFIG_THUMB2_KERNEL
93 if (addr)
94 addr |= 1; /* set bit 0 in address for thumb mode */
95#endif
96#endif
97 unregister_kprobe(&probe);
98 return addr;
99}
100
101unsigned long wrapper_kallsyms_lookup_name(const char *name)
102{
103 if (!kallsyms_lookup_name_sym) {
104 kallsyms_lookup_name_sym = (void *)do_get_kallsyms();
105 }
106 if (kallsyms_lookup_name_sym)
107 return kallsyms_lookup_name_sym(name);
108 else {
109 printk_once(KERN_WARNING "LTTng: requires kallsyms_lookup_name\n");
110 return 0;
111 }
112}
113EXPORT_SYMBOL_GPL(wrapper_kallsyms_lookup_name);
114
115#endif
This page took 0.024282 seconds and 4 git commands to generate.