-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add kernel symbol tracepoints when modules come/go
Add tracepoints to enumerate the new symbols brought when a new kernel module is loaded. The symbol enumeration is done using the struct module's kallsyms field. Part of the code for the enumeration is inspired by or taken from the linux kernel's module.c file. The overhead when tracepoints are enabled depends on the number of symbols in the module, but is in tens or hundreds or microseconds. With tracepoints disabled, overhead is below 10us in the cases tested. When the module is unloaded, there is only one event to notify of the module unload. The lttng_kallsyms_module_coming function is greatly inspired by and a few lines are copy-pasted from linux's module.c file. Signed-off-by: Geneviève Bastien <[email protected]>
- Loading branch information
Showing
2 changed files
with
124 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) | ||
/* SPDX-License-Identifier: (GPL-2.0) | ||
* | ||
* lttng-kallsyms.c | ||
* | ||
|
@@ -19,6 +19,8 @@ | |
|
||
DEFINE_TRACE(lttng_kallsyms_symbol_module); | ||
DEFINE_TRACE(lttng_kallsyms_symbol_core); | ||
DEFINE_TRACE(lttng_kallsyms_new_module_symbol); | ||
DEFINE_TRACE(lttng_kallsyms_module_unloaded); | ||
|
||
/* | ||
* Trace the kernel symbols from a given module | ||
|
@@ -57,6 +59,103 @@ int lttng_enumerate_kernel_symbols(struct lttng_session *session) | |
} | ||
EXPORT_SYMBOL_GPL(lttng_enumerate_kernel_symbols); | ||
|
||
#ifdef CONFIG_MODULES | ||
|
||
/* | ||
* This function is taken from the linux kernel's module.c file | ||
*/ | ||
static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum) | ||
{ | ||
return kallsyms->strtab + kallsyms->symtab[symnum].st_name; | ||
} | ||
|
||
static | ||
int lttng_kallsyms_module_coming(struct module *mod) | ||
{ | ||
int ret = 0, i; | ||
struct mod_kallsyms *kallsyms; | ||
|
||
/* Inspired by and partly taken from linux kernel's | ||
* module.c file, module_kallsyms_on_each_symbol function */ | ||
kallsyms = mod->kallsyms; | ||
for (i = 0; i < kallsyms->num_symtab; i++) { | ||
const Elf_Sym *sym = &kallsyms->symtab[i]; | ||
|
||
if (sym->st_shndx == SHN_UNDEF) | ||
continue; | ||
|
||
trace_lttng_kallsyms_new_module_symbol(kallsyms_symbol_value(sym), | ||
kallsyms_symbol_name(kallsyms, i), mod->name); | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
static | ||
int lttng_kallsyms_module_going(struct module *mod) | ||
{ | ||
trace_lttng_kallsyms_module_unloaded(mod->name); | ||
return 0; | ||
} | ||
|
||
static | ||
int lttng_kallsyms_module_notify(struct notifier_block *self, | ||
unsigned long val, void *data) | ||
{ | ||
struct module *mod = data; | ||
int ret = 0; | ||
|
||
switch (val) { | ||
case MODULE_STATE_COMING: | ||
ret = lttng_kallsyms_module_coming(mod); | ||
break; | ||
case MODULE_STATE_GOING: | ||
ret = lttng_kallsyms_module_going(mod); | ||
break; | ||
default: | ||
break; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
static | ||
struct notifier_block lttng_kallsyms_module_notifier = { | ||
.notifier_call = lttng_kallsyms_module_notify, | ||
.priority = 0, | ||
}; | ||
|
||
static | ||
int lttng_kallsyms_module_init(void) | ||
{ | ||
return register_module_notifier(<tng_kallsyms_module_notifier); | ||
} | ||
|
||
static | ||
void lttng_kallsyms_module_exit(void) | ||
{ | ||
WARN_ON(unregister_module_notifier(<tng_kallsyms_module_notifier)); | ||
} | ||
|
||
#else /* #ifdef CONFIG_MODULES */ | ||
|
||
static | ||
int lttng_kallsyms_module_init(void) | ||
{ | ||
return 0; | ||
} | ||
|
||
static | ||
void lttng_kallsyms_module_exit(void) | ||
{ | ||
} | ||
|
||
#endif /* #else #ifdef CONFIG_MODULES */ | ||
|
||
module_init(lttng_kallsyms_module_init); | ||
|
||
module_exit(lttng_kallsyms_module_exit); | ||
|
||
MODULE_LICENSE("GPL and additional rights"); | ||
MODULE_AUTHOR("Geneviève Bastien <[email protected]"); | ||
MODULE_DESCRIPTION("LTTng kallsyms"); | ||
|