1 /* 2 * arch/s390/kernel/module.c - Kernel module help for s390. 3 * 4 * S390 version 5 * Copyright (C) 2002, 2003 IBM Deutschland Entwicklung GmbH, 6 * IBM Corporation 7 * Author(s): Arnd Bergmann (arndb@de.ibm.com) 8 * Martin Schwidefsky (schwidefsky@de.ibm.com) 9 * 10 * based on i386 version 11 * Copyright (C) 2001 Rusty Russell. 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 #include <linux/module.h> 28 #include <linux/elf.h> 29 #include <linux/vmalloc.h> 30 #include <linux/fs.h> 31 #include <linux/string.h> 32 #include <linux/kernel.h> 33 #include <linux/moduleloader.h> 34 #include <linux/bug.h> 35 36 #if 0 37 #define DEBUGP printk 38 #else 39 #define DEBUGP(fmt , ...) 40 #endif 41 42 #ifndef CONFIG_64BIT 43 #define PLT_ENTRY_SIZE 12 44 #else /* CONFIG_64BIT */ 45 #define PLT_ENTRY_SIZE 20 46 #endif /* CONFIG_64BIT */ 47 48 /* Free memory returned from module_alloc */ 49 void module_free(struct module *mod, void *module_region) 50 { 51 if (mod) { 52 vfree(mod->arch.syminfo); 53 mod->arch.syminfo = NULL; 54 } 55 vfree(module_region); 56 } 57 58 static void 59 check_rela(Elf_Rela *rela, struct module *me) 60 { 61 struct mod_arch_syminfo *info; 62 63 info = me->arch.syminfo + ELF_R_SYM (rela->r_info); 64 switch (ELF_R_TYPE (rela->r_info)) { 65 case R_390_GOT12: /* 12 bit GOT offset. */ 66 case R_390_GOT16: /* 16 bit GOT offset. */ 67 case R_390_GOT20: /* 20 bit GOT offset. */ 68 case R_390_GOT32: /* 32 bit GOT offset. */ 69 case R_390_GOT64: /* 64 bit GOT offset. */ 70 case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */ 71 case R_390_GOTPLT12: /* 12 bit offset to jump slot. */ 72 case R_390_GOTPLT16: /* 16 bit offset to jump slot. */ 73 case R_390_GOTPLT20: /* 20 bit offset to jump slot. */ 74 case R_390_GOTPLT32: /* 32 bit offset to jump slot. */ 75 case R_390_GOTPLT64: /* 64 bit offset to jump slot. */ 76 case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */ 77 if (info->got_offset == -1UL) { 78 info->got_offset = me->arch.got_size; 79 me->arch.got_size += sizeof(void*); 80 } 81 break; 82 case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */ 83 case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */ 84 case R_390_PLT32: /* 32 bit PC relative PLT address. */ 85 case R_390_PLT64: /* 64 bit PC relative PLT address. */ 86 case R_390_PLTOFF16: /* 16 bit offset from GOT to PLT. */ 87 case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */ 88 case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */ 89 if (info->plt_offset == -1UL) { 90 info->plt_offset = me->arch.plt_size; 91 me->arch.plt_size += PLT_ENTRY_SIZE; 92 } 93 break; 94 case R_390_COPY: 95 case R_390_GLOB_DAT: 96 case R_390_JMP_SLOT: 97 case R_390_RELATIVE: 98 /* Only needed if we want to support loading of 99 modules linked with -shared. */ 100 break; 101 } 102 } 103 104 /* 105 * Account for GOT and PLT relocations. We can't add sections for 106 * got and plt but we can increase the core module size. 107 */ 108 int 109 module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, 110 char *secstrings, struct module *me) 111 { 112 Elf_Shdr *symtab; 113 Elf_Sym *symbols; 114 Elf_Rela *rela; 115 char *strings; 116 int nrela, i, j; 117 118 /* Find symbol table and string table. */ 119 symtab = NULL; 120 for (i = 0; i < hdr->e_shnum; i++) 121 switch (sechdrs[i].sh_type) { 122 case SHT_SYMTAB: 123 symtab = sechdrs + i; 124 break; 125 } 126 if (!symtab) { 127 printk(KERN_ERR "module %s: no symbol table\n", me->name); 128 return -ENOEXEC; 129 } 130 131 /* Allocate one syminfo structure per symbol. */ 132 me->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym); 133 me->arch.syminfo = vmalloc(me->arch.nsyms * 134 sizeof(struct mod_arch_syminfo)); 135 if (!me->arch.syminfo) 136 return -ENOMEM; 137 symbols = (void *) hdr + symtab->sh_offset; 138 strings = (void *) hdr + sechdrs[symtab->sh_link].sh_offset; 139 for (i = 0; i < me->arch.nsyms; i++) { 140 if (symbols[i].st_shndx == SHN_UNDEF && 141 strcmp(strings + symbols[i].st_name, 142 "_GLOBAL_OFFSET_TABLE_") == 0) 143 /* "Define" it as absolute. */ 144 symbols[i].st_shndx = SHN_ABS; 145 me->arch.syminfo[i].got_offset = -1UL; 146 me->arch.syminfo[i].plt_offset = -1UL; 147 me->arch.syminfo[i].got_initialized = 0; 148 me->arch.syminfo[i].plt_initialized = 0; 149 } 150 151 /* Search for got/plt relocations. */ 152 me->arch.got_size = me->arch.plt_size = 0; 153 for (i = 0; i < hdr->e_shnum; i++) { 154 if (sechdrs[i].sh_type != SHT_RELA) 155 continue; 156 nrela = sechdrs[i].sh_size / sizeof(Elf_Rela); 157 rela = (void *) hdr + sechdrs[i].sh_offset; 158 for (j = 0; j < nrela; j++) 159 check_rela(rela + j, me); 160 } 161 162 /* Increase core size by size of got & plt and set start 163 offsets for got and plt. */ 164 me->core_size = ALIGN(me->core_size, 4); 165 me->arch.got_offset = me->core_size; 166 me->core_size += me->arch.got_size; 167 me->arch.plt_offset = me->core_size; 168 me->core_size += me->arch.plt_size; 169 return 0; 170 } 171 172 static int 173 apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, 174 struct module *me) 175 { 176 struct mod_arch_syminfo *info; 177 Elf_Addr loc, val; 178 int r_type, r_sym; 179 180 /* This is where to make the change */ 181 loc = base + rela->r_offset; 182 /* This is the symbol it is referring to. Note that all 183 undefined symbols have been resolved. */ 184 r_sym = ELF_R_SYM(rela->r_info); 185 r_type = ELF_R_TYPE(rela->r_info); 186 info = me->arch.syminfo + r_sym; 187 val = symtab[r_sym].st_value; 188 189 switch (r_type) { 190 case R_390_8: /* Direct 8 bit. */ 191 case R_390_12: /* Direct 12 bit. */ 192 case R_390_16: /* Direct 16 bit. */ 193 case R_390_20: /* Direct 20 bit. */ 194 case R_390_32: /* Direct 32 bit. */ 195 case R_390_64: /* Direct 64 bit. */ 196 val += rela->r_addend; 197 if (r_type == R_390_8) 198 *(unsigned char *) loc = val; 199 else if (r_type == R_390_12) 200 *(unsigned short *) loc = (val & 0xfff) | 201 (*(unsigned short *) loc & 0xf000); 202 else if (r_type == R_390_16) 203 *(unsigned short *) loc = val; 204 else if (r_type == R_390_20) 205 *(unsigned int *) loc = 206 (*(unsigned int *) loc & 0xf00000ff) | 207 (val & 0xfff) << 16 | (val & 0xff000) >> 4; 208 else if (r_type == R_390_32) 209 *(unsigned int *) loc = val; 210 else if (r_type == R_390_64) 211 *(unsigned long *) loc = val; 212 break; 213 case R_390_PC16: /* PC relative 16 bit. */ 214 case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */ 215 case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */ 216 case R_390_PC32: /* PC relative 32 bit. */ 217 case R_390_PC64: /* PC relative 64 bit. */ 218 val += rela->r_addend - loc; 219 if (r_type == R_390_PC16) 220 *(unsigned short *) loc = val; 221 else if (r_type == R_390_PC16DBL) 222 *(unsigned short *) loc = val >> 1; 223 else if (r_type == R_390_PC32DBL) 224 *(unsigned int *) loc = val >> 1; 225 else if (r_type == R_390_PC32) 226 *(unsigned int *) loc = val; 227 else if (r_type == R_390_PC64) 228 *(unsigned long *) loc = val; 229 break; 230 case R_390_GOT12: /* 12 bit GOT offset. */ 231 case R_390_GOT16: /* 16 bit GOT offset. */ 232 case R_390_GOT20: /* 20 bit GOT offset. */ 233 case R_390_GOT32: /* 32 bit GOT offset. */ 234 case R_390_GOT64: /* 64 bit GOT offset. */ 235 case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */ 236 case R_390_GOTPLT12: /* 12 bit offset to jump slot. */ 237 case R_390_GOTPLT20: /* 20 bit offset to jump slot. */ 238 case R_390_GOTPLT16: /* 16 bit offset to jump slot. */ 239 case R_390_GOTPLT32: /* 32 bit offset to jump slot. */ 240 case R_390_GOTPLT64: /* 64 bit offset to jump slot. */ 241 case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */ 242 if (info->got_initialized == 0) { 243 Elf_Addr *gotent; 244 245 gotent = me->module_core + me->arch.got_offset + 246 info->got_offset; 247 *gotent = val; 248 info->got_initialized = 1; 249 } 250 val = info->got_offset + rela->r_addend; 251 if (r_type == R_390_GOT12 || 252 r_type == R_390_GOTPLT12) 253 *(unsigned short *) loc = (val & 0xfff) | 254 (*(unsigned short *) loc & 0xf000); 255 else if (r_type == R_390_GOT16 || 256 r_type == R_390_GOTPLT16) 257 *(unsigned short *) loc = val; 258 else if (r_type == R_390_GOT20 || 259 r_type == R_390_GOTPLT20) 260 *(unsigned int *) loc = 261 (*(unsigned int *) loc & 0xf00000ff) | 262 (val & 0xfff) << 16 | (val & 0xff000) >> 4; 263 else if (r_type == R_390_GOT32 || 264 r_type == R_390_GOTPLT32) 265 *(unsigned int *) loc = val; 266 else if (r_type == R_390_GOTENT || 267 r_type == R_390_GOTPLTENT) 268 *(unsigned int *) loc = 269 (val + (Elf_Addr) me->module_core - loc) >> 1; 270 else if (r_type == R_390_GOT64 || 271 r_type == R_390_GOTPLT64) 272 *(unsigned long *) loc = val; 273 break; 274 case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */ 275 case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */ 276 case R_390_PLT32: /* 32 bit PC relative PLT address. */ 277 case R_390_PLT64: /* 64 bit PC relative PLT address. */ 278 case R_390_PLTOFF16: /* 16 bit offset from GOT to PLT. */ 279 case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */ 280 case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */ 281 if (info->plt_initialized == 0) { 282 unsigned int *ip; 283 ip = me->module_core + me->arch.plt_offset + 284 info->plt_offset; 285 #ifndef CONFIG_64BIT 286 ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */ 287 ip[1] = 0x100607f1; 288 ip[2] = val; 289 #else /* CONFIG_64BIT */ 290 ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */ 291 ip[1] = 0x100a0004; 292 ip[2] = 0x07f10000; 293 ip[3] = (unsigned int) (val >> 32); 294 ip[4] = (unsigned int) val; 295 #endif /* CONFIG_64BIT */ 296 info->plt_initialized = 1; 297 } 298 if (r_type == R_390_PLTOFF16 || 299 r_type == R_390_PLTOFF32 || 300 r_type == R_390_PLTOFF64) 301 val = me->arch.plt_offset - me->arch.got_offset + 302 info->plt_offset + rela->r_addend; 303 else { 304 if (!((r_type == R_390_PLT16DBL && 305 val - loc + 0xffffUL < 0x1ffffeUL) || 306 (r_type == R_390_PLT32DBL && 307 val - loc + 0xffffffffULL < 0x1fffffffeULL))) 308 val = (Elf_Addr) me->module_core + 309 me->arch.plt_offset + 310 info->plt_offset; 311 val += rela->r_addend - loc; 312 } 313 if (r_type == R_390_PLT16DBL) 314 *(unsigned short *) loc = val >> 1; 315 else if (r_type == R_390_PLTOFF16) 316 *(unsigned short *) loc = val; 317 else if (r_type == R_390_PLT32DBL) 318 *(unsigned int *) loc = val >> 1; 319 else if (r_type == R_390_PLT32 || 320 r_type == R_390_PLTOFF32) 321 *(unsigned int *) loc = val; 322 else if (r_type == R_390_PLT64 || 323 r_type == R_390_PLTOFF64) 324 *(unsigned long *) loc = val; 325 break; 326 case R_390_GOTOFF16: /* 16 bit offset to GOT. */ 327 case R_390_GOTOFF32: /* 32 bit offset to GOT. */ 328 case R_390_GOTOFF64: /* 64 bit offset to GOT. */ 329 val = val + rela->r_addend - 330 ((Elf_Addr) me->module_core + me->arch.got_offset); 331 if (r_type == R_390_GOTOFF16) 332 *(unsigned short *) loc = val; 333 else if (r_type == R_390_GOTOFF32) 334 *(unsigned int *) loc = val; 335 else if (r_type == R_390_GOTOFF64) 336 *(unsigned long *) loc = val; 337 break; 338 case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */ 339 case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */ 340 val = (Elf_Addr) me->module_core + me->arch.got_offset + 341 rela->r_addend - loc; 342 if (r_type == R_390_GOTPC) 343 *(unsigned int *) loc = val; 344 else if (r_type == R_390_GOTPCDBL) 345 *(unsigned int *) loc = val >> 1; 346 break; 347 case R_390_COPY: 348 case R_390_GLOB_DAT: /* Create GOT entry. */ 349 case R_390_JMP_SLOT: /* Create PLT entry. */ 350 case R_390_RELATIVE: /* Adjust by program base. */ 351 /* Only needed if we want to support loading of 352 modules linked with -shared. */ 353 break; 354 default: 355 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 356 me->name, r_type); 357 return -ENOEXEC; 358 } 359 return 0; 360 } 361 362 int 363 apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, 364 unsigned int symindex, unsigned int relsec, 365 struct module *me) 366 { 367 Elf_Addr base; 368 Elf_Sym *symtab; 369 Elf_Rela *rela; 370 unsigned long i, n; 371 int rc; 372 373 DEBUGP("Applying relocate section %u to %u\n", 374 relsec, sechdrs[relsec].sh_info); 375 base = sechdrs[sechdrs[relsec].sh_info].sh_addr; 376 symtab = (Elf_Sym *) sechdrs[symindex].sh_addr; 377 rela = (Elf_Rela *) sechdrs[relsec].sh_addr; 378 n = sechdrs[relsec].sh_size / sizeof(Elf_Rela); 379 380 for (i = 0; i < n; i++, rela++) { 381 rc = apply_rela(rela, base, symtab, me); 382 if (rc) 383 return rc; 384 } 385 return 0; 386 } 387 388 int module_finalize(const Elf_Ehdr *hdr, 389 const Elf_Shdr *sechdrs, 390 struct module *me) 391 { 392 vfree(me->arch.syminfo); 393 me->arch.syminfo = NULL; 394 return 0; 395 } 396