aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-07-28 19:47:53 -0400
committerMichal Marek <mmarek@suse.cz>2010-08-03 09:05:56 -0400
commit1ce53adf13a54375d2a5c7cdbe341b2558389615 (patch)
treeebd9f596daa9cdbf3eca2f964e2f58946d4b4d16 /scripts/mod
parent4696e2958b345189afebcb52e365d16ca6e403ef (diff)
modpost: support objects with more than 64k sections
This patch makes modpost able to process object files with more than 64k sections. Needed for huge kernel builds (allyesconfig, for example) with -ffunction-sections. 64k sections handling is covered, for example, by this document: "IA-64 gABI Proposal 74: Section Indexes" http://www.codesourcery.com/public/cxx-abi/abi/prop-74-sindex.html Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> Signed-off-by: Anders Kaseorg <andersk@mit.edu> Acked-by: Sam Ravnborg <sam@ravnborg.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Michal Marek <mmarek@suse.cz>
Diffstat (limited to 'scripts/mod')
-rw-r--r--scripts/mod/file2alias.c6
-rw-r--r--scripts/mod/modpost.c102
-rw-r--r--scripts/mod/modpost.h43
3 files changed, 122 insertions, 29 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 220213e603d..33f436328f9 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -839,16 +839,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
839 char *zeros = NULL; 839 char *zeros = NULL;
840 840
841 /* We're looking for a section relative symbol */ 841 /* We're looking for a section relative symbol */
842 if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum) 842 if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
843 return; 843 return;
844 844
845 /* Handle all-NULL symbols allocated into .bss */ 845 /* Handle all-NULL symbols allocated into .bss */
846 if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) { 846 if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
847 zeros = calloc(1, sym->st_size); 847 zeros = calloc(1, sym->st_size);
848 symval = zeros; 848 symval = zeros;
849 } else { 849 } else {
850 symval = (void *)info->hdr 850 symval = (void *)info->hdr
851 + info->sechdrs[sym->st_shndx].sh_offset 851 + info->sechdrs[get_secindex(info, sym)].sh_offset
852 + sym->st_value; 852 + sym->st_value;
853 } 853 }
854 854
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 3318692e4e7..7249ab44f44 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -253,7 +253,7 @@ static enum export export_no(const char *s)
253 return export_unknown; 253 return export_unknown;
254} 254}
255 255
256static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) 256static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
257{ 257{
258 if (sec == elf->export_sec) 258 if (sec == elf->export_sec)
259 return export_plain; 259 return export_plain;
@@ -373,6 +373,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
373 Elf_Ehdr *hdr; 373 Elf_Ehdr *hdr;
374 Elf_Shdr *sechdrs; 374 Elf_Shdr *sechdrs;
375 Elf_Sym *sym; 375 Elf_Sym *sym;
376 const char *secstrings;
377 unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;
376 378
377 hdr = grab_file(filename, &info->size); 379 hdr = grab_file(filename, &info->size);
378 if (!hdr) { 380 if (!hdr) {
@@ -417,8 +419,27 @@ static int parse_elf(struct elf_info *info, const char *filename)
417 return 0; 419 return 0;
418 } 420 }
419 421
422 if (hdr->e_shnum == 0) {
423 /*
424 * There are more than 64k sections,
425 * read count from .sh_size.
426 * note: it doesn't need shndx2secindex()
427 */
428 info->num_sections = TO_NATIVE(sechdrs[0].sh_size);
429 }
430 else {
431 info->num_sections = hdr->e_shnum;
432 }
433 if (hdr->e_shstrndx == SHN_XINDEX) {
434 info->secindex_strings =
435 shndx2secindex(TO_NATIVE(sechdrs[0].sh_link));
436 }
437 else {
438 info->secindex_strings = hdr->e_shstrndx;
439 }
440
420 /* Fix endianness in section headers */ 441 /* Fix endianness in section headers */
421 for (i = 0; i < hdr->e_shnum; i++) { 442 for (i = 0; i < info->num_sections; i++) {
422 sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); 443 sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
423 sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); 444 sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
424 sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); 445 sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
@@ -431,9 +452,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
431 sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); 452 sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
432 } 453 }
433 /* Find symbol table. */ 454 /* Find symbol table. */
434 for (i = 1; i < hdr->e_shnum; i++) { 455 secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;
435 const char *secstrings 456 for (i = 1; i < info->num_sections; i++) {
436 = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
437 const char *secname; 457 const char *secname;
438 int nobits = sechdrs[i].sh_type == SHT_NOBITS; 458 int nobits = sechdrs[i].sh_type == SHT_NOBITS;
439 459
@@ -461,14 +481,26 @@ static int parse_elf(struct elf_info *info, const char *filename)
461 else if (strcmp(secname, "__ksymtab_gpl_future") == 0) 481 else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
462 info->export_gpl_future_sec = i; 482 info->export_gpl_future_sec = i;
463 483
464 if (sechdrs[i].sh_type != SHT_SYMTAB) 484 if (sechdrs[i].sh_type == SHT_SYMTAB) {
465 continue; 485 unsigned int sh_link_idx;
486 symtab_idx = i;
487 info->symtab_start = (void *)hdr +
488 sechdrs[i].sh_offset;
489 info->symtab_stop = (void *)hdr +
490 sechdrs[i].sh_offset + sechdrs[i].sh_size;
491 sh_link_idx = shndx2secindex(sechdrs[i].sh_link);
492 info->strtab = (void *)hdr +
493 sechdrs[sh_link_idx].sh_offset;
494 }
466 495
467 info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; 496 /* 32bit section no. table? ("more than 64k sections") */
468 info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset 497 if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) {
469 + sechdrs[i].sh_size; 498 symtab_shndx_idx = i;
470 info->strtab = (void *)hdr + 499 info->symtab_shndx_start = (void *)hdr +
471 sechdrs[sechdrs[i].sh_link].sh_offset; 500 sechdrs[i].sh_offset;
501 info->symtab_shndx_stop = (void *)hdr +
502 sechdrs[i].sh_offset + sechdrs[i].sh_size;
503 }
472 } 504 }
473 if (!info->symtab_start) 505 if (!info->symtab_start)
474 fatal("%s has no symtab?\n", filename); 506 fatal("%s has no symtab?\n", filename);
@@ -480,6 +512,21 @@ static int parse_elf(struct elf_info *info, const char *filename)
480 sym->st_value = TO_NATIVE(sym->st_value); 512 sym->st_value = TO_NATIVE(sym->st_value);
481 sym->st_size = TO_NATIVE(sym->st_size); 513 sym->st_size = TO_NATIVE(sym->st_size);
482 } 514 }
515
516 if (symtab_shndx_idx != ~0U) {
517 Elf32_Word *p;
518 if (symtab_idx !=
519 shndx2secindex(sechdrs[symtab_shndx_idx].sh_link))
520 fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n",
521 filename,
522 shndx2secindex(sechdrs[symtab_shndx_idx].sh_link),
523 symtab_idx);
524 /* Fix endianness */
525 for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;
526 p++)
527 *p = TO_NATIVE(*p);
528 }
529
483 return 1; 530 return 1;
484} 531}
485 532
@@ -514,7 +561,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
514 Elf_Sym *sym, const char *symname) 561 Elf_Sym *sym, const char *symname)
515{ 562{
516 unsigned int crc; 563 unsigned int crc;
517 enum export export = export_from_sec(info, sym->st_shndx); 564 enum export export = export_from_sec(info, get_secindex(info, sym));
518 565
519 switch (sym->st_shndx) { 566 switch (sym->st_shndx) {
520 case SHN_COMMON: 567 case SHN_COMMON:
@@ -656,19 +703,19 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
656 return "(unknown)"; 703 return "(unknown)";
657} 704}
658 705
659static const char *sec_name(struct elf_info *elf, int shndx) 706static const char *sec_name(struct elf_info *elf, int secindex)
660{ 707{
661 Elf_Shdr *sechdrs = elf->sechdrs; 708 Elf_Shdr *sechdrs = elf->sechdrs;
662 return (void *)elf->hdr + 709 return (void *)elf->hdr +
663 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + 710 elf->sechdrs[elf->secindex_strings].sh_offset +
664 sechdrs[shndx].sh_name; 711 sechdrs[secindex].sh_name;
665} 712}
666 713
667static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr) 714static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
668{ 715{
669 return (void *)elf->hdr + 716 return (void *)elf->hdr +
670 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + 717 elf->sechdrs[elf->secindex_strings].sh_offset +
671 sechdr->sh_name; 718 sechdr->sh_name;
672} 719}
673 720
674/* if sym is empty or point to a string 721/* if sym is empty or point to a string
@@ -1047,11 +1094,14 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
1047 Elf_Sym *near = NULL;