1 /* Kernel dynamically loadable module help for PARISC. 2 * 3 * The best reference for this stuff is probably the Processor- 4 * Specific ELF Supplement for PA-RISC: 5 * http://ftp.parisc-linux.org/docs/arch/elf-pa-hp.pdf 6 * 7 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 8 * Copyright (C) 2003 Randolph Chung <tausq at debian . org> 9 * 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * 25 * 26 * Notes: 27 * - SEGREL32 handling 28 * We are not doing SEGREL32 handling correctly. According to the ABI, we 29 * should do a value offset, like this: 30 * if (is_init(me, (void *)val)) 31 * val -= (uint32_t)me->module_init; 32 * else 33 * val -= (uint32_t)me->module_core; 34 * However, SEGREL32 is used only for PARISC unwind entries, and we want 35 * those entries to have an absolute address, and not just an offset. 36 * 37 * The unwind table mechanism has the ability to specify an offset for 38 * the unwind table; however, because we split off the init functions into 39 * a different piece of memory, it is not possible to do this using a 40 * single offset. Instead, we use the above hack for now. 41 */ 42 43 #include <linux/moduleloader.h> 44 #include <linux/elf.h> 45 #include <linux/vmalloc.h> 46 #include <linux/fs.h> 47 #include <linux/string.h> 48 #include <linux/kernel.h> 49 50 #include <asm/unwind.h> 51 52 #if 0 53 #define DEBUGP printk 54 #else 55 #define DEBUGP(fmt...) 56 #endif 57 58 #define CHECK_RELOC(val, bits) \ 59 if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ 60 ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \ 61 printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ 62 me->name, strtab + sym->st_name, (unsigned long)val, bits); \ 63 return -ENOEXEC; \ 64 } 65 66 /* Maximum number of GOT entries. We use a long displacement ldd from 67 * the bottom of the table, which has a maximum signed displacement of 68 * 0x3fff; however, since we're only going forward, this becomes 69 * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have 70 * at most 1023 entries */ 71 #define MAX_GOTS 1023 72 73 /* three functions to determine where in the module core 74 * or init pieces the location is */ 75 static inline int is_init(struct module *me, void *loc) 76 { 77 return (loc >= me->module_init && 78 loc <= (me->module_init + me->init_size)); 79 } 80 81 static inline int is_core(struct module *me, void *loc) 82 { 83 return (loc >= me->module_core && 84 loc <= (me->module_core + me->core_size)); 85 } 86 87 static inline int is_local(struct module *me, void *loc) 88 { 89 return is_init(me, loc) || is_core(me, loc); 90 } 91 92 93 #ifndef __LP64__ 94 struct got_entry { 95 Elf32_Addr addr; 96 }; 97 98 #define Elf_Fdesc Elf32_Fdesc 99 100 struct stub_entry { 101 Elf32_Word insns[2]; /* each stub entry has two insns */ 102 }; 103 #else 104 struct got_entry { 105 Elf64_Addr addr; 106 }; 107 108 #define Elf_Fdesc Elf64_Fdesc 109 110 struct stub_entry { 111 Elf64_Word insns[4]; /* each stub entry has four insns */ 112 }; 113 #endif 114 115 /* Field selection types defined by hppa */ 116 #define rnd(x) (((x)+0x1000)&~0x1fff) 117 /* fsel: full 32 bits */ 118 #define fsel(v,a) ((v)+(a)) 119 /* lsel: select left 21 bits */ 120 #define lsel(v,a) (((v)+(a))>>11) 121 /* rsel: select right 11 bits */ 122 #define rsel(v,a) (((v)+(a))&0x7ff) 123 /* lrsel with rounding of addend to nearest 8k */ 124 #define lrsel(v,a) (((v)+rnd(a))>>11) 125 /* rrsel with rounding of addend to nearest 8k */ 126 #define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a))) 127 128 #define mask(x,sz) ((x) & ~((1<<(sz))-1)) 129 130 131 /* The reassemble_* functions prepare an immediate value for 132 insertion into an opcode. pa-risc uses all sorts of weird bitfields 133 in the instruction to hold the value. */ 134 static inline int reassemble_14(int as14) 135 { 136 return (((as14 & 0x1fff) << 1) | 137 ((as14 & 0x2000) >> 13)); 138 } 139 140 static inline int reassemble_17(int as17) 141 { 142 return (((as17 & 0x10000) >> 16) | 143 ((as17 & 0x0f800) << 5) | 144 ((as17 & 0x00400) >> 8) | 145 ((as17 & 0x003ff) << 3)); 146 } 147 148 static inline int reassemble_21(int as21) 149 { 150 return (((as21 & 0x100000) >> 20) | 151 ((as21 & 0x0ffe00) >> 8) | 152 ((as21 & 0x000180) << 7) | 153 ((as21 & 0x00007c) << 14) | 154 ((as21 & 0x000003) << 12)); 155 } 156 157 static inline int reassemble_22(int as22) 158 { 159 return (((as22 & 0x200000) >> 21) | 160 ((as22 & 0x1f0000) << 5) | 161 ((as22 & 0x00f800) << 5) | 162 ((as22 & 0x000400) >> 8) | 163 ((as22 & 0x0003ff) << 3)); 164 } 165 166 void *module_alloc(unsigned long size) 167 { 168 if (size == 0) 169 return NULL; 170 return vmalloc(size); 171 } 172 173 #ifndef __LP64__ 174 static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n) 175 { 176 return 0; 177 } 178 179 static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n) 180 { 181 return 0; 182 } 183 184 static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) 185 { 186 unsigned long cnt = 0; 187 188 for (; n > 0; n--, rela++) 189 { 190 switch (ELF32_R_TYPE(rela->r_info)) { 191 case R_PARISC_PCREL17F: 192 case R_PARISC_PCREL22F: 193 cnt++; 194 } 195 } 196 197 return cnt; 198 } 199 #else 200 static inline unsigned long count_gots(const Elf_Rela *rela, unsigned long n) 201 { 202 unsigned long cnt = 0; 203 204 for (; n > 0; n--, rela++) 205 { 206 switch (ELF64_R_TYPE(rela->r_info)) { 207 case R_PARISC_LTOFF21L: 208 case R_PARISC_LTOFF14R: 209 case R_PARISC_PCREL22F: 210 cnt++; 211 } 212 } 213 214 return cnt; 215 } 216 217 static inline unsigned long count_fdescs(const Elf_Rela *rela, unsigned long n) 218 { 219 unsigned long cnt = 0; 220 221 for (; n > 0; n--, rela++) 222 { 223 switch (ELF64_R_TYPE(rela->r_info)) { 224 case R_PARISC_FPTR64: 225 cnt++; 226 } 227 } 228 229 return cnt; 230 } 231 232 static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n) 233 { 234 unsigned long cnt = 0; 235 236 for (; n > 0; n--, rela++) 237 { 238 switch (ELF64_R_TYPE(rela->r_info)) { 239 case R_PARISC_PCREL22F: 240 cnt++; 241 } 242 } 243 244 return cnt; 245 } 246 #endif 247 248 249 /* Free memory returned from module_alloc */ 250 void module_free(struct module *mod, void *module_region) 251 { 252 vfree(module_region); 253 /* FIXME: If module_region == mod->init_region, trim exception 254 table entries. */ 255 } 256 257 #define CONST 258 int module_frob_arch_sections(CONST Elf_Ehdr *hdr, 259 CONST Elf_Shdr *sechdrs, 260 CONST char *secstrings, 261 struct module *me) 262 { 263 unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0; 264 unsigned int i; 265 266 for (i = 1; i < hdr->e_shnum; i++) { 267 const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; 268 unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); 269 270 if (strncmp(secstrings + sechdrs[i].sh_name, 271 ".PARISC.unwind", 14) == 0) 272 me->arch.unwind_section = i; 273 274 if (sechdrs[i].sh_type != SHT_RELA) 275 continue; 276 277 /* some of these are not relevant for 32-bit/64-bit 278 * we leave them here to make the code common. the 279 * compiler will do its thing and optimize out the 280 * stuff we don't need 281 */ 282 gots += count_gots(rels, nrels); 283 fdescs += count_fdescs(rels, nrels); 284 if(strncmp(secstrings + sechdrs[i].sh_name, 285 ".rela.init", 10) == 0) 286 init_stubs += count_stubs(rels, nrels); 287 else 288 stubs += count_stubs(rels, nrels); 289 } 290 291 /* align things a bit */ 292 me->core_size = ALIGN(me->core_size, 16); 293 me->arch.got_offset = me->core_size; 294 me->core_size += gots * sizeof(struct got_entry); 295 296 me->core_size = ALIGN(me->core_size, 16); 297 me->arch.fdesc_offset = me->core_size; 298 me->core_size += fdescs * sizeof(Elf_Fdesc); 299 300 me->core_size = ALIGN(me->core_size, 16); 301 me->arch.stub_offset = me->core_size; 302 me->core_size += stubs * sizeof(struct stub_entry); 303 304 me->init_size = ALIGN(me->init_size, 16); 305 me->arch.init_stub_offset = me->init_size; 306 me->init_size += init_stubs * sizeof(struct stub_entry); 307 308 me->arch.got_max = gots; 309 me->arch.fdesc_max = fdescs; 310 me->arch.stub_max = stubs; 311 me->arch.init_stub_max = init_stubs; 312 313 return 0; 314 } 315 316 #ifdef __LP64__ 317 static Elf64_Word get_got(struct module *me, unsigned long value, long addend) 318 { 319 unsigned int i; 320 struct got_entry *got; 321 322 value += addend; 323 324 BUG_ON(value == 0); 325 326 got = me->module_core + me->arch.got_offset; 327 for (i = 0; got[i].addr; i++) 328 if (got[i].addr == value) 329 goto out; 330 331 BUG_ON(++me->arch.got_count > me->arch.got_max); 332 333 got[i].addr = value; 334 out: 335 DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry), 336 value); 337 return i * sizeof(struct got_entry); 338 } 339 #endif /* __LP64__ */ 340 341 #ifdef __LP64__ 342 static Elf_Addr get_fdesc(struct module *me, unsigned long value) 343 { 344 Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset; 345 346 if (!value) { 347 printk(KERN_ERR "%s: zero OPD requested!\n", me->name); 348 return 0; 349 } 350 351 /* Look for existing fdesc entry. */ 352 while (fdesc->addr) { 353 if (fdesc->addr == value) 354 return (Elf_Addr)fdesc; 355 fdesc++; 356 } 357 358 BUG_ON(++me->arch.fdesc_count > me->arch.fdesc_max); 359 360 /* Create new one */ 361 fdesc->addr = value; 362 fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset; 363 return (Elf_Addr)fdesc; 364 } 365 #endif /* __LP64__ */ 366 367 static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, 368 int millicode, int init_section) 369 { 370 unsigned long i; 371 struct stub_entry *stub; 372 373 if(init_section) { 374 i = me->arch.init_stub_count++; 375 BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); 376 stub = me->module_init + me->arch.init_stub_offset + 377 i * sizeof(struct stub_entry); 378 } else { 379 i = me->arch.stub_count++; 380 BUG_ON(me->arch.stub_count > me->arch.stub_max); 381 stub = me->module_core + me->arch.stub_offset + 382 i * sizeof(struct stub_entry); 383 } 384 385 #ifndef __LP64__ 386 /* for 32-bit the stub looks like this: 387 * ldil L'XXX,%r1 388 * be,n R'XXX(%sr4,%r1) 389 */ 390 //value = *(unsigned long *)((value + addend) & ~3); /* why? */ 391 392 stub->insns[0] = 0x20200000; /* ldil L'XXX,%r1 */ 393 stub->insns[1] = 0xe0202002; /* be,n R'XXX(%sr4,%r1) */ 394 395 stub->insns[0] |= reassemble_21(lrsel(value, addend)); 396 stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4); 397 398 #else 399 /* for 64-bit we have two kinds of stubs: 400 * for normal function calls: 401 * ldd 0(%dp),%dp 402 * ldd 10(%dp), %r1 403 * bve (%r1) 404 * ldd 18(%dp), %dp 405 * 406 * for millicode: 407 * ldil 0, %r1 408 * ldo 0(%r1), %r1 409 * ldd 10(%r1), %r1 410 * bve,n (%r1) 411 */ 412 if (!millicode) 413 { 414 stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ 415 stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ 416 stub->insns[2] = 0xe820d000; /* bve (%r1) */ 417 stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ 418 419 stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); 420 } 421 else 422 { 423 stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ 424 stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ 425 stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */ 426 stub->insns[3] = 0xe820d002; /* bve,n (%r1) */ 427 428 stub->insns[0] |= reassemble_21(lrsel(value, addend)); 429 stub->insns[1] |= reassemble_14(rrsel(value, addend)); 430 } 431 #endif 432 433 return (Elf_Addr)stub; 434 } 435 436 int apply_relocate(Elf_Shdr *sechdrs, 437 const char *strtab, 438 unsigned int symindex, 439 unsigned int relsec, 440 struct module *me) 441 { 442 /* parisc should not need this ... */ 443 printk(KERN_ERR "module %s: RELOCATION unsupported\n", 444 me->name); 445 return -ENOEXEC; 446 } 447 448 #ifndef __LP64__ 449 int apply_relocate_add(Elf_Shdr *sechdrs, 450 const char *strtab, 451 unsigned int symindex, 452 unsigned int relsec, 453 struct module *me) 454 { 455 int i; 456 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; 457 Elf32_Sym *sym; 458 Elf32_Word *loc; 459 Elf32_Addr val; 460 Elf32_Sword addend; 461 Elf32_Addr dot; 462 //unsigned long dp = (unsigned long)$global$; 463 register unsigned long dp asm ("r27"); 464 465 DEBUGP("Applying relocate section %u to %u\n", relsec, 466 sechdrs[relsec].sh_info); 467 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 468 /* This is where to make the change */ 469 loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 470 + rel[i].r_offset; 471 /* This is the symbol it is referring to */ 472 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 473 + ELF32_R_SYM(rel[i].r_info); 474 if (!sym->st_value) { 475 printk(KERN_WARNING "%s: Unknown symbol %s\n", 476 me->name, strtab + sym->st_name); 477 return -ENOENT; 478 } 479 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; 480 dot = (Elf32_Addr)loc & ~0x03; 481 482 val = sym->st_value; 483 addend = rel[i].r_addend; 484 485 #if 0 486 #define r(t) ELF32_R_TYPE(rel[i].r_info)==t ? #t : 487 DEBUGP("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n", 488 strtab + sym->st_name, 489 (uint32_t)loc, val, addend, 490 r(R_PARISC_PLABEL32) 491 r(R_PARISC_DIR32) 492 r(R_PARISC_DIR21L) 493 r(R_PARISC_DIR14R) 494 r(R_PARISC_SEGREL32) 495 r(R_PARISC_DPREL21L) 496 r(R_PARISC_DPREL14R) 497 r(R_PARISC_PCREL17F) 498 r(R_PARISC_PCREL22F) 499 "UNKNOWN"); 500 #undef r 501 #endif 502 503 switch (ELF32_R_TYPE(rel[i].r_info)) { 504 case R_PARISC_PLABEL32: 505 /* 32-bit function address */ 506 /* no function descriptors... */ 507 *loc = fsel(val, addend); 508 break; 509 case R_PARISC_DIR32: 510 /* direct 32-bit ref */ 511 *loc = fsel(val, addend); 512 break; 513 case R_PARISC_DIR21L: 514 /* left 21 bits of effective address */ 515 val = lrsel(val, addend); 516 *loc = mask(*loc, 21) | reassemble_21(val); 517 break; 518 case R_PARISC_DIR14R: 519 /* right 14 bits of effective address */ 520 val = rrsel(val, addend); 521 *loc = mask(*loc, 14) | reassemble_14(val); 522 break; 523 case R_PARISC_SEGREL32: 524 /* 32-bit segment relative address */ 525 /* See note about special handling of SEGREL32 at 526 * the beginning of this file. 527 */ 528 *loc = fsel(val, addend); 529 break; 530 case R_PARISC_DPREL21L: 531 /* left 21 bit of relative address */ 532 val = lrsel(val - dp, addend); 533 *loc = mask(*loc, 21) | reassemble_21(val); 534 break; 535 case R_PARISC_DPREL14R: 536 /* right 14 bit of relative address */ 537 val = rrsel(val - dp, addend); 538 *loc = mask(*loc, 14) | reassemble_14(val); 539 break; 540 case R_PARISC_PCREL17F: 541 /* 17-bit PC relative address */ 542 val = get_stub(me, val, addend, 0, is_init(me, loc)); 543 val = (val - dot - 8)/4; 544 CHECK_RELOC(val, 17) 545 *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); 546 break; 547 case R_PARISC_PCREL22F: 548 /* 22-bit PC relative address; only defined for pa20 */ 549 val = get_stub(me, val, addend, 0, is_init(me, loc)); 550 DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", 551 strtab + sym->st_name, (unsigned long)loc, addend, 552 val) 553 val = (val - dot - 8)/4; 554 CHECK_RELOC(val, 22); 555 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 556 break; 557 558 default: 559 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 560 me->name, ELF32_R_TYPE(rel[i].r_info)); 561 return -ENOEXEC; 562 } 563 } 564 565 return 0; 566 } 567 568 #else 569 int apply_relocate_add(Elf_Shdr *sechdrs, 570 const char *strtab, 571 unsigned int symindex, 572 unsigned int relsec, 573 struct module *me) 574 { 575 int i; 576 Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; 577 Elf64_Sym *sym; 578 Elf64_Word *loc; 579 Elf64_Xword *loc64; 580 Elf64_Addr val; 581 Elf64_Sxword addend; 582 Elf64_Addr dot; 583 584 DEBUGP("Applying relocate section %u to %u\n", relsec, 585 sechdrs[relsec].sh_info); 586 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 587 /* This is where to make the change */ 588 loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 589 + rel[i].r_offset; 590 /* This is the symbol it is referring to */ 591 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr 592 + ELF64_R_SYM(rel[i].r_info); 593 if (!sym->st_value) { 594 printk(KERN_WARNING "%s: Unknown symbol %s\n", 595 me->name, strtab + sym->st_name); 596 return -ENOENT; 597 } 598 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; 599 dot = (Elf64_Addr)loc & ~0x03; 600 loc64 = (Elf64_Xword *)loc; 601 602 val = sym->st_value; 603 addend = rel[i].r_addend; 604 605 #if 0 606 #define r(t) ELF64_R_TYPE(rel[i].r_info)==t ? #t : 607 printk("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n", 608 strtab + sym->st_name, 609 loc, val, addend, 610 r(R_PARISC_LTOFF14R) 611 r(R_PARISC_LTOFF21L) 612 r(R_PARISC_PCREL22F) 613 r(R_PARISC_DIR64) 614 r(R_PARISC_SEGREL32) 615 r(R_PARISC_FPTR64) 616 "UNKNOWN"); 617 #undef r 618 #endif 619 620 switch (ELF64_R_TYPE(rel[i].r_info)) { 621 case R_PARISC_LTOFF21L: 622 /* LT-relative; left 21 bits */ 623 val = get_got(me, val, addend); 624 DEBUGP("LTOFF21L Symbol %s loc %p val %lx\n", 625 strtab + sym->st_name, 626 loc, val); 627 val = lrsel(val, 0); 628 *loc = mask(*loc, 21) | reassemble_21(val); 629 break; 630 case R_PARISC_LTOFF14R: 631 /* L(ltoff(val+addend)) */ 632 /* LT-relative; right 14 bits */ 633 val = get_got(me, val, addend); 634 val = rrsel(val, 0); 635 DEBUGP("LTOFF14R Symbol %s loc %p val %lx\n", 636 strtab + sym->st_name, 637 loc, val); 638 *loc = mask(*loc, 14) | reassemble_14(val); 639 break; 640 case R_PARISC_PCREL22F: 641 /* PC-relative; 22 bits */ 642 DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", 643 strtab + sym->st_name, 644 loc, val); 645 /* can we reach it locally? */ 646 if(!is_local(me, (void *)val)) { 647 if (strncmp(strtab + sym->st_name, "$$", 2) 648 == 0) 649 val = get_stub(me, val, addend, 1, 650 is_init(me, loc)); 651 else 652 val = get_stub(me, val, addend, 0, 653 is_init(me, loc)); 654 } 655 DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 656 strtab + sym->st_name, loc, sym->st_value, 657 addend, val); 658 /* FIXME: local symbols work as long as the 659 * core and init pieces aren't separated too 660 * far. If this is ever broken, you will trip 661 * the check below. The way to fix it would 662 * be to generate local stubs to go between init 663 * and core */ 664 if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 || 665 (Elf64_Sxword)(val - dot - 8) < -0x800000) { 666 printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n", 667 me->name, strtab + sym->st_name); 668 return -ENOEXEC; 669 } 670 val = (val - dot - 8)/4; 671 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 672 break; 673 case R_PARISC_DIR64: 674 /* 64-bit effective address */ 675 *loc64 = val + addend; 676 break; 677 case R_PARISC_SEGREL32: 678 /* 32-bit segment relative address */ 679 /* See note about special handling of SEGREL32 at 680 * the beginning of this file. 681 */ 682 *loc = fsel(val, addend); 683 break; 684 case R_PARISC_FPTR64: 685 /* 64-bit function address */ 686 if(is_local(me, (void *)(val + addend))) { 687 *loc64 = get_fdesc(me, val+addend); 688 DEBUGP("FDESC for %s at %p points to %lx\n", 689 strtab + sym->st_name, *loc64, 690 ((Elf_Fdesc *)*loc64)->addr); 691 } else { 692 /* if the symbol is not local to this 693 * module then val+addend is a pointer 694 * to the function descriptor */ 695 DEBUGP("Non local FPTR64 Symbol %s loc %p val %lx\n", 696 strtab + sym->st_name, 697 loc, val); 698 *loc64 = val + addend; 699 } 700 break; 701 702 default: 703 printk(KERN_ERR "module %s: Unknown relocation: %Lu\n", 704 me->name, ELF64_R_TYPE(rel[i].r_info)); 705 return -ENOEXEC; 706 } 707 } 708 return 0; 709 } 710 #endif 711 712 static void 713 register_unwind_table(struct module *me, 714 const Elf_Shdr *sechdrs) 715 { 716 unsigned char *table, *end; 717 unsigned long gp; 718 719 if (!me->arch.unwind_section) 720 return; 721 722 table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; 723 end = table + sechdrs[me->arch.unwind_section].sh_size; 724 gp = (Elf_Addr)me->module_core + me->arch.got_offset; 725 726 DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", 727 me->arch.unwind_section, table, end, gp); 728 me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end); 729 } 730 731 static void 732 deregister_unwind_table(struct module *me) 733 { 734 if (me->arch.unwind) 735 unwind_table_remove(me->arch.unwind); 736 } 737 738 int module_finalize(const Elf_Ehdr *hdr, 739 const Elf_Shdr *sechdrs, 740 struct module *me) 741 { 742 int i; 743 unsigned long nsyms; 744 const char *strtab = NULL; 745 Elf_Sym *newptr, *oldptr; 746 Elf_Shdr *symhdr = NULL; 747 #ifdef DEBUG 748 Elf_Fdesc *entry; 749 u32 *addr; 750 751 entry = (Elf_Fdesc *)me->init; 752 printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry, 753 entry->gp, entry->addr); 754 addr = (u32 *)entry->addr; 755 printk("INSNS: %x %x %x %x\n", 756 addr[0], addr[1], addr[2], addr[3]); 757 printk("stubs used %ld, stubs max %ld\n" 758 "init_stubs used %ld, init stubs max %ld\n" 759 "got entries used %ld, gots max %ld\n" 760 "fdescs used %ld, fdescs max %ld\n", 761 me->arch.stub_count, me->arch.stub_max, 762 me->arch.init_stub_count, me->arch.init_stub_max, 763 me->arch.got_count, me->arch.got_max, 764 me->arch.fdesc_count, me->arch.fdesc_max); 765 #endif 766 767 register_unwind_table(me, sechdrs); 768 769 /* haven't filled in me->symtab yet, so have to find it 770 * ourselves */ 771 for (i = 1; i < hdr->e_shnum; i++) { 772 if(sechdrs[i].sh_type == SHT_SYMTAB 773 && (sechdrs[i].sh_type & SHF_ALLOC)) { 774 int strindex = sechdrs[i].sh_link; 775 /* FIXME: AWFUL HACK 776 * The cast is to drop the const from 777 * the sechdrs pointer */ 778 symhdr = (Elf_Shdr *)&sechdrs[i]; 779 strtab = (char *)sechdrs[strindex].sh_addr; 780 break; 781 } 782 } 783 784 DEBUGP("module %s: strtab %p, symhdr %p\n", 785 me->name, strtab, symhdr); 786 787 if(me->arch.got_count > MAX_GOTS) { 788 printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS); 789 return -EINVAL; 790 } 791 792 /* no symbol table */ 793 if(symhdr == NULL) 794 return 0; 795 796 oldptr = (void *)symhdr->sh_addr; 797 newptr = oldptr + 1; /* we start counting at 1 */ 798 nsyms = symhdr->sh_size / sizeof(Elf_Sym); 799 DEBUGP("OLD num_symtab %lu\n", nsyms); 800 801 for (i = 1; i < nsyms; i++) { 802 oldptr++; /* note, count starts at 1 so preincrement */ 803 if(strncmp(strtab + oldptr->st_name, 804 ".L", 2) == 0) 805 continue; 806 807 if(newptr != oldptr) 808 *newptr++ = *oldptr; 809 else 810 newptr++; 811 812 } 813 nsyms = newptr - (Elf_Sym *)symhdr->sh_addr; 814 DEBUGP("NEW num_symtab %lu\n", nsyms); 815 symhdr->sh_size = nsyms * sizeof(Elf_Sym); 816 return 0; 817 } 818 819 void module_arch_cleanup(struct module *mod) 820 { 821 deregister_unwind_table(mod); 822 } 823