diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 4b0df09cbe678dc5aa33e97a46972c9de40fef72..ac3df84b935cedf9d510f12da7fe30b1fd78344c 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -20,7 +20,7 @@ enum { #endif struct mod_plt_sec { - struct elf32_shdr *plt; + int plt_shndx; int plt_count; }; @@ -35,7 +35,8 @@ struct mod_arch_specific { }; struct module; -u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val); +u32 get_module_plt(struct module *mod, Elf32_Shdr *sechdrs, + unsigned long loc, Elf32_Addr val); #ifdef CONFIG_THUMB2_KERNEL #define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c index 6e626abaefc54e5f5a5a7f914250a3d6e5f3f9c2..1dbdf27265052223187db21e4b6d2a7c7302e8fd 100644 --- a/arch/arm/kernel/module-plts.c +++ b/arch/arm/kernel/module-plts.c @@ -34,12 +34,14 @@ static bool in_init(const struct module *mod, unsigned long loc) return loc - (u32)mod->init_layout.base < mod->init_layout.size; } -u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) +u32 get_module_plt(struct module *mod, Elf32_Shdr *sechdrs, + unsigned long loc, Elf32_Addr val) { struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core : &mod->arch.init; - struct plt_entries *plt = (struct plt_entries *)pltsec->plt->sh_addr; + struct plt_entries *plt = + (struct plt_entries *)sechdrs[pltsec->plt_shndx].sh_addr; int idx = 0; /* @@ -60,7 +62,8 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) } pltsec->plt_count++; - BUG_ON(pltsec->plt_count * PLT_ENT_SIZE > pltsec->plt->sh_size); + BUG_ON(pltsec->plt_count * PLT_ENT_SIZE > + sechdrs[pltsec->plt_shndx].sh_size); if (!idx) /* Populate a new set of entries */ @@ -193,21 +196,23 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, unsigned long init_plts = 0; Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; Elf32_Sym *syms = NULL; + Elf32_Shdr *core_pltsec, *init_pltsec; + int i = 0; /* * To store the PLTs, we expand the .text section for core module code * and for initialization code. */ - for (s = sechdrs; s < sechdrs_end; ++s) { + for (s = sechdrs; s < sechdrs_end; ++s, ++i) { if (strcmp(".plt", secstrings + s->sh_name) == 0) - mod->arch.core.plt = s; + mod->arch.core.plt_shndx = i; else if (strcmp(".init.plt", secstrings + s->sh_name) == 0) - mod->arch.init.plt = s; + mod->arch.init.plt_shndx = i; else if (s->sh_type == SHT_SYMTAB) syms = (Elf32_Sym *)s->sh_addr; } - if (!mod->arch.core.plt || !mod->arch.init.plt) { + if (!mod->arch.core.plt_shndx || !mod->arch.init.plt_shndx) { pr_err("%s: module PLT section(s) missing\n", mod->name); return -ENOEXEC; } @@ -239,21 +244,23 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, numrels, s->sh_info); } - mod->arch.core.plt->sh_type = SHT_NOBITS; - mod->arch.core.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; - mod->arch.core.plt->sh_addralign = L1_CACHE_BYTES; - mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE, - sizeof(struct plt_entries)); + core_pltsec = sechdrs + mod->arch.core.plt_shndx; + core_pltsec->sh_type = SHT_NOBITS; + core_pltsec->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + core_pltsec->sh_addralign = L1_CACHE_BYTES; + core_pltsec->sh_size = round_up(core_plts * PLT_ENT_SIZE, + sizeof(struct plt_entries)); mod->arch.core.plt_count = 0; - mod->arch.init.plt->sh_type = SHT_NOBITS; - mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; - mod->arch.init.plt->sh_addralign = L1_CACHE_BYTES; - mod->arch.init.plt->sh_size = round_up(init_plts * PLT_ENT_SIZE, - sizeof(struct plt_entries)); + init_pltsec = sechdrs + mod->arch.init.plt_shndx; + init_pltsec->sh_type = SHT_NOBITS; + init_pltsec->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + init_pltsec->sh_addralign = L1_CACHE_BYTES; + init_pltsec->sh_size = round_up(init_plts * PLT_ENT_SIZE, + sizeof(struct plt_entries)); mod->arch.init.plt_count = 0; pr_debug("%s: plt=%x, init.plt=%x\n", __func__, - mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size); + core_pltsec->sh_size, init_pltsec->sh_size); return 0; } diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index beac45e89ba64b07d20cd9d52b6025e2c86e4e8d..1cd09cf38c69bb18cc95ba0acb5de525b0d7c23d 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -142,7 +142,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS) && (offset <= (s32)0xfe000000 || offset >= (s32)0x02000000)) - offset = get_module_plt(module, loc, + offset = get_module_plt(module, sechdrs, loc, offset + loc + 8) - loc - 8; @@ -265,7 +265,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS) && (offset <= (s32)0xff000000 || offset >= (s32)0x01000000)) - offset = get_module_plt(module, loc, + offset = get_module_plt(module, sechdrs, loc, offset + loc + 4) - loc - 4;