parisc: fix module loading failure of large kernel modules

On 32bit (and sometimes 64bit) and with big kernel modules like xfs or
ipv6 the relocation types R_PARISC_PCREL17F and R_PARISC_PCREL22F may
fail to reach their PLT stub if we only create one big stub array for
all sections at the beginning of the core or init section.

With this patch we now instead add individual PLT stub entries
directly in front of the code sections where the stubs are actually
called. This reduces the distance between the PCREL location and the
stub entry so that the relocations can be fulfilled.

While calculating the final layout of the kernel module in memory, the
kernel module loader calls arch_mod_section_prepend() to request the
to be reserved amount of memory in front of each individual section.

Tested with 32- and 64bit kernels.

Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

authored by

Helge Deller and committed by
Rusty Russell
c298be74 088af9a6

+139 -83
+4 -2
arch/parisc/include/asm/module.h
··· 23 23 { 24 24 unsigned long got_offset, got_count, got_max; 25 25 unsigned long fdesc_offset, fdesc_count, fdesc_max; 26 - unsigned long stub_offset, stub_count, stub_max; 27 - unsigned long init_stub_offset, init_stub_count, init_stub_max; 26 + struct { 27 + unsigned long stub_offset; 28 + unsigned int stub_entries; 29 + } *section; 28 30 int unwind_section; 29 31 struct unwind_table *unwind; 30 32 };
+135 -81
arch/parisc/kernel/module.c
··· 6 6 * 7 7 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 8 8 * Copyright (C) 2003 Randolph Chung <tausq at debian . org> 9 + * Copyright (C) 2008 Helge Deller <deller@gmx.de> 9 10 * 10 11 * 11 12 * This program is free software; you can redistribute it and/or modify ··· 25 24 * 26 25 * 27 26 * Notes: 27 + * - PLT stub handling 28 + * On 32bit (and sometimes 64bit) and with big kernel modules like xfs or 29 + * ipv6 the relocation types R_PARISC_PCREL17F and R_PARISC_PCREL22F may 30 + * fail to reach their PLT stub if we only create one big stub array for 31 + * all sections at the beginning of the core or init section. 32 + * Instead we now insert individual PLT stub entries directly in front of 33 + * of the code sections where the stubs are actually called. 34 + * This reduces the distance between the PCREL location and the stub entry 35 + * so that the relocations can be fulfilled. 36 + * While calculating the final layout of the kernel module in memory, the 37 + * kernel module loader calls arch_mod_section_prepend() to request the 38 + * to be reserved amount of memory in front of each individual section. 39 + * 28 40 * - SEGREL32 handling 29 41 * We are not doing SEGREL32 handling correctly. According to the ABI, we 30 42 * should do a value offset, like this: ··· 72 58 #define DEBUGP(fmt...) 73 59 #endif 74 60 61 + #define RELOC_REACHABLE(val, bits) \ 62 + (( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ 63 + ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \ 64 + 0 : 1) 65 + 75 66 #define CHECK_RELOC(val, bits) \ 76 - if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \ 77 - ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \ 67 + if (!RELOC_REACHABLE(val, bits)) { \ 78 68 printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ 79 69 me->name, strtab + sym->st_name, (unsigned long)val, bits); \ 80 70 return -ENOEXEC; \ ··· 109 91 { 110 92 return in_init(me, loc) || in_core(me, loc); 111 93 } 112 - 113 - static inline int in_local_section(struct module *me, void *loc, void *dot) 114 - { 115 - return (in_init(me, loc) && in_init(me, dot)) || 116 - (in_core(me, loc) && in_core(me, dot)); 117 - } 118 - 119 94 120 95 #ifndef CONFIG_64BIT 121 96 struct got_entry { ··· 269 258 /* Free memory returned from module_alloc */ 270 259 void module_free(struct module *mod, void *module_region) 271 260 { 261 + kfree(mod->arch.section); 262 + mod->arch.section = NULL; 263 + 272 264 vfree(module_region); 273 265 /* FIXME: If module_region == mod->init_region, trim exception 274 266 table entries. */ 267 + } 268 + 269 + /* Additional bytes needed in front of individual sections */ 270 + unsigned int arch_mod_section_prepend(struct module *mod, 271 + unsigned int section) 272 + { 273 + /* size needed for all stubs of this section (including 274 + * one additional for correct alignment of the stubs) */ 275 + return (mod->arch.section[section].stub_entries + 1) 276 + * sizeof(struct stub_entry); 275 277 } 276 278 277 279 #define CONST ··· 293 269 CONST char *secstrings, 294 270 struct module *me) 295 271 { 296 - unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0; 272 + unsigned long gots = 0, fdescs = 0, len; 297 273 unsigned int i; 298 274 275 + len = hdr->e_shnum * sizeof(me->arch.section[0]); 276 + me->arch.section = kzalloc(len, GFP_KERNEL); 277 + if (!me->arch.section) 278 + return -ENOMEM; 279 + 299 280 for (i = 1; i < hdr->e_shnum; i++) { 300 - const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; 281 + const Elf_Rela *rels = (void *)sechdrs[i].sh_addr; 301 282 unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); 283 + unsigned int count, s; 302 284 303 285 if (strncmp(secstrings + sechdrs[i].sh_name, 304 286 ".PARISC.unwind", 14) == 0) ··· 320 290 */ 321 291 gots += count_gots(rels, nrels); 322 292 fdescs += count_fdescs(rels, nrels); 323 - if(strncmp(secstrings + sechdrs[i].sh_name, 324 - ".rela.init", 10) == 0) 325 - init_stubs += count_stubs(rels, nrels); 326 - else 327 - stubs += count_stubs(rels, nrels); 293 + 294 + /* XXX: By sorting the relocs and finding duplicate entries 295 + * we could reduce the number of necessary stubs and save 296 + * some memory. */ 297 + count = count_stubs(rels, nrels); 298 + if (!count) 299 + continue; 300 + 301 + /* so we need relocation stubs. reserve necessary memory. */ 302 + /* sh_info gives the section for which we need to add stubs. */ 303 + s = sechdrs[i].sh_info; 304 + 305 + /* each code section should only have one relocation section */ 306 + WARN_ON(me->arch.section[s].stub_entries); 307 + 308 + /* store number of stubs we need for this section */ 309 + me->arch.section[s].stub_entries += count; 328 310 } 329 311 330 312 /* align things a bit */ ··· 348 306 me->arch.fdesc_offset = me->core_size; 349 307 me->core_size += fdescs * sizeof(Elf_Fdesc); 350 308 351 - me->core_size = ALIGN(me->core_size, 16); 352 - me->arch.stub_offset = me->core_size; 353 - me->core_size += stubs * sizeof(struct stub_entry); 354 - 355 - me->init_size = ALIGN(me->init_size, 16); 356 - me->arch.init_stub_offset = me->init_size; 357 - me->init_size += init_stubs * sizeof(struct stub_entry); 358 - 359 309 me->arch.got_max = gots; 360 310 me->arch.fdesc_max = fdescs; 361 - me->arch.stub_max = stubs; 362 - me->arch.init_stub_max = init_stubs; 363 311 364 312 return 0; 365 313 } ··· 412 380 }; 413 381 414 382 static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, 415 - enum elf_stub_type stub_type, int init_section) 383 + enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec) 416 384 { 417 - unsigned long i; 418 385 struct stub_entry *stub; 419 386 420 - if(init_section) { 421 - i = me->arch.init_stub_count++; 422 - BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); 423 - stub = me->module_init + me->arch.init_stub_offset + 424 - i * sizeof(struct stub_entry); 425 - } else { 426 - i = me->arch.stub_count++; 427 - BUG_ON(me->arch.stub_count > me->arch.stub_max); 428 - stub = me->module_core + me->arch.stub_offset + 429 - i * sizeof(struct stub_entry); 387 + /* initialize stub_offset to point in front of the section */ 388 + if (!me->arch.section[targetsec].stub_offset) { 389 + loc0 -= (me->arch.section[targetsec].stub_entries + 1) * 390 + sizeof(struct stub_entry); 391 + /* get correct alignment for the stubs */ 392 + loc0 = ALIGN(loc0, sizeof(struct stub_entry)); 393 + me->arch.section[targetsec].stub_offset = loc0; 430 394 } 395 + 396 + /* get address of stub entry */ 397 + stub = (void *) me->arch.section[targetsec].stub_offset; 398 + me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry); 399 + 400 + /* do not write outside available stub area */ 401 + BUG_ON(0 == me->arch.section[targetsec].stub_entries--); 402 + 431 403 432 404 #ifndef CONFIG_64BIT 433 405 /* for 32-bit the stub looks like this: ··· 525 489 Elf32_Addr val; 526 490 Elf32_Sword addend; 527 491 Elf32_Addr dot; 492 + Elf_Addr loc0; 493 + unsigned int targetsec = sechdrs[relsec].sh_info; 528 494 //unsigned long dp = (unsigned long)$global$; 529 495 register unsigned long dp asm ("r27"); 530 496 531 497 DEBUGP("Applying relocate section %u to %u\n", relsec, 532 - sechdrs[relsec].sh_info); 498 + targetsec); 533 499 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 534 500 /* This is where to make the change */ 535 - loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 501 + loc = (void *)sechdrs[targetsec].sh_addr 536 502 + rel[i].r_offset; 503 + /* This is the start of the target section */ 504 + loc0 = sechdrs[targetsec].sh_addr; 537 505 /* This is the symbol it is referring to */ 538 506 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 539 507 + ELF32_R_SYM(rel[i].r_info); ··· 609 569 break; 610 570 case R_PARISC_PCREL17F: 611 571 /* 17-bit PC relative address */ 612 - val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); 572 + /* calculate direct call offset */ 573 + val += addend; 613 574 val = (val - dot - 8)/4; 614 - CHECK_RELOC(val, 17) 575 + if (!RELOC_REACHABLE(val, 17)) { 576 + /* direct distance too far, create 577 + * stub entry instead */ 578 + val = get_stub(me, sym->st_value, addend, 579 + ELF_STUB_DIRECT, loc0, targetsec); 580 + val = (val - dot - 8)/4; 581 + CHECK_RELOC(val, 17); 582 + } 615 583 *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); 616 584 break; 617 585 case R_PARISC_PCREL22F: 618 586 /* 22-bit PC relative address; only defined for pa20 */ 619 - val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); 620 - DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", 621 - strtab + sym->st_name, (unsigned long)loc, addend, 622 - val) 587 + /* calculate direct call offset */ 588 + val += addend; 623 589 val = (val - dot - 8)/4; 624 - CHECK_RELOC(val, 22); 590 + if (!RELOC_REACHABLE(val, 22)) { 591 + /* direct distance too far, create 592 + * stub entry instead */ 593 + val = get_stub(me, sym->st_value, addend, 594 + ELF_STUB_DIRECT, loc0, targetsec); 595 + val = (val - dot - 8)/4; 596 + CHECK_RELOC(val, 22); 597 + } 625 598 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 626 599 break; 627 600 ··· 663 610 Elf64_Addr val; 664 611 Elf64_Sxword addend; 665 612 Elf64_Addr dot; 613 + Elf_Addr loc0; 614 + unsigned int targetsec = sechdrs[relsec].sh_info; 666 615 667 616 DEBUGP("Applying relocate section %u to %u\n", relsec, 668 - sechdrs[relsec].sh_info); 617 + targetsec); 669 618 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 670 619 /* This is where to make the change */ 671 - loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 620 + loc = (void *)sechdrs[targetsec].sh_addr 672 621 + rel[i].r_offset; 622 + /* This is the start of the target section */ 623 + loc0 = sechdrs[targetsec].sh_addr; 673 624 /* This is the symbol it is referring to */ 674 625 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr 675 626 + ELF64_R_SYM(rel[i].r_info); ··· 729 672 DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", 730 673 strtab + sym->st_name, 731 674 loc, val); 675 + val += addend; 732 676 /* can we reach it locally? */ 733 - if(!in_local_section(me, (void *)val, (void *)dot)) { 734 - 735 - if (in_local(me, (void *)val)) 736 - /* this is the case where the 737 - * symbol is local to the 738 - * module, but in a different 739 - * section, so stub the jump 740 - * in case it's more than 22 741 - * bits away */ 742 - val = get_stub(me, val, addend, ELF_STUB_DIRECT, 743 - in_init(me, loc)); 744 - else if (strncmp(strtab + sym->st_name, "$$", 2) 677 + if (in_local(me, (void *)val)) { 678 + /* this is the case where the symbol is local 679 + * to the module, but in a different section, 680 + * so stub the jump in case it's more than 22 681 + * bits away */ 682 + val = (val - dot - 8)/4; 683 + if (!RELOC_REACHABLE(val, 22)) { 684 + /* direct distance too far, create 685 + * stub entry instead */ 686 + val = get_stub(me, sym->st_value, 687 + addend, ELF_STUB_DIRECT, 688 + loc0, targetsec); 689 + } else { 690 + /* Ok, we can reach it directly. */ 691 + val = sym->st_value; 692 + val += addend; 693 + } 694 + } else { 695 + val = sym->st_value; 696 + if (strncmp(strtab + sym->st_name, "$$", 2) 745 697 == 0) 746 698 val = get_stub(me, val, addend, ELF_STUB_MILLI, 747 - in_init(me, loc)); 699 + loc0, targetsec); 748 700 else 749 701 val = get_stub(me, val, addend, ELF_STUB_GOT, 750 - in_init(me, loc)); 702 + loc0, targetsec); 751 703 } 752 704 DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 753 705 strtab + sym->st_name, loc, sym->st_value, 754 706 addend, val); 755 - /* FIXME: local symbols work as long as the 756 - * core and init pieces aren't separated too 757 - * far. If this is ever broken, you will trip 758 - * the check below. The way to fix it would 759 - * be to generate local stubs to go between init 760 - * and core */ 761 - if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 || 762 - (Elf64_Sxword)(val - dot - 8) < -0x800000) { 763 - printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n", 764 - me->name, strtab + sym->st_name); 765 - return -ENOEXEC; 766 - } 767 707 val = (val - dot - 8)/4; 708 + CHECK_RELOC(val, 22); 768 709 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 769 710 break; 770 711 case R_PARISC_DIR64: ··· 849 794 addr = (u32 *)entry->addr; 850 795 printk("INSNS: %x %x %x %x\n", 851 796 addr[0], addr[1], addr[2], addr[3]); 852 - printk("stubs used %ld, stubs max %ld\n" 853 - "init_stubs used %ld, init stubs max %ld\n" 854 - "got entries used %ld, gots max %ld\n" 797 + printk("got entries used %ld, gots max %ld\n" 855 798 "fdescs used %ld, fdescs max %ld\n", 856 - me->arch.stub_count, me->arch.stub_max, 857 - me->arch.init_stub_count, me->arch.init_stub_max, 858 799 me->arch.got_count, me->arch.got_max, 859 800 me->arch.fdesc_count, me->arch.fdesc_max); 860 801 #endif ··· 880 829 me->name, me->arch.got_count, MAX_GOTS); 881 830 return -EINVAL; 882 831 } 883 - 832 + 833 + kfree(me->arch.section); 834 + me->arch.section = NULL; 835 + 884 836 /* no symbol table */ 885 837 if(symhdr == NULL) 886 838 return 0;