- `CONFIG_TRACEPOINTS`: kernel tracepoint instrumentation
(enabled as a side-effect of any of the perf/ftrace/blktrace
instrumentation features).
+ - `CONFIG_KPROBES` (5.7+): use kallsyms for kernel 5.7 and newer.
### Supported (optional) kernel config options
--- /dev/null
+/* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only)
+ *
+ * wrapper/kallsyms.c
+ *
+ * Wrapper around kallsyms. Using kprobes to get its address when available.
+ *
+ * Can we mainline LTTng already so we don't have to waste our time doing this
+ * kind of hack ?
+ *
+ * Copyright (C) 2020 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#include <linux/kprobes.h>
+#include <linux/module.h>
+#include <wrapper/kallsyms.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0))
+
+#ifndef CONFIG_KPROBES
+# error "LTTng-modules requires CONFIG_KPROBES on kernels >= 5.7.0"
+#endif
+
+static
+unsigned long (*kallsyms_lookup_name_sym)(const char *name);
+
+static
+int dummy_kprobe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ return 0;
+}
+
+static
+unsigned long do_get_kallsyms(void)
+{
+ struct kprobe probe;
+ int ret;
+ unsigned long addr;
+
+ memset(&probe, 0, sizeof(probe));
+ probe.pre_handler = dummy_kprobe_handler;
+ probe.symbol_name = "kallsyms_lookup_name";
+ ret = register_kprobe(&probe);
+ if (ret)
+ return 0;
+ addr = (unsigned long)probe.addr;
+#ifdef CONFIG_ARM
+#ifdef CONFIG_THUMB2_KERNEL
+ if (addr)
+ addr |= 1; /* set bit 0 in address for thumb mode */
+#endif
+#endif
+ unregister_kprobe(&probe);
+ return addr;
+}
+
+unsigned long wrapper_kallsyms_lookup_name(const char *name)
+{
+ if (!kallsyms_lookup_name_sym) {
+ kallsyms_lookup_name_sym = (void *)do_get_kallsyms();
+ }
+ if (kallsyms_lookup_name_sym)
+ return kallsyms_lookup_name_sym(name);
+ else {
+ printk_once(KERN_WARNING "LTTng requires kallsyms_lookup_name\n");
+ return 0;
+ }
+}
+EXPORT_SYMBOL_GPL(wrapper_kallsyms_lookup_name);
+
+#endif
#define _LTTNG_WRAPPER_KALLSYMS_H
#include <linux/kallsyms.h>
+#include <linux/version.h>
/*
* PowerPC ABIv1 needs KALLSYMS_ALL to get the function descriptor,
# endif
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0))
+
+unsigned long wrapper_kallsyms_lookup_name(const char *name);
+
+#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)) */
+
+static inline
+unsigned long wrapper_kallsyms_lookup_name(const char *name)
+{
+ return kallsyms_lookup_name(name);
+}
+
+#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)) */
+
static inline
unsigned long kallsyms_lookup_funcptr(const char *name)
{
unsigned long addr;
- addr = kallsyms_lookup_name(name);
+ addr = wrapper_kallsyms_lookup_name(name);
#ifdef CONFIG_ARM
#ifdef CONFIG_THUMB2_KERNEL
if (addr)
static inline
unsigned long kallsyms_lookup_dataptr(const char *name)
{
- return kallsyms_lookup_name(name);
+ return wrapper_kallsyms_lookup_name(name);
}
+
#endif /* _LTTNG_WRAPPER_KALLSYMS_H */