projects/linux·blob master · refs

504 lines · 13.3 KiB

1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Module kallsyms support
4 *
5 * Copyright (C) 2010 Rusty Russell
6 */
7
8#include <linux/module.h>
9#include <linux/module_symbol.h>
10#include <linux/kallsyms.h>
11#include <linux/buildid.h>
12#include <linux/bsearch.h>
13#include "internal.h"
14
15/* Lookup exported symbol in given range of kernel_symbols */
16static const struct kernel_symbol *lookup_exported_symbol(const char *name,
17 const struct kernel_symbol *start,
18 const struct kernel_symbol *stop)
19{
20 return bsearch(name, start, stop - start,
21 sizeof(struct kernel_symbol), cmp_name);
22}
23
24static int is_exported(const char *name, unsigned long value,
25 const struct module *mod)
26{
27 const struct kernel_symbol *ks;
28
29 if (!mod)
30 ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab);
31 else
32 ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms);
33
34 return ks && kernel_symbol_value(ks) == value;
35}
36
37/* As per nm */
38static char elf_type(const Elf_Sym *sym, const struct load_info *info)
39{
40 const Elf_Shdr *sechdrs = info->sechdrs;
41
42 if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
43 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)
44 return 'v';
45 else
46 return 'w';
47 }
48 if (sym->st_shndx == SHN_UNDEF)
49 return 'U';
50 if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu)
51 return 'a';
52 if (sym->st_shndx >= SHN_LORESERVE)
53 return '?';
54 if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR)
55 return 't';
56 if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC &&
57 sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) {
58 if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE))
59 return 'r';
60 else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
61 return 'g';
62 else
63 return 'd';
64 }
65 if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) {
66 if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL)
67 return 's';
68 else
69 return 'b';
70 }
71 if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name,
72 ".debug")) {
73 return 'n';
74 }
75 return '?';
76}
77
78static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
79 unsigned int shnum, unsigned int pcpundx)
80{
81 const Elf_Shdr *sec;
82 enum mod_mem_type type;
83
84 if (src->st_shndx == SHN_UNDEF ||
85 src->st_shndx >= shnum ||
86 !src->st_name)
87 return false;
88
89#ifdef CONFIG_KALLSYMS_ALL
90 if (src->st_shndx == pcpundx)
91 return true;
92#endif
93
94 sec = sechdrs + src->st_shndx;
95 type = sec->sh_entsize >> SH_ENTSIZE_TYPE_SHIFT;
96 if (!(sec->sh_flags & SHF_ALLOC)
97#ifndef CONFIG_KALLSYMS_ALL
98 || !(sec->sh_flags & SHF_EXECINSTR)
99#endif
100 || mod_mem_type_is_init(type))
101 return false;
102
103 return true;
104}
105
106/*
107 * We only allocate and copy the strings needed by the parts of symtab
108 * we keep. This is simple, but has the effect of making multiple
109 * copies of duplicates. We could be more sophisticated, see
110 * linux-kernel thread starting with
111 * <73defb5e4bca04a6431392cc341112b1@localhost>.
112 */
113void layout_symtab(struct module *mod, struct load_info *info)
114{
115 Elf_Shdr *symsect = info->sechdrs + info->index.sym;
116 Elf_Shdr *strsect = info->sechdrs + info->index.str;
117 const Elf_Sym *src;
118 unsigned int i, nsrc, ndst, strtab_size = 0;
119 struct module_memory *mod_mem_data = &mod->mem[MOD_DATA];
120 struct module_memory *mod_mem_init_data = &mod->mem[MOD_INIT_DATA];
121
122 /* Put symbol section at end of init part of module. */
123 symsect->sh_flags |= SHF_ALLOC;
124 symsect->sh_entsize = module_get_offset_and_type(mod, MOD_INIT_DATA,
125 symsect, info->index.sym);
126 pr_debug("\t%s\n", info->secstrings + symsect->sh_name);
127
128 src = (void *)info->hdr + symsect->sh_offset;
129 nsrc = symsect->sh_size / sizeof(*src);
130
131 /* Compute total space required for the core symbols' strtab. */
132 for (ndst = i = 0; i < nsrc; i++) {
133 if (i == 0 || is_livepatch_module(mod) ||
134 is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
135 info->index.pcpu)) {
136 strtab_size += strlen(&info->strtab[src[i].st_name]) + 1;
137 ndst++;
138 }
139 }
140
141 /* Append room for core symbols at end of core part. */
142 info->symoffs = ALIGN(mod_mem_data->size, symsect->sh_addralign ?: 1);
143 info->stroffs = mod_mem_data->size = info->symoffs + ndst * sizeof(Elf_Sym);
144 mod_mem_data->size += strtab_size;
145 /* Note add_kallsyms() computes strtab_size as core_typeoffs - stroffs */
146 info->core_typeoffs = mod_mem_data->size;
147 mod_mem_data->size += ndst * sizeof(char);
148
149 /* Put string table section at end of init part of module. */
150 strsect->sh_flags |= SHF_ALLOC;
151 strsect->sh_entsize = module_get_offset_and_type(mod, MOD_INIT_DATA,
152 strsect, info->index.str);
153 pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
154
155 /* We'll tack temporary mod_kallsyms on the end. */
156 mod_mem_init_data->size = ALIGN(mod_mem_init_data->size,
157 __alignof__(struct mod_kallsyms));
158 info->mod_kallsyms_init_off = mod_mem_init_data->size;
159
160 mod_mem_init_data->size += sizeof(struct mod_kallsyms);
161 info->init_typeoffs = mod_mem_init_data->size;
162 mod_mem_init_data->size += nsrc * sizeof(char);
163}
164
165/*
166 * We use the full symtab and strtab which layout_symtab arranged to
167 * be appended to the init section. Later we switch to the cut-down
168 * core-only ones.
169 */
170void add_kallsyms(struct module *mod, const struct load_info *info)
171{
172 unsigned int i, ndst;
173 const Elf_Sym *src;
174 Elf_Sym *dst;
175 char *s;
176 Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
177 unsigned long strtab_size;
178 void *data_base = mod->mem[MOD_DATA].base;
179 void *init_data_base = mod->mem[MOD_INIT_DATA].base;
180 struct mod_kallsyms *kallsyms;
181
182 kallsyms = init_data_base + info->mod_kallsyms_init_off;
183
184 kallsyms->symtab = (void *)symsec->sh_addr;
185 kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
186 /* Make sure we get permanent strtab: don't use info->strtab. */
187 kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
188 kallsyms->typetab = init_data_base + info->init_typeoffs;
189
190 /*
191 * Now populate the cut down core kallsyms for after init
192 * and set types up while we still have access to sections.
193 */
194 mod->core_kallsyms.symtab = dst = data_base + info->symoffs;
195 mod->core_kallsyms.strtab = s = data_base + info->stroffs;
196 mod->core_kallsyms.typetab = data_base + info->core_typeoffs;
197 strtab_size = info->core_typeoffs - info->stroffs;
198 src = kallsyms->symtab;
199 for (ndst = i = 0; i < kallsyms->num_symtab; i++) {
200 kallsyms->typetab[i] = elf_type(src + i, info);
201 if (i == 0 || is_livepatch_module(mod) ||
202 is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum,
203 info->index.pcpu)) {
204 ssize_t ret;
205
206 mod->core_kallsyms.typetab[ndst] =
207 kallsyms->typetab[i];
208 dst[ndst] = src[i];
209 dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
210 ret = strscpy(s, &kallsyms->strtab[src[i].st_name],
211 strtab_size);
212 if (ret < 0)
213 break;
214 s += ret + 1;
215 strtab_size -= ret + 1;
216 }
217 }
218
219 /* Set up to point into init section. */
220 rcu_assign_pointer(mod->kallsyms, kallsyms);
221 mod->core_kallsyms.num_symtab = ndst;
222}
223
224#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
225void init_build_id(struct module *mod, const struct load_info *info)
226{
227 const Elf_Shdr *sechdr;
228 unsigned int i;
229
230 for (i = 0; i < info->hdr->e_shnum; i++) {
231 sechdr = &info->sechdrs[i];
232 if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE &&
233 !build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id,
234 sechdr->sh_size))
235 break;
236 }
237}
238#else
239void init_build_id(struct module *mod, const struct load_info *info)
240{
241}
242#endif
243
244static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum)
245{
246 return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
247}
248
249/*
250 * Given a module and address, find the corresponding symbol and return its name
251 * while providing its size and offset if needed.
252 */
253static const char *find_kallsyms_symbol(struct module *mod,
254 unsigned long addr,
255 unsigned long *size,
256 unsigned long *offset)
257{
258 unsigned int i, best = 0;
259 unsigned long nextval, bestval;
260 struct mod_kallsyms *kallsyms = rcu_dereference(mod->kallsyms);
261 struct module_memory *mod_mem = NULL;
262
263 for_each_mod_mem_type(type) {
264#ifndef CONFIG_KALLSYMS_ALL
265 if (!mod_mem_type_is_text(type))
266 continue;
267#endif
268 if (within_module_mem_type(addr, mod, type)) {
269 mod_mem = &mod->mem[type];
270 break;
271 }
272 }
273
274 if (!mod_mem)
275 return NULL;
276
277 /* Initialize bounds within memory region the address belongs to. */
278 nextval = (unsigned long)mod_mem->base + mod_mem->size;
279 bestval = (unsigned long)mod_mem->base - 1;
280
281 /*
282 * Scan for closest preceding symbol, and next symbol. (ELF
283 * starts real symbols at 1).
284 */
285 for (i = 1; i < kallsyms->num_symtab; i++) {
286 const Elf_Sym *sym = &kallsyms->symtab[i];
287 unsigned long thisval = kallsyms_symbol_value(sym);
288
289 if (sym->st_shndx == SHN_UNDEF)
290 continue;
291
292 /*
293 * We ignore unnamed symbols: they're uninformative
294 * and inserted at a whim.
295 */
296 if (*kallsyms_symbol_name(kallsyms, i) == '\0' ||
297 is_mapping_symbol(kallsyms_symbol_name(kallsyms, i)))
298 continue;
299
300 if (thisval <= addr && thisval > bestval) {
301 best = i;
302 bestval = thisval;
303 }
304 if (thisval > addr && thisval < nextval)
305 nextval = thisval;
306 }
307
308 if (!best)
309 return NULL;
310
311 if (size)
312 *size = nextval - bestval;
313 if (offset)
314 *offset = addr - bestval;
315
316 return kallsyms_symbol_name(kallsyms, best);
317}
318
319void * __weak dereference_module_function_descriptor(struct module *mod,
320 void *ptr)
321{
322 return ptr;
323}
324
325/*
326 * For kallsyms to ask for address resolution. NULL means not found. Careful
327 * not to lock to avoid deadlock on oopses, RCU is enough.
328 */
329int module_address_lookup(unsigned long addr,
330 unsigned long *size,
331 unsigned long *offset,
332 char **modname,
333 const unsigned char **modbuildid,
334 char *namebuf)
335{
336 const char *sym;
337 int ret = 0;
338 struct module *mod;
339
340 guard(rcu)();
341 mod = __module_address(addr);
342 if (mod) {
343 if (modname)
344 *modname = mod->name;
345 if (modbuildid)
346 *modbuildid = module_buildid(mod);
347
348 sym = find_kallsyms_symbol(mod, addr, size, offset);
349
350 if (sym)
351 ret = strscpy(namebuf, sym, KSYM_NAME_LEN);
352 }
353 return ret;
354}
355
356int lookup_module_symbol_name(unsigned long addr, char *symname)
357{
358 struct module *mod;
359
360 guard(rcu)();
361 list_for_each_entry_rcu(mod, &modules, list) {
362 if (mod->state == MODULE_STATE_UNFORMED)
363 continue;
364 if (within_module(addr, mod)) {
365 const char *sym;
366
367 sym = find_kallsyms_symbol(mod, addr, NULL, NULL);
368 if (!sym)
369 goto out;
370
371 strscpy(symname, sym, KSYM_NAME_LEN);
372 return 0;
373 }
374 }
375out:
376 return -ERANGE;
377}
378
379int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
380 char *name, char *module_name, int *exported)
381{
382 struct module *mod;
383
384 guard(rcu)();
385 list_for_each_entry_rcu(mod, &modules, list) {
386 struct mod_kallsyms *kallsyms;
387
388 if (mod->state == MODULE_STATE_UNFORMED)
389 continue;
390 kallsyms = rcu_dereference(mod->kallsyms);
391 if (symnum < kallsyms->num_symtab) {
392 const Elf_Sym *sym = &kallsyms->symtab[symnum];
393
394 *value = kallsyms_symbol_value(sym);
395 *type = kallsyms->typetab[symnum];
396 strscpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN);
397 strscpy(module_name, mod->name, MODULE_NAME_LEN);
398 *exported = is_exported(name, *value, mod);
399 return 0;
400 }
401 symnum -= kallsyms->num_symtab;
402 }
403 return -ERANGE;
404}
405
406/* Given a module and name of symbol, find and return the symbol's value */
407static unsigned long __find_kallsyms_symbol_value(struct module *mod, const char *name)
408{
409 unsigned int i;
410 struct mod_kallsyms *kallsyms = rcu_dereference(mod->kallsyms);
411
412 for (i = 0; i < kallsyms->num_symtab; i++) {
413 const Elf_Sym *sym = &kallsyms->symtab[i];
414
415 if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 &&
416 sym->st_shndx != SHN_UNDEF)
417 return kallsyms_symbol_value(sym);
418 }
419 return 0;
420}
421
422static unsigned long __module_kallsyms_lookup_name(const char *name)
423{
424 struct module *mod;
425 char *colon;
426
427 colon = strnchr(name, MODULE_NAME_LEN, ':');
428 if (colon) {
429 mod = find_module_all(name, colon - name, false);
430 if (mod)
431 return __find_kallsyms_symbol_value(mod, colon + 1);
432 return 0;
433 }
434
435 list_for_each_entry_rcu(mod, &modules, list) {
436 unsigned long ret;
437
438 if (mod->state == MODULE_STATE_UNFORMED)
439 continue;
440 ret = __find_kallsyms_symbol_value(mod, name);
441 if (ret)
442 return ret;
443 }
444 return 0;
445}
446
447/* Look for this name: can be of form module:name. */
448unsigned long module_kallsyms_lookup_name(const char *name)
449{
450 /* Don't lock: we're in enough trouble already. */
451 guard(rcu)();
452 return __module_kallsyms_lookup_name(name);
453}
454
455unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name)
456{
457 guard(rcu)();
458 return __find_kallsyms_symbol_value(mod, name);
459}
460
461int module_kallsyms_on_each_symbol(const char *modname,
462 int (*fn)(void *, const char *, unsigned long),
463 void *data)
464{
465 struct module *mod;
466 unsigned int i;
467 int ret = 0;
468
469 mutex_lock(&module_mutex);
470 list_for_each_entry(mod, &modules, list) {
471 struct mod_kallsyms *kallsyms;
472
473 if (mod->state == MODULE_STATE_UNFORMED)
474 continue;
475
476 if (modname && strcmp(modname, mod->name))
477 continue;
478
479 kallsyms = rcu_dereference_check(mod->kallsyms,
480 lockdep_is_held(&module_mutex));
481
482 for (i = 0; i < kallsyms->num_symtab; i++) {
483 const Elf_Sym *sym = &kallsyms->symtab[i];
484
485 if (sym->st_shndx == SHN_UNDEF)
486 continue;
487
488 ret = fn(data, kallsyms_symbol_name(kallsyms, i),
489 kallsyms_symbol_value(sym));
490 if (ret != 0)
491 goto out;
492 }
493
494 /*
495 * The given module is found, the subsequent modules do not
496 * need to be compared.
497 */
498 if (modname)
499 break;
500 }
501out:
502 mutex_unlock(&module_mutex);
503 return ret;
504}