1 /* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only)
5 * Wrapper around kallsyms. Using kprobes to get its address when available.
7 * Can we mainline LTTng already so we don't have to waste our time doing this
10 * Copyright (C) 2020 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
13 #include <linux/kprobes.h>
14 #include <linux/module.h>
15 #include <wrapper/kallsyms.h>
17 #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,7,0))
19 #ifndef CONFIG_KPROBES
20 # error "LTTng-modules requires CONFIG_KPROBES on kernels >= 5.7.0"
24 unsigned long (*kallsyms_lookup_name_sym
)(const char *name
);
27 int dummy_kprobe_handler(struct kprobe
*p
, struct pt_regs
*regs
)
32 #ifdef LTTNG_CONFIG_PPC64_ELF_ABI_V2
34 void kallsyms_pre_arch_adjust(struct kprobe
*probe
)
37 * With powerpc64 ABIv2, we need the global entry point of
38 * kallsyms_lookup_name to call it later, while kprobe_register would
39 * automatically adjust the global entry point to the local entry point,
40 * when a kprobe was registered at a function entry. So we add 4 bytes
41 * which is the length of one instruction to kallsyms_lookup_name to
42 * avoid the adjustment.
48 void kallsyms_pre_arch_adjust(struct kprobe
*probe
)
53 #ifdef LTTNG_CONFIG_PPC64_ELF_ABI_V2
55 unsigned long kallsyms_get_arch_call_addr(const struct kprobe
*probe
)
57 /* Substract 4 bytes to get what we originally want */
58 return (unsigned long)(((char *)probe
->addr
) - 4);
61 #elif defined(LTTNG_CONFIG_PPC64_ELF_ABI_V1)
62 # if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,18,0))
64 # define LTTNG_FUNC_DESC_TYPE struct func_desc
65 # define LTTNG_FUNC_DESC_ADDR_NAME addr
67 # include <asm/types.h>
68 # define LTTNG_FUNC_DESC_TYPE func_descr_t
69 # define LTTNG_FUNC_DESC_ADDR_NAME entry
72 LTTNG_FUNC_DESC_TYPE kallsyms_lookup_name_func_desc
;
76 unsigned long kallsyms_get_arch_call_addr(const struct kprobe
*probe
)
79 * Build a function descriptor from the address of
80 * 'kallsyms_lookup_name' returned by kprobe and the toc of
81 * 'sprint_symbol' which is in the same compile unit and exported. I
82 * hate this on so many levels but it works.
84 kallsyms_lookup_name_func_desc
.LTTNG_FUNC_DESC_ADDR_NAME
= (unsigned long) probe
.addr
;
85 kallsyms_lookup_name_func_desc
.toc
= ((LTTNG_FUNC_DESC_TYPE
*) &sprint_symbol
)->toc
;
86 return (unsigned long) &kallsyms_lookup_name_func_desc
;
88 #elif defined(CONFIG_ARM) && defined(CONFIG_THUMB2_KERNEL)
90 unsigned long kallsyms_get_arch_call_addr(const struct kprobe
*probe
)
92 unsigned long addr
= (unsigned long)probe
->addr
;
95 addr
|= 1; /* set bit 0 in address for thumb mode */
100 unsigned long kallsyms_get_arch_call_addr(const struct kprobe
*probe
)
102 return (unsigned long)probe
->addr
;
107 unsigned long do_get_kallsyms(void)
113 memset(&probe
, 0, sizeof(probe
));
114 probe
.pre_handler
= dummy_kprobe_handler
;
115 probe
.symbol_name
= "kallsyms_lookup_name";
116 kallsyms_pre_arch_adjust(&probe
);
117 ret
= register_kprobe(&probe
);
120 addr
= kallsyms_get_arch_call_addr(&probe
);
121 unregister_kprobe(&probe
);
125 unsigned long wrapper_kallsyms_lookup_name(const char *name
)
127 if (!kallsyms_lookup_name_sym
) {
128 kallsyms_lookup_name_sym
= (void *)do_get_kallsyms();
130 if (kallsyms_lookup_name_sym
)
131 return kallsyms_lookup_name_sym(name
);
133 printk_once(KERN_WARNING
"LTTng: requires kallsyms_lookup_name\n");
137 EXPORT_SYMBOL_GPL(wrapper_kallsyms_lookup_name
);
141 #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,4,0) && defined(CONFIG_ANDROID))
142 MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver
);