From: Ard Biesheuvel <[email protected]>

It is no longer possible for .init.text to end up being placed out of
direct branching range of the .text section of the same module, so the
PLT array of core and init code can be combined again.

It also means there is no longer a need to allocate PLT entries for
cross-section calls within the same module, and so the upper bound
for the number of needed entries can be lowered again as well.

Signed-off-by: Ard Biesheuvel <[email protected]>
---
 arch/arm64/include/asm/module.h     |  1 -
 arch/arm64/include/asm/module.lds.h |  1 -
 arch/arm64/kernel/module-plts.c     | 35 +++++---------------
 3 files changed, 9 insertions(+), 28 deletions(-)

diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
index 79550b22ba19..9328fadb4a95 100644
--- a/arch/arm64/include/asm/module.h
+++ b/arch/arm64/include/asm/module.h
@@ -15,7 +15,6 @@ struct mod_plt_sec {
 
 struct mod_arch_specific {
        struct mod_plt_sec      core;
-       struct mod_plt_sec      init;
 
        /* for CONFIG_DYNAMIC_FTRACE */
        struct plt_entry        *ftrace_trampolines;
diff --git a/arch/arm64/include/asm/module.lds.h 
b/arch/arm64/include/asm/module.lds.h
index 0c3aea98e116..24fc9401c514 100644
--- a/arch/arm64/include/asm/module.lds.h
+++ b/arch/arm64/include/asm/module.lds.h
@@ -1,6 +1,5 @@
 SECTIONS {
        .plt 0 : { BYTE(0) }
-       .init.plt 0 : { BYTE(0) }
        .text.ftrace_trampoline 0 : { BYTE(0) }
 
 #ifdef CONFIG_KASAN_SW_TAGS
diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c
index bde32979c06a..e30876b90e30 100644
--- a/arch/arm64/kernel/module-plts.c
+++ b/arch/arm64/kernel/module-plts.c
@@ -70,8 +70,7 @@ u64 module_emit_plt_entry(struct module *mod, Elf64_Shdr 
*sechdrs,
                          void *loc, const Elf64_Rela *rela,
                          Elf64_Sym *sym)
 {
-       struct mod_plt_sec *pltsec = !within_module_init((unsigned long)loc, 
mod) ?
-                                               &mod->arch.core : 
&mod->arch.init;
+       struct mod_plt_sec *pltsec = &mod->arch.core;
        struct plt_entry *plt = (struct plt_entry 
*)sechdrs[pltsec->plt_shndx].sh_addr;
        int i = pltsec->plt_num_entries;
        int j = i - 1;
@@ -101,8 +100,7 @@ u64 module_emit_plt_entry(struct module *mod, Elf64_Shdr 
*sechdrs,
 u64 module_emit_veneer_for_adrp(struct module *mod, Elf64_Shdr *sechdrs,
                                void *loc, u64 val)
 {
-       struct mod_plt_sec *pltsec = !within_module_init((unsigned long)loc, 
mod) ?
-                                               &mod->arch.core : 
&mod->arch.init;
+       struct mod_plt_sec *pltsec = &mod->arch.core;
        struct plt_entry *plt = (struct plt_entry 
*)sechdrs[pltsec->plt_shndx].sh_addr;
        int i = pltsec->plt_num_entries++;
        u32 br;
@@ -169,17 +167,17 @@ static unsigned int count_plts(Elf64_Sym *syms, 
Elf64_Rela *rela, int num,
                case R_AARCH64_CALL26:
                        /*
                         * We only have to consider branch targets that resolve
-                        * to symbols that are defined in a different section.
+                        * to symbols that are not defined in the same module.
                         * This is not simply a heuristic, it is a fundamental
                         * limitation, since there is no guaranteed way to emit
                         * PLT entries sufficiently close to the branch if the
                         * section size exceeds the range of a branch
                         * instruction. So ignore relocations against defined
-                        * symbols if they live in the same section as the
+                        * symbols if they live in the same module as the
                         * relocation target.
                         */
                        s = syms + ELF64_R_SYM(rela[i].r_info);
-                       if (s->st_shndx == dstidx)
+                       if (s->st_shndx != SHN_UNDEF)
                                break;
 
                        /*
@@ -281,7 +279,6 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr 
*sechdrs,
                              char *secstrings, struct module *mod)
 {
        unsigned long core_plts = 0;
-       unsigned long init_plts = 0;
        Elf64_Sym *syms = NULL;
        Elf_Shdr *pltsec, *tramp = NULL;
        int i;
@@ -293,8 +290,6 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr 
*sechdrs,
        for (i = 0; i < ehdr->e_shnum; i++) {
                if (!strcmp(secstrings + sechdrs[i].sh_name, ".plt"))
                        mod->arch.core.plt_shndx = i;
-               else if (!strcmp(secstrings + sechdrs[i].sh_name, ".init.plt"))
-                       mod->arch.init.plt_shndx = i;
                else if (!strcmp(secstrings + sechdrs[i].sh_name,
                                 ".text.ftrace_trampoline"))
                        tramp = sechdrs + i;
@@ -302,8 +297,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr 
*sechdrs,
                        syms = (Elf64_Sym *)sechdrs[i].sh_addr;
        }
 
-       if (!mod->arch.core.plt_shndx || !mod->arch.init.plt_shndx) {
-               pr_err("%s: module PLT section(s) missing\n", mod->name);
+       if (!mod->arch.core.plt_shndx) {
+               pr_err("%s: module PLT section missing\n", mod->name);
                return -ENOEXEC;
        }
        if (!syms) {
@@ -332,12 +327,8 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr 
*sechdrs,
                if (nents)
                        sort(rels, nents, sizeof(Elf64_Rela), cmp_rela, NULL);
 
-               if (!module_init_layout_section(secstrings + dstsec->sh_name))
-                       core_plts += count_plts(syms, rels, numrels,
-                                               sechdrs[i].sh_info, dstsec);
-               else
-                       init_plts += count_plts(syms, rels, numrels,
-                                               sechdrs[i].sh_info, dstsec);
+               core_plts += count_plts(syms, rels, numrels, sechdrs[i].sh_info,
+                                       dstsec);
        }
 
        pltsec = sechdrs + mod->arch.core.plt_shndx;
@@ -348,14 +339,6 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr 
*sechdrs,
        mod->arch.core.plt_num_entries = 0;
        mod->arch.core.plt_max_entries = core_plts;
 
-       pltsec = sechdrs + mod->arch.init.plt_shndx;
-       pltsec->sh_type = SHT_NOBITS;
-       pltsec->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
-       pltsec->sh_addralign = L1_CACHE_BYTES;
-       pltsec->sh_size = (init_plts + 1) * sizeof(struct plt_entry);
-       mod->arch.init.plt_num_entries = 0;
-       mod->arch.init.plt_max_entries = init_plts;
-
        if (tramp) {
                tramp->sh_type = SHT_NOBITS;
                tramp->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
-- 
2.55.0.860.g4b6b3295ed-goog


Reply via email to