|
1 |
| -/* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1) |
| 1 | +/* SPDX-License-Identifier: (GPL-2.0) |
2 | 2 | *
|
3 | 3 | * lttng-kallsyms.c
|
4 | 4 | *
|
|
19 | 19 |
|
20 | 20 | DEFINE_TRACE(lttng_kallsyms_symbol_module);
|
21 | 21 | DEFINE_TRACE(lttng_kallsyms_symbol_core);
|
| 22 | +DEFINE_TRACE(lttng_kallsyms_new_module_symbol); |
| 23 | +DEFINE_TRACE(lttng_kallsyms_module_unloaded); |
22 | 24 |
|
23 | 25 | /*
|
24 | 26 | * Trace the kernel symbols from a given module
|
@@ -57,6 +59,103 @@ int lttng_enumerate_kernel_symbols(struct lttng_session *session)
|
57 | 59 | }
|
58 | 60 | EXPORT_SYMBOL_GPL(lttng_enumerate_kernel_symbols);
|
59 | 61 |
|
| 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(<tng_kallsyms_module_notifier); |
| 132 | +} |
| 133 | + |
| 134 | +static |
| 135 | +void lttng_kallsyms_module_exit(void) |
| 136 | +{ |
| 137 | + WARN_ON(unregister_module_notifier(<tng_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 | + |
60 | 159 | MODULE_LICENSE("GPL and additional rights");
|
61 | 160 | MODULE_AUTHOR( "Geneviève Bastien <[email protected]");
|
62 | 161 | MODULE_DESCRIPTION("LTTng kallsyms");
|
|
0 commit comments