1*ed981856SPaul Mackerras /* Kernel module help for PPC. 2*ed981856SPaul Mackerras Copyright (C) 2001 Rusty Russell. 3*ed981856SPaul Mackerras 4*ed981856SPaul Mackerras This program is free software; you can redistribute it and/or modify 5*ed981856SPaul Mackerras it under the terms of the GNU General Public License as published by 6*ed981856SPaul Mackerras the Free Software Foundation; either version 2 of the License, or 7*ed981856SPaul Mackerras (at your option) any later version. 8*ed981856SPaul Mackerras 9*ed981856SPaul Mackerras This program is distributed in the hope that it will be useful, 10*ed981856SPaul Mackerras but WITHOUT ANY WARRANTY; without even the implied warranty of 11*ed981856SPaul Mackerras MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*ed981856SPaul Mackerras GNU General Public License for more details. 13*ed981856SPaul Mackerras 14*ed981856SPaul Mackerras You should have received a copy of the GNU General Public License 15*ed981856SPaul Mackerras along with this program; if not, write to the Free Software 16*ed981856SPaul Mackerras Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17*ed981856SPaul Mackerras */ 18*ed981856SPaul Mackerras #include <linux/module.h> 19*ed981856SPaul Mackerras #include <linux/moduleloader.h> 20*ed981856SPaul Mackerras #include <linux/elf.h> 21*ed981856SPaul Mackerras #include <linux/vmalloc.h> 22*ed981856SPaul Mackerras #include <linux/fs.h> 23*ed981856SPaul Mackerras #include <linux/string.h> 24*ed981856SPaul Mackerras #include <linux/kernel.h> 25*ed981856SPaul Mackerras #include <linux/cache.h> 26*ed981856SPaul Mackerras 27*ed981856SPaul Mackerras #if 0 28*ed981856SPaul Mackerras #define DEBUGP printk 29*ed981856SPaul Mackerras #else 30*ed981856SPaul Mackerras #define DEBUGP(fmt , ...) 31*ed981856SPaul Mackerras #endif 32*ed981856SPaul Mackerras 33*ed981856SPaul Mackerras LIST_HEAD(module_bug_list); 34*ed981856SPaul Mackerras 35*ed981856SPaul Mackerras void *module_alloc(unsigned long size) 36*ed981856SPaul Mackerras { 37*ed981856SPaul Mackerras if (size == 0) 38*ed981856SPaul Mackerras return NULL; 39*ed981856SPaul Mackerras return vmalloc(size); 40*ed981856SPaul Mackerras } 41*ed981856SPaul Mackerras 42*ed981856SPaul Mackerras /* Free memory returned from module_alloc */ 43*ed981856SPaul Mackerras void module_free(struct module *mod, void *module_region) 44*ed981856SPaul Mackerras { 45*ed981856SPaul Mackerras vfree(module_region); 46*ed981856SPaul Mackerras /* FIXME: If module_region == mod->init_region, trim exception 47*ed981856SPaul Mackerras table entries. */ 48*ed981856SPaul Mackerras } 49*ed981856SPaul Mackerras 50*ed981856SPaul Mackerras /* Count how many different relocations (different symbol, different 51*ed981856SPaul Mackerras addend) */ 52*ed981856SPaul Mackerras static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) 53*ed981856SPaul Mackerras { 54*ed981856SPaul Mackerras unsigned int i, j, ret = 0; 55*ed981856SPaul Mackerras 56*ed981856SPaul Mackerras /* Sure, this is order(n^2), but it's usually short, and not 57*ed981856SPaul Mackerras time critical */ 58*ed981856SPaul Mackerras for (i = 0; i < num; i++) { 59*ed981856SPaul Mackerras for (j = 0; j < i; j++) { 60*ed981856SPaul Mackerras /* If this addend appeared before, it's 61*ed981856SPaul Mackerras already been counted */ 62*ed981856SPaul Mackerras if (ELF32_R_SYM(rela[i].r_info) 63*ed981856SPaul Mackerras == ELF32_R_SYM(rela[j].r_info) 64*ed981856SPaul Mackerras && rela[i].r_addend == rela[j].r_addend) 65*ed981856SPaul Mackerras break; 66*ed981856SPaul Mackerras } 67*ed981856SPaul Mackerras if (j == i) ret++; 68*ed981856SPaul Mackerras } 69*ed981856SPaul Mackerras return ret; 70*ed981856SPaul Mackerras } 71*ed981856SPaul Mackerras 72*ed981856SPaul Mackerras /* Get the potential trampolines size required of the init and 73*ed981856SPaul Mackerras non-init sections */ 74*ed981856SPaul Mackerras static unsigned long get_plt_size(const Elf32_Ehdr *hdr, 75*ed981856SPaul Mackerras const Elf32_Shdr *sechdrs, 76*ed981856SPaul Mackerras const char *secstrings, 77*ed981856SPaul Mackerras int is_init) 78*ed981856SPaul Mackerras { 79*ed981856SPaul Mackerras unsigned long ret = 0; 80*ed981856SPaul Mackerras unsigned i; 81*ed981856SPaul Mackerras 82*ed981856SPaul Mackerras /* Everything marked ALLOC (this includes the exported 83*ed981856SPaul Mackerras symbols) */ 84*ed981856SPaul Mackerras for (i = 1; i < hdr->e_shnum; i++) { 85*ed981856SPaul Mackerras /* If it's called *.init*, and we're not init, we're 86*ed981856SPaul Mackerras not interested */ 87*ed981856SPaul Mackerras if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) 88*ed981856SPaul Mackerras != is_init) 89*ed981856SPaul Mackerras continue; 90*ed981856SPaul Mackerras 91*ed981856SPaul Mackerras /* We don't want to look at debug sections. */ 92*ed981856SPaul Mackerras if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0) 93*ed981856SPaul Mackerras continue; 94*ed981856SPaul Mackerras 95*ed981856SPaul Mackerras if (sechdrs[i].sh_type == SHT_RELA) { 96*ed981856SPaul Mackerras DEBUGP("Found relocations in section %u\n", i); 97*ed981856SPaul Mackerras DEBUGP("Ptr: %p. Number: %u\n", 98*ed981856SPaul Mackerras (void *)hdr + sechdrs[i].sh_offset, 99*ed981856SPaul Mackerras sechdrs[i].sh_size / sizeof(Elf32_Rela)); 100*ed981856SPaul Mackerras ret += count_relocs((void *)hdr 101*ed981856SPaul Mackerras + sechdrs[i].sh_offset, 102*ed981856SPaul Mackerras sechdrs[i].sh_size 103*ed981856SPaul Mackerras / sizeof(Elf32_Rela)) 104*ed981856SPaul Mackerras * sizeof(struct ppc_plt_entry); 105*ed981856SPaul Mackerras } 106*ed981856SPaul Mackerras } 107*ed981856SPaul Mackerras 108*ed981856SPaul Mackerras return ret; 109*ed981856SPaul Mackerras } 110*ed981856SPaul Mackerras 111*ed981856SPaul Mackerras int module_frob_arch_sections(Elf32_Ehdr *hdr, 112*ed981856SPaul Mackerras Elf32_Shdr *sechdrs, 113*ed981856SPaul Mackerras char *secstrings, 114*ed981856SPaul Mackerras struct module *me) 115*ed981856SPaul Mackerras { 116*ed981856SPaul Mackerras unsigned int i; 117*ed981856SPaul Mackerras 118*ed981856SPaul Mackerras /* Find .plt and .init.plt sections */ 119*ed981856SPaul Mackerras for (i = 0; i < hdr->e_shnum; i++) { 120*ed981856SPaul Mackerras if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0) 121*ed981856SPaul Mackerras me->arch.init_plt_section = i; 122*ed981856SPaul Mackerras else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0) 123*ed981856SPaul Mackerras me->arch.core_plt_section = i; 124*ed981856SPaul Mackerras } 125*ed981856SPaul Mackerras if (!me->arch.core_plt_section || !me->arch.init_plt_section) { 126*ed981856SPaul Mackerras printk("Module doesn't contain .plt or .init.plt sections.\n"); 127*ed981856SPaul Mackerras return -ENOEXEC; 128*ed981856SPaul Mackerras } 129*ed981856SPaul Mackerras 130*ed981856SPaul Mackerras /* Override their sizes */ 131*ed981856SPaul Mackerras sechdrs[me->arch.core_plt_section].sh_size 132*ed981856SPaul Mackerras = get_plt_size(hdr, sechdrs, secstrings, 0); 133*ed981856SPaul Mackerras sechdrs[me->arch.init_plt_section].sh_size 134*ed981856SPaul Mackerras = get_plt_size(hdr, sechdrs, secstrings, 1); 135*ed981856SPaul Mackerras return 0; 136*ed981856SPaul Mackerras } 137*ed981856SPaul Mackerras 138*ed981856SPaul Mackerras int apply_relocate(Elf32_Shdr *sechdrs, 139*ed981856SPaul Mackerras const char *strtab, 140*ed981856SPaul Mackerras unsigned int symindex, 141*ed981856SPaul Mackerras unsigned int relsec, 142*ed981856SPaul Mackerras struct module *module) 143*ed981856SPaul Mackerras { 144*ed981856SPaul Mackerras printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", 145*ed981856SPaul Mackerras module->name); 146*ed981856SPaul Mackerras return -ENOEXEC; 147*ed981856SPaul Mackerras } 148*ed981856SPaul Mackerras 149*ed981856SPaul Mackerras static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) 150*ed981856SPaul Mackerras { 151*ed981856SPaul Mackerras if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) 152*ed981856SPaul Mackerras && entry->jump[1] == 0x396b0000 + (val & 0xffff)) 153*ed981856SPaul Mackerras return 1; 154*ed981856SPaul Mackerras return 0; 155*ed981856SPaul Mackerras } 156*ed981856SPaul Mackerras 157*ed981856SPaul Mackerras /* Set up a trampoline in the PLT to bounce us to the distant function */ 158*ed981856SPaul Mackerras static uint32_t do_plt_call(void *location, 159*ed981856SPaul Mackerras Elf32_Addr val, 160*ed981856SPaul Mackerras Elf32_Shdr *sechdrs, 161*ed981856SPaul Mackerras struct module *mod) 162*ed981856SPaul Mackerras { 163*ed981856SPaul Mackerras struct ppc_plt_entry *entry; 164*ed981856SPaul Mackerras 165*ed981856SPaul Mackerras DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); 166*ed981856SPaul Mackerras /* Init, or core PLT? */ 167*ed981856SPaul Mackerras if (location >= mod->module_core 168*ed981856SPaul Mackerras && location < mod->module_core + mod->core_size) 169*ed981856SPaul Mackerras entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; 170*ed981856SPaul Mackerras else 171*ed981856SPaul Mackerras entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; 172*ed981856SPaul Mackerras 173*ed981856SPaul Mackerras /* Find this entry, or if that fails, the next avail. entry */ 174*ed981856SPaul Mackerras while (entry->jump[0]) { 175*ed981856SPaul Mackerras if (entry_matches(entry, val)) return (uint32_t)entry; 176*ed981856SPaul Mackerras entry++; 177*ed981856SPaul Mackerras } 178*ed981856SPaul Mackerras 179*ed981856SPaul Mackerras /* Stolen from Paul Mackerras as well... */ 180*ed981856SPaul Mackerras entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ 181*ed981856SPaul Mackerras entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ 182*ed981856SPaul Mackerras entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ 183*ed981856SPaul Mackerras entry->jump[3] = 0x4e800420; /* bctr */ 184*ed981856SPaul Mackerras 185*ed981856SPaul Mackerras DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); 186*ed981856SPaul Mackerras return (uint32_t)entry; 187*ed981856SPaul Mackerras } 188*ed981856SPaul Mackerras 189*ed981856SPaul Mackerras int apply_relocate_add(Elf32_Shdr *sechdrs, 190*ed981856SPaul Mackerras const char *strtab, 191*ed981856SPaul Mackerras unsigned int symindex, 192*ed981856SPaul Mackerras unsigned int relsec, 193*ed981856SPaul Mackerras struct module *module) 194*ed981856SPaul Mackerras { 195*ed981856SPaul Mackerras unsigned int i; 196*ed981856SPaul Mackerras Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 197*ed981856SPaul Mackerras Elf32_Sym *sym; 198*ed981856SPaul Mackerras uint32_t *location; 199*ed981856SPaul Mackerras uint32_t value; 200*ed981856SPaul Mackerras 201*ed981856SPaul Mackerras DEBUGP("Applying ADD relocate section %u to %u\n", relsec, 202*ed981856SPaul Mackerras sechdrs[relsec].sh_info); 203*ed981856SPaul Mackerras for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 204*ed981856SPaul Mackerras /* This is where to make the change */ 205*ed981856SPaul Mackerras location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 206*ed981856SPaul Mackerras + rela[i].r_offset; 207*ed981856SPaul Mackerras /* This is the symbol it is referring to. Note that all 208*ed981856SPaul Mackerras undefined symbols have been resolved. */ 209*ed981856SPaul Mackerras sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 210*ed981856SPaul Mackerras + ELF32_R_SYM(rela[i].r_info); 211*ed981856SPaul Mackerras /* `Everything is relative'. */ 212*ed981856SPaul Mackerras value = sym->st_value + rela[i].r_addend; 213*ed981856SPaul Mackerras 214*ed981856SPaul Mackerras switch (ELF32_R_TYPE(rela[i].r_info)) { 215*ed981856SPaul Mackerras case R_PPC_ADDR32: 216*ed981856SPaul Mackerras /* Simply set it */ 217*ed981856SPaul Mackerras *(uint32_t *)location = value; 218*ed981856SPaul Mackerras break; 219*ed981856SPaul Mackerras 220*ed981856SPaul Mackerras case R_PPC_ADDR16_LO: 221*ed981856SPaul Mackerras /* Low half of the symbol */ 222*ed981856SPaul Mackerras *(uint16_t *)location = value; 223*ed981856SPaul Mackerras break; 224*ed981856SPaul Mackerras 225*ed981856SPaul Mackerras case R_PPC_ADDR16_HA: 226*ed981856SPaul Mackerras /* Sign-adjusted lower 16 bits: PPC ELF ABI says: 227*ed981856SPaul Mackerras (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. 228*ed981856SPaul Mackerras This is the same, only sane. 229*ed981856SPaul Mackerras */ 230*ed981856SPaul Mackerras *(uint16_t *)location = (value + 0x8000) >> 16; 231*ed981856SPaul Mackerras break; 232*ed981856SPaul Mackerras 233*ed981856SPaul Mackerras case R_PPC_REL24: 234*ed981856SPaul Mackerras if ((int)(value - (uint32_t)location) < -0x02000000 235*ed981856SPaul Mackerras || (int)(value - (uint32_t)location) >= 0x02000000) 236*ed981856SPaul Mackerras value = do_plt_call(location, value, 237*ed981856SPaul Mackerras sechdrs, module); 238*ed981856SPaul Mackerras 239*ed981856SPaul Mackerras /* Only replace bits 2 through 26 */ 240*ed981856SPaul Mackerras DEBUGP("REL24 value = %08X. location = %08X\n", 241*ed981856SPaul Mackerras value, (uint32_t)location); 242*ed981856SPaul Mackerras DEBUGP("Location before: %08X.\n", 243*ed981856SPaul Mackerras *(uint32_t *)location); 244*ed981856SPaul Mackerras *(uint32_t *)location 245*ed981856SPaul Mackerras = (*(uint32_t *)location & ~0x03fffffc) 246*ed981856SPaul Mackerras | ((value - (uint32_t)location) 247*ed981856SPaul Mackerras & 0x03fffffc); 248*ed981856SPaul Mackerras DEBUGP("Location after: %08X.\n", 249*ed981856SPaul Mackerras *(uint32_t *)location); 250*ed981856SPaul Mackerras DEBUGP("ie. jump to %08X+%08X = %08X\n", 251*ed981856SPaul Mackerras *(uint32_t *)location & 0x03fffffc, 252*ed981856SPaul Mackerras (uint32_t)location, 253*ed981856SPaul Mackerras (*(uint32_t *)location & 0x03fffffc) 254*ed981856SPaul Mackerras + (uint32_t)location); 255*ed981856SPaul Mackerras break; 256*ed981856SPaul Mackerras 257*ed981856SPaul Mackerras case R_PPC_REL32: 258*ed981856SPaul Mackerras /* 32-bit relative jump. */ 259*ed981856SPaul Mackerras *(uint32_t *)location = value - (uint32_t)location; 260*ed981856SPaul Mackerras break; 261*ed981856SPaul Mackerras 262*ed981856SPaul Mackerras default: 263*ed981856SPaul Mackerras printk("%s: unknown ADD relocation: %u\n", 264*ed981856SPaul Mackerras module->name, 265*ed981856SPaul Mackerras ELF32_R_TYPE(rela[i].r_info)); 266*ed981856SPaul Mackerras return -ENOEXEC; 267*ed981856SPaul Mackerras } 268*ed981856SPaul Mackerras } 269*ed981856SPaul Mackerras return 0; 270*ed981856SPaul Mackerras } 271*ed981856SPaul Mackerras 272*ed981856SPaul Mackerras int module_finalize(const Elf_Ehdr *hdr, 273*ed981856SPaul Mackerras const Elf_Shdr *sechdrs, 274*ed981856SPaul Mackerras struct module *me) 275*ed981856SPaul Mackerras { 276*ed981856SPaul Mackerras char *secstrings; 277*ed981856SPaul Mackerras unsigned int i; 278*ed981856SPaul Mackerras 279*ed981856SPaul Mackerras me->arch.bug_table = NULL; 280*ed981856SPaul Mackerras me->arch.num_bugs = 0; 281*ed981856SPaul Mackerras 282*ed981856SPaul Mackerras /* Find the __bug_table section, if present */ 283*ed981856SPaul Mackerras secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 284*ed981856SPaul Mackerras for (i = 1; i < hdr->e_shnum; i++) { 285*ed981856SPaul Mackerras if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) 286*ed981856SPaul Mackerras continue; 287*ed981856SPaul Mackerras me->arch.bug_table = (void *) sechdrs[i].sh_addr; 288*ed981856SPaul Mackerras me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); 289*ed981856SPaul Mackerras break; 290*ed981856SPaul Mackerras } 291*ed981856SPaul Mackerras 292*ed981856SPaul Mackerras /* 293*ed981856SPaul Mackerras * Strictly speaking this should have a spinlock to protect against 294*ed981856SPaul Mackerras * traversals, but since we only traverse on BUG()s, a spinlock 295*ed981856SPaul Mackerras * could potentially lead to deadlock and thus be counter-productive. 296*ed981856SPaul Mackerras */ 297*ed981856SPaul Mackerras list_add(&me->arch.bug_list, &module_bug_list); 298*ed981856SPaul Mackerras 299*ed981856SPaul Mackerras return 0; 300*ed981856SPaul Mackerras } 301*ed981856SPaul Mackerras 302*ed981856SPaul Mackerras void module_arch_cleanup(struct module *mod) 303*ed981856SPaul Mackerras { 304*ed981856SPaul Mackerras list_del(&mod->arch.bug_list); 305*ed981856SPaul Mackerras } 306*ed981856SPaul Mackerras 307*ed981856SPaul Mackerras struct bug_entry *module_find_bug(unsigned long bugaddr) 308*ed981856SPaul Mackerras { 309*ed981856SPaul Mackerras struct mod_arch_specific *mod; 310*ed981856SPaul Mackerras unsigned int i; 311*ed981856SPaul Mackerras struct bug_entry *bug; 312*ed981856SPaul Mackerras 313*ed981856SPaul Mackerras list_for_each_entry(mod, &module_bug_list, bug_list) { 314*ed981856SPaul Mackerras bug = mod->bug_table; 315*ed981856SPaul Mackerras for (i = 0; i < mod->num_bugs; ++i, ++bug) 316*ed981856SPaul Mackerras if (bugaddr == bug->bug_addr) 317*ed981856SPaul Mackerras return bug; 318*ed981856SPaul Mackerras } 319*ed981856SPaul Mackerras return NULL; 320*ed981856SPaul Mackerras } 321