Skip to content

Commit 7ad060b

Browse files
committed
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]>
1 parent 18643a5 commit 7ad060b

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed

instrumentation/events/lttng-module/lttng-kallsyms.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,30 @@ LTTNG_TRACEPOINT_EVENT(lttng_kallsyms_symbol_core,
3434
)
3535
)
3636

37+
LTTNG_TRACEPOINT_EVENT(lttng_kallsyms_new_module_symbol,
38+
39+
TP_PROTO(unsigned long addr, const char *symbol, const char *module),
40+
41+
TP_ARGS(addr, symbol, module),
42+
43+
TP_FIELDS(
44+
ctf_integer_hex(unsigned long, addr, addr)
45+
ctf_string(symbol, symbol)
46+
ctf_string(module, module)
47+
)
48+
)
49+
50+
LTTNG_TRACEPOINT_EVENT(lttng_kallsyms_module_unloaded,
51+
52+
TP_PROTO(const char *module),
53+
54+
TP_ARGS(module),
55+
56+
TP_FIELDS(
57+
ctf_string(module, module)
58+
)
59+
)
60+
3761
#endif /* LTTNG_TRACE_LTTNG_KALLSYMS_H */
3862

3963
/* This part must be outside protection */

lttng-kallsyms.c

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
1+
/* SPDX-License-Identifier: (GPL-2.0)
22
*
33
* lttng-kallsyms.c
44
*
@@ -19,6 +19,8 @@
1919

2020
DEFINE_TRACE(lttng_kallsyms_symbol_module);
2121
DEFINE_TRACE(lttng_kallsyms_symbol_core);
22+
DEFINE_TRACE(lttng_kallsyms_new_module_symbol);
23+
DEFINE_TRACE(lttng_kallsyms_module_unloaded);
2224

2325
/*
2426
* Trace the kernel symbols from a given module
@@ -57,6 +59,103 @@ int lttng_enumerate_kernel_symbols(struct lttng_session *session)
5759
}
5860
EXPORT_SYMBOL_GPL(lttng_enumerate_kernel_symbols);
5961

62+
#ifdef CONFIG_MODULES
63+
64+
/*
65+
* This function is taken from the linux kernel's module.c file
66+
*/
67+
static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum)
68+
{
69+
return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
70+
}
71+
72+
static
73+
int lttng_kallsyms_module_coming(struct module *mod)
74+
{
75+
int ret = 0, i;
76+
struct mod_kallsyms *kallsyms;
77+
78+
/* Inspired by and partly taken from linux kernel's
79+
* module.c file, module_kallsyms_on_each_symbol function */
80+
kallsyms = rcu_dereference(mod->kallsyms);
81+
for (i = 0; i < kallsyms->num_symtab; i++) {
82+
const Elf_Sym *sym = &kallsyms->symtab[i];
83+
84+
if (sym->st_shndx == SHN_UNDEF)
85+
continue;
86+
87+
trace_lttng_kallsyms_new_module_symbol(kallsyms_symbol_value(sym),
88+
kallsyms_symbol_name(kallsyms, i), mod->name);
89+
}
90+
91+
return ret;
92+
}
93+
94+
static
95+
int lttng_kallsyms_module_going(struct module *mod)
96+
{
97+
trace_lttng_kallsyms_module_unloaded(mod->name);
98+
return 0;
99+
}
100+
101+
static
102+
int lttng_kallsyms_module_notify(struct notifier_block *self,
103+
unsigned long val, void *data)
104+
{
105+
struct module *mod = data;
106+
int ret = 0;
107+
108+
switch (val) {
109+
case MODULE_STATE_COMING:
110+
ret = lttng_kallsyms_module_coming(mod);
111+
break;
112+
case MODULE_STATE_GOING:
113+
ret = lttng_kallsyms_module_going(mod);
114+
break;
115+
default:
116+
break;
117+
}
118+
119+
return ret;
120+
}
121+
122+
static
123+
struct notifier_block lttng_kallsyms_module_notifier = {
124+
.notifier_call = lttng_kallsyms_module_notify,
125+
.priority = 0,
126+
};
127+
128+
static
129+
int lttng_kallsyms_module_init(void)
130+
{
131+
return register_module_notifier(&lttng_kallsyms_module_notifier);
132+
}
133+
134+
static
135+
void lttng_kallsyms_module_exit(void)
136+
{
137+
WARN_ON(unregister_module_notifier(&lttng_kallsyms_module_notifier));
138+
}
139+
140+
#else /* #ifdef CONFIG_MODULES */
141+
142+
static
143+
int lttng_kallsyms_module_init(void)
144+
{
145+
return 0;
146+
}
147+
148+
static
149+
void lttng_kallsyms_module_exit(void)
150+
{
151+
}
152+
153+
#endif /* #else #ifdef CONFIG_MODULES */
154+
155+
module_init(lttng_kallsyms_module_init);
156+
157+
module_exit(lttng_kallsyms_module_exit);
158+
60159
MODULE_LICENSE("GPL and additional rights");
61160
MODULE_AUTHOR("Geneviève Bastien <[email protected]");
62161
MODULE_DESCRIPTION("LTTng kallsyms");

0 commit comments

Comments
 (0)