Skip to content

Commit 7e35bc6

Browse files
mirabgregkh
authored andcommitted
module: keep percpu symbols in module's symtab
commit e022441 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 104fd57 commit 7e35bc6

1 file changed

Lines changed: 11 additions & 4 deletions

File tree

kernel/module.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2404,7 +2404,7 @@ static char elf_type(const Elf_Sym *sym, const struct load_info *info)
24042404
}
24052405
if (sym->st_shndx == SHN_UNDEF)
24062406
return 'U';
2407-
if (sym->st_shndx == SHN_ABS)
2407+
if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu)
24082408
return 'a';
24092409
if (sym->st_shndx >= SHN_LORESERVE)
24102410
return '?';
@@ -2433,7 +2433,7 @@ static char elf_type(const Elf_Sym *sym, const struct load_info *info)
24332433
}
24342434

24352435
static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
2436-
unsigned int shnum)
2436+
unsigned int shnum, unsigned int pcpundx)
24372437
{
24382438
const Elf_Shdr *sec;
24392439

@@ -2442,6 +2442,11 @@ static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
24422442
|| !src->st_name)
24432443
return false;
24442444

2445+
#ifdef CONFIG_KALLSYMS_ALL
2446+
if (src->st_shndx == pcpundx)
2447+
return true;
2448+
#endif
2449+
24452450
sec = sechdrs + src->st_shndx;
24462451
if (!(sec->sh_flags & SHF_ALLOC)
24472452
#ifndef CONFIG_KALLSYMS_ALL
@@ -2479,7 +2484,8 @@ static void layout_symtab(struct module *mod, struct load_info *info)
24792484
/* Compute total space required for the core symbols' strtab. */
24802485
for (ndst = i = 0; i < nsrc; i++) {
24812486
if (i == 0 ||
2482-
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
2487+
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
2488+
info->index.pcpu)) {
24832489
strtab_size += strlen(&info->strtab[src[i].st_name])+1;
24842490
ndst++;
24852491
}
@@ -2537,7 +2543,8 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
25372543
src = mod->kallsyms->symtab;
25382544
for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
25392545
if (i == 0 ||
2540-
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
2546+
is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum,
2547+
info->index.pcpu)) {
25412548
dst[ndst] = src[i];
25422549
dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
25432550
s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],

0 commit comments

Comments
 (0)