#endif
#endif
+// No export check and gates. This one seems simply like a non-export.
+extern void *_stp_module_kallsyms_on_each_symbol;
+
#if defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL) && defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED)
#define USE_KALLSYMS_ON_EACH_SYMBOL (1)
#elif defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL)
static int
-stapkp_symbol_callback(void *data, const char *name,
+__stapkp_symbol_callback(void *data, const char *name,
struct module *mod, unsigned long addr)
{
struct stapkp_symbol_data *sd = data;
return 0;
}
+static int
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+stapkp_symbol_callback(void *data, const char *name,
+ unsigned long addr)
+{
+ struct module *mod = NULL;
+#else
+stapkp_symbol_callback(void *data, const char *name,
+ struct module *mod, unsigned long addr)
+{
+#endif
+ return __stapkp_symbol_callback(data, name, mod, addr);
+}
static int
stapkp_init(struct stap_kprobe_probe *probes,
mutex_lock(&module_mutex);
#endif
kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
+ module_kallsyms_on_each_symbol(sd.modname, stapkp_symbol_callback, &sd);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
+ module_kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#endif
#ifdef STAPCONF_MODULE_MUTEX
mutex_unlock(&module_mutex);
#endif
mutex_lock(&module_mutex);
#endif
kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
+ module_kallsyms_on_each_symbol(sd.modname, stapkp_symbol_callback, &sd);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
+ module_kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
+#endif
#ifdef STAPCONF_MODULE_MUTEX
mutex_unlock(&module_mutex);
#endif
#ifndef CONFIG_PPC64
#define STAPCONF_KALLSYMS_ON_EACH_SYMBOL
#if !defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED)
-// XXX Should not be static, since it is linked into kprobes.c.
-static void *_stp_kallsyms_on_each_symbol;
+// Not static, since it is linked into kprobes.c:
+void *_stp_kallsyms_on_each_symbol;
#endif
#endif
+// No export check and gates. This one seems simply like a non-export.
+// Not static, since it is linked into kprobes.c:
+void *_stp_module_kallsyms_on_each_symbol;
+
// PR13489, inode-uprobes sometimes lacks the necessary SYMBOL_EXPORT's.
#if !defined(STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED)
static void *kallsyms_task_user_regset_view;
typedef typeof(&kallsyms_on_each_symbol) kallsyms_on_each_symbol_fn;
// XXX Will be linked in place of the kernel's kallsyms_on_each_symbol:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+int kallsyms_on_each_symbol(int (*fn)(void *, const char *,
+ unsigned long),
+ void *data)
+#else
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
unsigned long),
void *data)
+#endif
{
/* First, try to use a kallsyms_lookup_name address passed to us
through the relocation mechanism. */
_stp_error("BUG: attempting to use unavailable kallsyms_on_each_symbol!!\n");
return 0;
}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
+typedef typeof(&module_kallsyms_on_each_symbol) module_kallsyms_on_each_symbol_fn;
+
+// XXX Will be linked in place of the kernel's module_kallsyms_on_each_symbol:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+int module_kallsyms_on_each_symbol(const char *modname,
+ int (*fn)(void *, const char *,
+ unsigned long),
+ void *data)
+#else
+int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
+ unsigned long),
+ void *data)
+#endif
+{
+ /* First, try to use a kallsyms_lookup_name address passed to us
+ through the relocation mechanism. */
+ if (_stp_module_kallsyms_on_each_symbol != NULL)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
+ return (* (module_kallsyms_on_each_symbol_fn)_stp_module_kallsyms_on_each_symbol)(modname, fn, data);
+#else
+ return (* (module_kallsyms_on_each_symbol_fn)_stp_module_kallsyms_on_each_symbol)(fn, data);
+#endif
+
+ /* Next, give up and signal a BUG. We should have detected
+ that this function is not available and used a different
+ mechanism! */
+ _stp_error("BUG: attempting to use unavailable module_kallsyms_on_each_symbol!!\n");
+ return 0;
+}
+#endif
+
#endif
_stp_kallsyms_on_each_symbol = (void *) msg.address;
}
#endif
+ if (!strcmp ("kernel", msg.module)
+ && !strcmp ("module_kallsyms_on_each_symbol", msg.reloc)) {
+ _stp_module_kallsyms_on_each_symbol = (void *) msg.address;
+ }
_stp_kmodule_update_address(msg.module, msg.reloc, msg.address);
}
#if defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL) && !defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED)
_stp_kallsyms_on_each_symbol = NULL;
#endif
+ _stp_module_kallsyms_on_each_symbol = NULL;
#if defined(CONFIG_KALLSYMS) && !defined(STAPCONF_KALLSYMS_LOOKUP_NAME_EXPORTED)
_stp_need_kallsyms_stext = 0;
#endif
int found_stext = 0;
int found_kallsyms_lookup_name = 0;
int found_kallsyms_on_each_symbol = 0;
+ int found_module_kallsyms_on_each_symbol = 0;
int done_with_kallsyms = 0;
char *line = NULL;
size_t linesz = 0;
found_kallsyms_on_each_symbol = 1;
}
+ else if (linesize - pos == sizeof "module_kallsyms_on_each_symbol"
+ && !strcmp(line + pos, "module_kallsyms_on_each_symbol" "\n"))
+ {
+ rc = send_a_relocation ("kernel", "module_kallsyms_on_each_symbol", address);
+ if (rc != 0) // non fatal, follows perror()
+ dbug(1, "Relocation was reloc module_kallsyms_on_each_symbol=%llx\n", address);
+
+ found_module_kallsyms_on_each_symbol = 1;
+ }
}
done_with_kallsyms = found_stext
&& found_kallsyms_lookup_name
- && found_kallsyms_on_each_symbol;
+ && found_kallsyms_on_each_symbol
+ && found_module_kallsyms_on_each_symbol;
}
free (line);
fclose (kallsyms);