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 { 24 unsigned long got_offset, got_count, got_max; 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; 28 int unwind_section; 29 struct unwind_table *unwind; 30 };
··· 23 { 24 unsigned long got_offset, got_count, got_max; 25 unsigned long fdesc_offset, fdesc_count, fdesc_max; 26 + struct { 27 + unsigned long stub_offset; 28 + unsigned int stub_entries; 29 + } *section; 30 int unwind_section; 31 struct unwind_table *unwind; 32 };
+135 -81
arch/parisc/kernel/module.c
··· 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 ··· 25 * 26 * 27 * Notes: 28 * - SEGREL32 handling 29 * We are not doing SEGREL32 handling correctly. According to the ABI, we 30 * should do a value offset, like this: ··· 72 #define DEBUGP(fmt...) 73 #endif 74 75 #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)))) { \ 78 printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ 79 me->name, strtab + sym->st_name, (unsigned long)val, bits); \ 80 return -ENOEXEC; \ ··· 109 { 110 return in_init(me, loc) || in_core(me, loc); 111 } 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 120 #ifndef CONFIG_64BIT 121 struct got_entry { ··· 269 /* Free memory returned from module_alloc */ 270 void module_free(struct module *mod, void *module_region) 271 { 272 vfree(module_region); 273 /* FIXME: If module_region == mod->init_region, trim exception 274 table entries. */ 275 } 276 277 #define CONST ··· 293 CONST char *secstrings, 294 struct module *me) 295 { 296 - unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0; 297 unsigned int i; 298 299 for (i = 1; i < hdr->e_shnum; i++) { 300 - const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset; 301 unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); 302 303 if (strncmp(secstrings + sechdrs[i].sh_name, 304 ".PARISC.unwind", 14) == 0) ··· 320 */ 321 gots += count_gots(rels, nrels); 322 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); 328 } 329 330 /* align things a bit */ ··· 348 me->arch.fdesc_offset = me->core_size; 349 me->core_size += fdescs * sizeof(Elf_Fdesc); 350 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 me->arch.got_max = gots; 360 me->arch.fdesc_max = fdescs; 361 - me->arch.stub_max = stubs; 362 - me->arch.init_stub_max = init_stubs; 363 364 return 0; 365 } ··· 412 }; 413 414 static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, 415 - enum elf_stub_type stub_type, int init_section) 416 { 417 - unsigned long i; 418 struct stub_entry *stub; 419 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); 430 } 431 432 #ifndef CONFIG_64BIT 433 /* for 32-bit the stub looks like this: ··· 525 Elf32_Addr val; 526 Elf32_Sword addend; 527 Elf32_Addr dot; 528 //unsigned long dp = (unsigned long)$global$; 529 register unsigned long dp asm ("r27"); 530 531 DEBUGP("Applying relocate section %u to %u\n", relsec, 532 - sechdrs[relsec].sh_info); 533 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 534 /* This is where to make the change */ 535 - loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 536 + rel[i].r_offset; 537 /* This is the symbol it is referring to */ 538 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 539 + ELF32_R_SYM(rel[i].r_info); ··· 609 break; 610 case R_PARISC_PCREL17F: 611 /* 17-bit PC relative address */ 612 - val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc)); 613 val = (val - dot - 8)/4; 614 - CHECK_RELOC(val, 17) 615 *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); 616 break; 617 case R_PARISC_PCREL22F: 618 /* 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) 623 val = (val - dot - 8)/4; 624 - CHECK_RELOC(val, 22); 625 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 626 break; 627 ··· 663 Elf64_Addr val; 664 Elf64_Sxword addend; 665 Elf64_Addr dot; 666 667 DEBUGP("Applying relocate section %u to %u\n", relsec, 668 - sechdrs[relsec].sh_info); 669 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 670 /* This is where to make the change */ 671 - loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 672 + rel[i].r_offset; 673 /* This is the symbol it is referring to */ 674 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr 675 + ELF64_R_SYM(rel[i].r_info); ··· 729 DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", 730 strtab + sym->st_name, 731 loc, val); 732 /* 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) 745 == 0) 746 val = get_stub(me, val, addend, ELF_STUB_MILLI, 747 - in_init(me, loc)); 748 else 749 val = get_stub(me, val, addend, ELF_STUB_GOT, 750 - in_init(me, loc)); 751 } 752 DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 753 strtab + sym->st_name, loc, sym->st_value, 754 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 val = (val - dot - 8)/4; 768 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 769 break; 770 case R_PARISC_DIR64: ··· 849 addr = (u32 *)entry->addr; 850 printk("INSNS: %x %x %x %x\n", 851 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" 855 "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 me->arch.got_count, me->arch.got_max, 859 me->arch.fdesc_count, me->arch.fdesc_max); 860 #endif ··· 880 me->name, me->arch.got_count, MAX_GOTS); 881 return -EINVAL; 882 } 883 - 884 /* no symbol table */ 885 if(symhdr == NULL) 886 return 0;
··· 6 * 7 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 8 * Copyright (C) 2003 Randolph Chung <tausq at debian . org> 9 + * Copyright (C) 2008 Helge Deller <deller@gmx.de> 10 * 11 * 12 * This program is free software; you can redistribute it and/or modify ··· 24 * 25 * 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 + * 40 * - SEGREL32 handling 41 * We are not doing SEGREL32 handling correctly. According to the ABI, we 42 * should do a value offset, like this: ··· 58 #define DEBUGP(fmt...) 59 #endif 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 + 66 #define CHECK_RELOC(val, bits) \ 67 + if (!RELOC_REACHABLE(val, bits)) { \ 68 printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \ 69 me->name, strtab + sym->st_name, (unsigned long)val, bits); \ 70 return -ENOEXEC; \ ··· 91 { 92 return in_init(me, loc) || in_core(me, loc); 93 } 94 95 #ifndef CONFIG_64BIT 96 struct got_entry { ··· 258 /* Free memory returned from module_alloc */ 259 void module_free(struct module *mod, void *module_region) 260 { 261 + kfree(mod->arch.section); 262 + mod->arch.section = NULL; 263 + 264 vfree(module_region); 265 /* FIXME: If module_region == mod->init_region, trim exception 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); 277 } 278 279 #define CONST ··· 269 CONST char *secstrings, 270 struct module *me) 271 { 272 + unsigned long gots = 0, fdescs = 0, len; 273 unsigned int i; 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 + 280 for (i = 1; i < hdr->e_shnum; i++) { 281 + const Elf_Rela *rels = (void *)sechdrs[i].sh_addr; 282 unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels); 283 + unsigned int count, s; 284 285 if (strncmp(secstrings + sechdrs[i].sh_name, 286 ".PARISC.unwind", 14) == 0) ··· 290 */ 291 gots += count_gots(rels, nrels); 292 fdescs += count_fdescs(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; 310 } 311 312 /* align things a bit */ ··· 306 me->arch.fdesc_offset = me->core_size; 307 me->core_size += fdescs * sizeof(Elf_Fdesc); 308 309 me->arch.got_max = gots; 310 me->arch.fdesc_max = fdescs; 311 312 return 0; 313 } ··· 380 }; 381 382 static Elf_Addr get_stub(struct module *me, unsigned long value, long addend, 383 + enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec) 384 { 385 struct stub_entry *stub; 386 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; 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 + 403 404 #ifndef CONFIG_64BIT 405 /* for 32-bit the stub looks like this: ··· 489 Elf32_Addr val; 490 Elf32_Sword addend; 491 Elf32_Addr dot; 492 + Elf_Addr loc0; 493 + unsigned int targetsec = sechdrs[relsec].sh_info; 494 //unsigned long dp = (unsigned long)$global$; 495 register unsigned long dp asm ("r27"); 496 497 DEBUGP("Applying relocate section %u to %u\n", relsec, 498 + targetsec); 499 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 500 /* This is where to make the change */ 501 + loc = (void *)sechdrs[targetsec].sh_addr 502 + rel[i].r_offset; 503 + /* This is the start of the target section */ 504 + loc0 = sechdrs[targetsec].sh_addr; 505 /* This is the symbol it is referring to */ 506 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 507 + ELF32_R_SYM(rel[i].r_info); ··· 569 break; 570 case R_PARISC_PCREL17F: 571 /* 17-bit PC relative address */ 572 + /* calculate direct call offset */ 573 + val += addend; 574 val = (val - dot - 8)/4; 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 + } 583 *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); 584 break; 585 case R_PARISC_PCREL22F: 586 /* 22-bit PC relative address; only defined for pa20 */ 587 + /* calculate direct call offset */ 588 + val += addend; 589 val = (val - dot - 8)/4; 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 + } 598 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 599 break; 600 ··· 610 Elf64_Addr val; 611 Elf64_Sxword addend; 612 Elf64_Addr dot; 613 + Elf_Addr loc0; 614 + unsigned int targetsec = sechdrs[relsec].sh_info; 615 616 DEBUGP("Applying relocate section %u to %u\n", relsec, 617 + targetsec); 618 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 619 /* This is where to make the change */ 620 + loc = (void *)sechdrs[targetsec].sh_addr 621 + rel[i].r_offset; 622 + /* This is the start of the target section */ 623 + loc0 = sechdrs[targetsec].sh_addr; 624 /* This is the symbol it is referring to */ 625 sym = (Elf64_Sym *)sechdrs[symindex].sh_addr 626 + ELF64_R_SYM(rel[i].r_info); ··· 672 DEBUGP("PCREL22F Symbol %s loc %p val %lx\n", 673 strtab + sym->st_name, 674 loc, val); 675 + val += addend; 676 /* can we reach it locally? */ 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) 697 == 0) 698 val = get_stub(me, val, addend, ELF_STUB_MILLI, 699 + loc0, targetsec); 700 else 701 val = get_stub(me, val, addend, ELF_STUB_GOT, 702 + loc0, targetsec); 703 } 704 DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 705 strtab + sym->st_name, loc, sym->st_value, 706 addend, val); 707 val = (val - dot - 8)/4; 708 + CHECK_RELOC(val, 22); 709 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 710 break; 711 case R_PARISC_DIR64: ··· 794 addr = (u32 *)entry->addr; 795 printk("INSNS: %x %x %x %x\n", 796 addr[0], addr[1], addr[2], addr[3]); 797 + printk("got entries used %ld, gots max %ld\n" 798 "fdescs used %ld, fdescs max %ld\n", 799 me->arch.got_count, me->arch.got_max, 800 me->arch.fdesc_count, me->arch.fdesc_max); 801 #endif ··· 829 me->name, me->arch.got_count, MAX_GOTS); 830 return -EINVAL; 831 } 832 + 833 + kfree(me->arch.section); 834 + me->arch.section = NULL; 835 + 836 /* no symbol table */ 837 if(symhdr == NULL) 838 return 0;