aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorMiroslav Benes <mbenes@suse.cz>2015-11-25 21:48:06 -0500
committerJiri Kosina <jkosina@suse.cz>2015-12-04 16:46:26 -0500
commite0224418516b4d8a6c2160574bac18447c354ef0 (patch)
treed1c86aad47d95389109f434a3862a67920da7c2f /kernel/module.c
parent85c898db6327353d38f3dd428457384cf81f83f8 (diff)
module: keep percpu symbols in module's symtab
Currently, percpu symbols from .data..percpu ELF section of a module are not copied over and stored in final symtab array of struct module. Consequently such symbol cannot be returned via kallsyms API (for example kallsyms_lookup_name). This can be especially confusing when the percpu symbol is exported. Only its __ksymtab et al. are present in its symtab. The culprit is in layout_and_allocate() function where SHF_ALLOC flag is dropped for .data..percpu section. There is in fact no need to copy the section to final struct module, because kernel module loader allocates extra percpu section by itself. Unfortunately only symbols from SHF_ALLOC sections are copied due to a check in is_core_symbol(). The patch changes is_core_symbol() function to copy over also percpu symbols (their st_shndx points to .data..percpu ELF section). We do it only if CONFIG_KALLSYMS_ALL is set to be consistent with the rest of the function (ELF section is SHF_ALLOC but !SHF_EXECINSTR). Finally elf_type() returns type 'a' for a percpu symbol because its address is absolute. Signed-off-by: Miroslav Benes <mbenes@suse.cz> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 77212128f34a..912e891e0e2f 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2383,7 +2383,7 @@ static char elf_type(const Elf_Sym *sym, const struct load_info *info)
2383 } 2383 }
2384 if (sym->st_shndx == SHN_UNDEF) 2384 if (sym->st_shndx == SHN_UNDEF)
2385 return 'U'; 2385 return 'U';
2386 if (sym->st_shndx == SHN_ABS) 2386 if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu)
2387 return 'a'; 2387 return 'a';
2388 if (sym->st_shndx >= SHN_LORESERVE) 2388 if (sym->st_shndx >= SHN_LORESERVE)
2389 return '?'; 2389 return '?';
@@ -2412,7 +2412,7 @@ static char elf_type(const Elf_Sym *sym, const struct load_info *info)
2412} 2412}
2413 2413
2414static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, 2414static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
2415 unsigned int shnum) 2415 unsigned int shnum, unsigned int pcpundx)
2416{ 2416{
2417 const Elf_Shdr *sec; 2417 const Elf_Shdr *sec;
2418 2418
@@ -2421,6 +2421,11 @@ static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
2421 || !src->st_name) 2421 || !src->st_name)
2422 return false; 2422 return false;
2423 2423
2424#ifdef CONFIG_KALLSYMS_ALL
2425 if (src->st_shndx == pcpundx)
2426 return true;
2427#endif
2428
2424 sec = sechdrs + src->st_shndx; 2429 sec = sechdrs + src->st_shndx;
2425 if (!(sec->sh_flags & SHF_ALLOC) 2430 if (!(sec->sh_flags & SHF_ALLOC)
2426#ifndef CONFIG_KALLSYMS_ALL 2431#ifndef CONFIG_KALLSYMS_ALL
@@ -2458,7 +2463,8 @@ static void layout_symtab(struct module *mod, struct load_info *info)
2458 /* Compute total space required for the core symbols' strtab. */ 2463 /* Compute total space required for the core symbols' strtab. */
2459 for (ndst = i = 0; i < nsrc; i++) { 2464 for (ndst = i = 0; i < nsrc; i++) {
2460 if (i == 0 || 2465 if (i == 0 ||
2461 is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { 2466 is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
2467 info->index.pcpu)) {
2462 strtab_size += strlen(&info->strtab[src[i].st_name])+1; 2468 strtab_size += strlen(&info->strtab[src[i].st_name])+1;
2463 ndst++; 2469 ndst++;
2464 } 2470 }
@@ -2500,7 +2506,8 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
2500 src = mod->symtab; 2506 src = mod->symtab;
2501 for (ndst = i = 0; i < mod->num_symtab; i++) { 2507 for (ndst = i = 0; i < mod->num_symtab; i++) {
2502 if (i == 0 || 2508 if (i == 0 ||
2503 is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { 2509 is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
2510 info->index.pcpu)) {
2504 dst[ndst] = src[i]; 2511 dst[ndst] = src[i];
2505 dst[ndst++].st_name = s - mod->core_strtab; 2512 dst[ndst++].st_name = s - mod->core_strtab;
2506 s += strlcpy(s, &mod->strtab[src[i].st_name], 2513 s += strlcpy(s, &mod->strtab[src[i].st_name],