-
Notifications
You must be signed in to change notification settings - Fork 72
Expand file tree
/
Copy pathlttng-kallsyms.c
More file actions
165 lines (135 loc) · 3.77 KB
/
lttng-kallsyms.c
File metadata and controls
165 lines (135 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* SPDX-License-Identifier: (GPL-2.0)
*
* lttng-kallsyms.c
*
* Copyright (C) 2019 Geneviève Bastien <gbastien@versatic.net>
*/
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <lttng-events.h>
#include <lttng-kallsyms.h>
/* Define the tracepoints, but do not build the probes */
#define CREATE_TRACE_POINTS
#define TRACE_INCLUDE_PATH instrumentation/events/lttng-module
#define TRACE_INCLUDE_FILE lttng-kallsyms
#define LTTNG_INSTRUMENTATION
#include <instrumentation/events/lttng-module/lttng-kallsyms.h>
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
*
* data: The lttng_session instance
* symbol_name: The function name this symbol resolves to
* module: The module containing this symbol. Can be NULL
* symbol_addr: The symbol address
*/
static
int _lttng_one_symbol_received(void * data, const char * symbol_name,
struct module * module, unsigned long symbol_addr)
{
struct lttng_session *session = data;
if (module) {
trace_lttng_kallsyms_symbol_module(session, symbol_addr,
symbol_name, module->name);
} else {
trace_lttng_kallsyms_symbol_core(session, symbol_addr,
symbol_name);
}
return 0;
}
int lttng_enumerate_kernel_symbols(struct lttng_session *session)
{
int ret = 0;
mutex_lock(&module_mutex);
ret = kallsyms_on_each_symbol(_lttng_one_symbol_received, (void *) session);
mutex_unlock(&module_mutex);
return ret;
}
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 <gbastien@versatic.net");
MODULE_DESCRIPTION("LTTng kallsyms");
MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
__stringify(LTTNG_MODULES_MINOR_VERSION) "."
__stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
LTTNG_MODULES_EXTRAVERSION);