1 /* 2 * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #include <linux/elf.h> 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 13 #include <asm/cache.h> 14 #include <asm/opcodes.h> 15 16 #define PLT_ENT_STRIDE L1_CACHE_BYTES 17 #define PLT_ENT_COUNT (PLT_ENT_STRIDE / sizeof(u32)) 18 #define PLT_ENT_SIZE (sizeof(struct plt_entries) / PLT_ENT_COUNT) 19 20 #ifdef CONFIG_THUMB2_KERNEL 21 #define PLT_ENT_LDR __opcode_to_mem_thumb32(0xf8dff000 | \ 22 (PLT_ENT_STRIDE - 4)) 23 #else 24 #define PLT_ENT_LDR __opcode_to_mem_arm(0xe59ff000 | \ 25 (PLT_ENT_STRIDE - 8)) 26 #endif 27 28 struct plt_entries { 29 u32 ldr[PLT_ENT_COUNT]; 30 u32 lit[PLT_ENT_COUNT]; 31 }; 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) 39 { 40 struct plt_entries *plt, *plt_end; 41 int c, *count; 42 43 if (in_init(mod, loc)) { 44 plt = (void *)mod->arch.init_plt->sh_addr; 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 53 /* Look for an existing entry pointing to 'val' */ 54 for (c = *count; plt < plt_end; c -= PLT_ENT_COUNT, plt++) { 55 int i; 56 57 if (!c) { 58 /* Populate a new set of entries */ 59 *plt = (struct plt_entries){ 60 { [0 ... PLT_ENT_COUNT - 1] = PLT_ENT_LDR, }, 61 { val, } 62 }; 63 ++*count; 64 return (u32)plt->ldr; 65 } 66 for (i = 0; i < PLT_ENT_COUNT; i++) { 67 if (!plt->lit[i]) { 68 plt->lit[i] = val; 69 ++*count; 70 } 71 if (plt->lit[i] == val) 72 return (u32)&plt->ldr[i]; 73 } 74 } 75 BUG(); 76 } 77 78 static int duplicate_rel(Elf32_Addr base, const Elf32_Rel *rel, int num, 79 u32 mask) 80 { 81 u32 *loc1, *loc2; 82 int i; 83 84 for (i = 0; i < num; i++) { 85 if (rel[i].r_info != rel[num].r_info) 86 continue; 87 88 /* 89 * Identical relocation types against identical symbols can 90 * still result in different PLT entries if the addend in the 91 * place is different. So resolve the target of the relocation 92 * to compare the values. 93 */ 94 loc1 = (u32 *)(base + rel[i].r_offset); 95 loc2 = (u32 *)(base + rel[num].r_offset); 96 if (((*loc1 ^ *loc2) & mask) == 0) 97 return 1; 98 } 99 return 0; 100 } 101 102 /* Count how many PLT entries we may need */ 103 static unsigned int count_plts(Elf32_Addr base, const Elf32_Rel *rel, int num) 104 { 105 unsigned int ret = 0; 106 int i; 107 108 /* 109 * Sure, this is order(n^2), but it's usually short, and not 110 * time critical 111 */ 112 for (i = 0; i < num; i++) 113 switch (ELF32_R_TYPE(rel[i].r_info)) { 114 case R_ARM_CALL: 115 case R_ARM_PC24: 116 case R_ARM_JUMP24: 117 if (!duplicate_rel(base, rel, i, 118 __opcode_to_mem_arm(0x00ffffff))) 119 ret++; 120 break; 121 #ifdef CONFIG_THUMB2_KERNEL 122 case R_ARM_THM_CALL: 123 case R_ARM_THM_JUMP24: 124 if (!duplicate_rel(base, rel, i, 125 __opcode_to_mem_thumb32(0x07ff2fff))) 126 ret++; 127 #endif 128 } 129 return ret; 130 } 131 132 int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, 133 char *secstrings, struct module *mod) 134 { 135 unsigned long core_plts = 0, init_plts = 0; 136 Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; 137 138 /* 139 * To store the PLTs, we expand the .text section for core module code 140 * and the .init.text section for initialization code. 141 */ 142 for (s = sechdrs; s < sechdrs_end; ++s) 143 if (strcmp(".core.plt", secstrings + s->sh_name) == 0) 144 mod->arch.core_plt = s; 145 else if (strcmp(".init.plt", secstrings + s->sh_name) == 0) 146 mod->arch.init_plt = s; 147 148 if (!mod->arch.core_plt || !mod->arch.init_plt) { 149 pr_err("%s: sections missing\n", mod->name); 150 return -ENOEXEC; 151 } 152 153 for (s = sechdrs + 1; s < sechdrs_end; ++s) { 154 const Elf32_Rel *rels = (void *)ehdr + s->sh_offset; 155 int numrels = s->sh_size / sizeof(Elf32_Rel); 156 Elf32_Shdr *dstsec = sechdrs + s->sh_info; 157 158 if (s->sh_type != SHT_REL) 159 continue; 160 161 if (strstr(secstrings + s->sh_name, ".init")) 162 init_plts += count_plts(dstsec->sh_addr, rels, numrels); 163 else 164 core_plts += count_plts(dstsec->sh_addr, rels, numrels); 165 } 166 167 mod->arch.core_plt->sh_type = SHT_NOBITS; 168 mod->arch.core_plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 169 mod->arch.core_plt->sh_addralign = L1_CACHE_BYTES; 170 mod->arch.core_plt->sh_size = round_up(core_plts * PLT_ENT_SIZE, 171 sizeof(struct plt_entries)); 172 mod->arch.core_plt_count = 0; 173 174 mod->arch.init_plt->sh_type = SHT_NOBITS; 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; 183 } 184