diff options
| -rw-r--r-- | arch/arm/include/asm/module.h | 6 | ||||
| -rw-r--r-- | arch/arm/kernel/module-plts.c | 68 | ||||
| -rw-r--r-- | arch/arm/kernel/module.lds | 3 |
3 files changed, 25 insertions, 52 deletions
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index e358b7966c06..464748b9fd7d 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h | |||
| @@ -23,10 +23,8 @@ struct mod_arch_specific { | |||
| 23 | struct unwind_table *unwind[ARM_SEC_MAX]; | 23 | struct unwind_table *unwind[ARM_SEC_MAX]; |
| 24 | #endif | 24 | #endif |
| 25 | #ifdef CONFIG_ARM_MODULE_PLTS | 25 | #ifdef CONFIG_ARM_MODULE_PLTS |
| 26 | struct elf32_shdr *core_plt; | 26 | struct elf32_shdr *plt; |
| 27 | struct elf32_shdr *init_plt; | 27 | int plt_count; |
| 28 | int core_plt_count; | ||
| 29 | int init_plt_count; | ||
| 30 | #endif | 28 | #endif |
| 31 | }; | 29 | }; |
| 32 | 30 | ||
diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c index 0c7efc3446c0..6832d1d6444e 100644 --- a/arch/arm/kernel/module-plts.c +++ b/arch/arm/kernel/module-plts.c | |||
| @@ -30,28 +30,16 @@ struct plt_entries { | |||
| 30 | u32 lit[PLT_ENT_COUNT]; | 30 | u32 lit[PLT_ENT_COUNT]; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | static bool in_init(const struct module *mod, u32 addr) | ||
| 34 | { | ||
| 35 | return addr - (u32)mod->init_layout.base < mod->init_layout.size; | ||
| 36 | } | ||
| 37 | |||
| 38 | u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) | 33 | u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) |
| 39 | { | 34 | { |
| 40 | struct plt_entries *plt, *plt_end; | 35 | struct plt_entries *plt, *plt_end; |
| 41 | int c, *count; | 36 | int c; |
| 42 | 37 | ||
| 43 | if (in_init(mod, loc)) { | 38 | plt = (void *)mod->arch.plt->sh_addr; |
| 44 | plt = (void *)mod->arch.init_plt->sh_addr; | 39 | plt_end = (void *)plt + mod->arch.plt->sh_size; |
| 45 | plt_end = (void *)plt + mod->arch.init_plt->sh_size; | ||
| 46 | count = &mod->arch.init_plt_count; | ||
| 47 | } else { | ||
| 48 | plt = (void *)mod->arch.core_plt->sh_addr; | ||
| 49 | plt_end = (void *)plt + mod->arch.core_plt->sh_size; | ||
| 50 | count = &mod->arch.core_plt_count; | ||
| 51 | } | ||
| 52 | 40 | ||
| 53 | /* Look for an existing entry pointing to 'val' */ | 41 | /* Look for an existing entry pointing to 'val' */ |
| 54 | for (c = *count; plt < plt_end; c -= PLT_ENT_COUNT, plt++) { | 42 | for (c = mod->arch.plt_count; plt < plt_end; c -= PLT_ENT_COUNT, plt++) { |
| 55 | int i; | 43 | int i; |
| 56 | 44 | ||
| 57 | if (!c) { | 45 | if (!c) { |
| @@ -60,13 +48,13 @@ u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val) | |||
| 60 | { [0 ... PLT_ENT_COUNT - 1] = PLT_ENT_LDR, }, | 48 | { [0 ... PLT_ENT_COUNT - 1] = PLT_ENT_LDR, }, |
| 61 | { val, } | 49 | { val, } |
| 62 | }; | 50 | }; |
| 63 | ++*count; | 51 | mod->arch.plt_count++; |
| 64 | return (u32)plt->ldr; | 52 | return (u32)plt->ldr; |
| 65 | } | 53 | } |
| 66 | for (i = 0; i < PLT_ENT_COUNT; i++) { | 54 | for (i = 0; i < PLT_ENT_COUNT; i++) { |
| 67 | if (!plt->lit[i]) { | 55 | if (!plt->lit[i]) { |
| 68 | plt->lit[i] = val; | 56 | plt->lit[i] = val; |
| 69 | ++*count; | 57 | mod->arch.plt_count++; |
| 70 | } | 58 | } |
| 71 | if (plt->lit[i] == val) | 59 | if (plt->lit[i] == val) |
| 72 | return (u32)&plt->ldr[i]; | 60 | return (u32)&plt->ldr[i]; |
| @@ -132,21 +120,19 @@ static unsigned int count_plts(Elf32_Addr base, const Elf32_Rel *rel, int num) | |||
| 132 | int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | 120 | int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, |
| 133 | char *secstrings, struct module *mod) | 121 | char *secstrings, struct module *mod) |
| 134 | { | 122 | { |
| 135 | unsigned long core_plts = 0, init_plts = 0; | 123 | unsigned long plts = 0; |
| 136 | Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; | 124 | Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; |
| 137 | 125 | ||
| 138 | /* | 126 | /* |
| 139 | * To store the PLTs, we expand the .text section for core module code | 127 | * To store the PLTs, we expand the .text section for core module code |
| 140 | * and the .init.text section for initialization code. | 128 | * and for initialization code. |
| 141 | */ | 129 | */ |
| 142 | for (s = sechdrs; s < sechdrs_end; ++s) | 130 | for (s = sechdrs; s < sechdrs_end; ++s) |
| 143 | if (strcmp(".core.plt", secstrings + s->sh_name) == 0) | 131 | if (strcmp(".plt", secstrings + s->sh_name) == 0) |
| 144 | mod->arch.core_plt = s; | 132 | mod->arch.plt = s; |
| 145 | else if (strcmp(".init.plt", secstrings + s->sh_name) == 0) | ||
| 146 | mod->arch.init_plt = s; | ||
| 147 | 133 | ||
| 148 | if (!mod->arch.core_plt || !mod->arch.init_plt) { | 134 | if (!mod->arch.plt) { |
| 149 | pr_err("%s: sections missing\n", mod->name); | 135 | pr_err("%s: module PLT section missing\n", mod->name); |
| 150 | return -ENOEXEC; | 136 | return -ENOEXEC; |
| 151 | } | 137 | } |
| 152 | 138 | ||
| @@ -158,26 +144,16 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, | |||
| 158 | if (s->sh_type != SHT_REL) | 144 | if (s->sh_type != SHT_REL) |
| 159 | continue; | 145 | continue; |
| 160 | 146 | ||
| 161 | if (strstr(secstrings + s->sh_name, ".init")) | 147 | plts += count_plts(dstsec->sh_addr, rels, numrels); |
| 162 | init_plts += count_plts(dstsec->sh_addr, rels, numrels); | ||
| 163 | else | ||
| 164 | core_plts += count_plts(dstsec->sh_addr, rels, numrels); | ||
| 165 | } | 148 | } |
| 166 | 149 | ||
| 167 | mod->arch.core_plt->sh_type = SHT_NOBITS; | 150 | mod->arch.plt->sh_type = SHT_NOBITS; |
| 168 | mod->arch.core_plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; | 151 | mod->arch.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; |
| 169 | mod->arch.core_plt->sh_addralign = L1_CACHE_BYTES; | 152 | mod->arch.plt->sh_addralign = L1_CACHE_BYTES; |
| 170 | mod->arch.core_plt->sh_size = round_up(core_plts * PLT_ENT_SIZE, | 153 | mod->arch.plt->sh_size = round_up(plts * PLT_ENT_SIZE, |
| 171 | sizeof(struct plt_entries)); | 154 | sizeof(struct plt_entries)); |
| 172 | mod->arch.core_plt_count = 0; | 155 | mod->arch.plt_count = 0; |
| 173 | 156 | ||
| 174 | mod->arch.init_plt->sh_type = SHT_NOBITS; | 157 | pr_debug("%s: plt=%x\n", __func__, mod->arch.plt->sh_size); |
| 175 | mod->arch.init_plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; | ||
| 176 | mod->arch.init_plt->sh_addralign = L1_CACHE_BYTES; | ||
| 177 | mod->arch.init_plt->sh_size = round_up(init_plts * PLT_ENT_SIZE, | ||
| 178 | sizeof(struct plt_entries)); | ||
| 179 | mod->arch.init_plt_count = 0; | ||
| 180 | pr_debug("%s: core.plt=%x, init.plt=%x\n", __func__, | ||
| 181 | mod->arch.core_plt->sh_size, mod->arch.init_plt->sh_size); | ||
| 182 | return 0; | 158 | return 0; |
| 183 | } | 159 | } |
diff --git a/arch/arm/kernel/module.lds b/arch/arm/kernel/module.lds index 3682fa107918..05881e2b414c 100644 --- a/arch/arm/kernel/module.lds +++ b/arch/arm/kernel/module.lds | |||
| @@ -1,4 +1,3 @@ | |||
| 1 | SECTIONS { | 1 | SECTIONS { |
| 2 | .core.plt : { BYTE(0) } | 2 | .plt : { BYTE(0) } |
| 3 | .init.plt : { BYTE(0) } | ||
| 4 | } | 3 | } |
