Skip to content

Commit

Permalink
Add kernel symbol tracepoints when modules come/go
Browse files Browse the repository at this point in the history
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
tahini committed Jul 4, 2019
1 parent 18643a5 commit 9a89449
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 1 deletion.
24 changes: 24 additions & 0 deletions instrumentation/events/lttng-module/lttng-kallsyms.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ LTTNG_TRACEPOINT_EVENT(lttng_kallsyms_symbol_core,
)
)

LTTNG_TRACEPOINT_EVENT(lttng_kallsyms_new_module_symbol,

TP_PROTO(unsigned long addr, const char *symbol, const char *module),

TP_ARGS(addr, symbol, module),

TP_FIELDS(
ctf_integer_hex(unsigned long, addr, addr)
ctf_string(symbol, symbol)
ctf_string(module, module)
)
)

LTTNG_TRACEPOINT_EVENT(lttng_kallsyms_module_unloaded,

TP_PROTO(const char *module),

TP_ARGS(module),

TP_FIELDS(
ctf_string(module, module)
)
)

#endif /* LTTNG_TRACE_LTTNG_KALLSYMS_H */

/* This part must be outside protection */
Expand Down
101 changes: 100 additions & 1 deletion lttng-kallsyms.c
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
*
Expand All @@ -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
Expand Down Expand Up @@ -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(&lttng_kallsyms_module_notifier);
}

static
void lttng_kallsyms_module_exit(void)
{
WARN_ON(unregister_module_notifier(&lttng_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");
Expand Down

0 comments on commit 9a89449

Please sign in to comment.