Commit 1ce53adf13a54375d2a5c7cdbe341b2558389615

Authored by Denys Vlasenko
Committed by Michal Marek
1 parent 4696e2958b

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>

Showing 3 changed files with 122 additions and 29 deletions Side-by-side Diff

scripts/mod/file2alias.c
... ... @@ -839,16 +839,16 @@
839 839 char *zeros = NULL;
840 840  
841 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 843 return;
844 844  
845 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 847 zeros = calloc(1, sym->st_size);
848 848 symval = zeros;
849 849 } else {
850 850 symval = (void *)info->hdr
851   - + info->sechdrs[sym->st_shndx].sh_offset
  851 + + info->sechdrs[get_secindex(info, sym)].sh_offset
852 852 + sym->st_value;
853 853 }
854 854  
scripts/mod/modpost.c
... ... @@ -253,7 +253,7 @@
253 253 return export_unknown;
254 254 }
255 255  
256   -static enum export export_from_sec(struct elf_info *elf, Elf_Section sec)
  256 +static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
257 257 {
258 258 if (sec == elf->export_sec)
259 259 return export_plain;
... ... @@ -373,6 +373,8 @@
373 373 Elf_Ehdr *hdr;
374 374 Elf_Shdr *sechdrs;
375 375 Elf_Sym *sym;
  376 + const char *secstrings;
  377 + unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;
376 378  
377 379 hdr = grab_file(filename, &info->size);
378 380 if (!hdr) {
379 381  
... ... @@ -417,8 +419,27 @@
417 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 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 443 sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
423 444 sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
424 445 sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
... ... @@ -431,9 +452,8 @@
431 452 sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
432 453 }
433 454 /* Find symbol table. */
434   - for (i = 1; i < hdr->e_shnum; i++) {
435   - const char *secstrings
436   - = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
  455 + secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;
  456 + for (i = 1; i < info->num_sections; i++) {
437 457 const char *secname;
438 458 int nobits = sechdrs[i].sh_type == SHT_NOBITS;
439 459  
440 460  
... ... @@ -461,14 +481,26 @@
461 481 else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
462 482 info->export_gpl_future_sec = i;
463 483  
464   - if (sechdrs[i].sh_type != SHT_SYMTAB)
465   - continue;
  484 + if (sechdrs[i].sh_type == SHT_SYMTAB) {
  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;
468   - info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset
469   - + sechdrs[i].sh_size;
470   - info->strtab = (void *)hdr +
471   - sechdrs[sechdrs[i].sh_link].sh_offset;
  496 + /* 32bit section no. table? ("more than 64k sections") */
  497 + if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) {
  498 + symtab_shndx_idx = i;
  499 + info->symtab_shndx_start = (void *)hdr +
  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 505 if (!info->symtab_start)
474 506 fatal("%s has no symtab?\n", filename);
... ... @@ -480,6 +512,21 @@
480 512 sym->st_value = TO_NATIVE(sym->st_value);
481 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 530 return 1;
484 531 }
485 532  
... ... @@ -514,7 +561,7 @@
514 561 Elf_Sym *sym, const char *symname)
515 562 {
516 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 566 switch (sym->st_shndx) {
520 567 case SHN_COMMON:
521 568  
522 569  
... ... @@ -656,19 +703,19 @@
656 703 return "(unknown)";
657 704 }
658 705  
659   -static const char *sec_name(struct elf_info *elf, int shndx)
  706 +static const char *sec_name(struct elf_info *elf, int secindex)
660 707 {
661 708 Elf_Shdr *sechdrs = elf->sechdrs;
662 709 return (void *)elf->hdr +
663   - elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
664   - sechdrs[shndx].sh_name;
  710 + elf->sechdrs[elf->secindex_strings].sh_offset +
  711 + sechdrs[secindex].sh_name;
665 712 }
666 713  
667 714 static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
668 715 {
669 716 return (void *)elf->hdr +
670   - elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
671   - sechdr->sh_name;
  717 + elf->sechdrs[elf->secindex_strings].sh_offset +
  718 + sechdr->sh_name;
672 719 }
673 720  
674 721 /* if sym is empty or point to a string
675 722  
676 723  
... ... @@ -1047,11 +1094,14 @@
1047 1094 Elf_Sym *near = NULL;
1048 1095 Elf64_Sword distance = 20;
1049 1096 Elf64_Sword d;
  1097 + unsigned int relsym_secindex;
1050 1098  
1051 1099 if (relsym->st_name != 0)
1052 1100 return relsym;
  1101 +
  1102 + relsym_secindex = get_secindex(elf, relsym);
1053 1103 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
1054   - if (sym->st_shndx != relsym->st_shndx)
  1104 + if (get_secindex(elf, sym) != relsym_secindex)
1055 1105 continue;
1056 1106 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
1057 1107 continue;
1058 1108  
... ... @@ -1113,9 +1163,9 @@
1113 1163 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
1114 1164 const char *symsec;
1115 1165  
1116   - if (sym->st_shndx >= SHN_LORESERVE)
  1166 + if (is_shndx_special(sym->st_shndx))
1117 1167 continue;
1118   - symsec = sec_name(elf, sym->st_shndx);
  1168 + symsec = sec_name(elf, get_secindex(elf, sym));
1119 1169 if (strcmp(symsec, sec) != 0)
1120 1170 continue;
1121 1171 if (!is_valid_name(elf, sym))
... ... @@ -1311,7 +1361,7 @@
1311 1361 const char *tosec;
1312 1362 const struct sectioncheck *mismatch;
1313 1363  
1314   - tosec = sec_name(elf, sym->st_shndx);
  1364 + tosec = sec_name(elf, get_secindex(elf, sym));
1315 1365 mismatch = section_mismatch(fromsec, tosec);
1316 1366 if (mismatch) {
1317 1367 Elf_Sym *to;
... ... @@ -1339,7 +1389,7 @@
1339 1389 Elf_Shdr *sechdr, Elf_Rela *r)
1340 1390 {
1341 1391 Elf_Shdr *sechdrs = elf->sechdrs;
1342   - int section = sechdr->sh_info;
  1392 + int section = shndx2secindex(sechdr->sh_info);
1343 1393  
1344 1394 return (void *)elf->hdr + sechdrs[section].sh_offset +
1345 1395 (r->r_offset - sechdrs[section].sh_addr);
... ... @@ -1447,7 +1497,7 @@
1447 1497 r.r_addend = TO_NATIVE(rela->r_addend);
1448 1498 sym = elf->symtab_start + r_sym;
1449 1499 /* Skip special sections */
1450   - if (sym->st_shndx >= SHN_LORESERVE)
  1500 + if (is_shndx_special(sym->st_shndx))
1451 1501 continue;
1452 1502 check_section_mismatch(modname, elf, &r, sym, fromsec);
1453 1503 }
... ... @@ -1505,7 +1555,7 @@
1505 1555 }
1506 1556 sym = elf->symtab_start + r_sym;
1507 1557 /* Skip special sections */
1508   - if (sym->st_shndx >= SHN_LORESERVE)
  1558 + if (is_shndx_special(sym->st_shndx))
1509 1559 continue;
1510 1560 check_section_mismatch(modname, elf, &r, sym, fromsec);
1511 1561 }
... ... @@ -1530,7 +1580,7 @@
1530 1580 Elf_Shdr *sechdrs = elf->sechdrs;
1531 1581  
1532 1582 /* Walk through all sections */
1533   - for (i = 0; i < elf->hdr->e_shnum; i++) {
  1583 + for (i = 0; i < elf->num_sections; i++) {
1534 1584 check_section(modname, elf, &elf->sechdrs[i]);
1535 1585 /* We want to process only relocation sections and not .init */
1536 1586 if (sechdrs[i].sh_type == SHT_RELA)
scripts/mod/modpost.h
... ... @@ -129,7 +129,50 @@
129 129 const char *strtab;
130 130 char *modinfo;
131 131 unsigned int modinfo_len;
  132 +
  133 + /* support for 32bit section numbers */
  134 +
  135 + unsigned int num_sections; /* max_secindex + 1 */
  136 + unsigned int secindex_strings;
  137 + /* if Nth symbol table entry has .st_shndx = SHN_XINDEX,
  138 + * take shndx from symtab_shndx_start[N] instead */
  139 + Elf32_Word *symtab_shndx_start;
  140 + Elf32_Word *symtab_shndx_stop;
132 141 };
  142 +
  143 +static inline int is_shndx_special(unsigned int i)
  144 +{
  145 + return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
  146 +}
  147 +
  148 +/* shndx is in [0..SHN_LORESERVE) U (SHN_HIRESERVE, 0xfffffff], thus:
  149 + * shndx == 0 <=> sechdrs[0]
  150 + * ......
  151 + * shndx == SHN_LORESERVE-1 <=> sechdrs[SHN_LORESERVE-1]
  152 + * shndx == SHN_HIRESERVE+1 <=> sechdrs[SHN_LORESERVE]
  153 + * shndx == SHN_HIRESERVE+2 <=> sechdrs[SHN_LORESERVE+1]
  154 + * ......
  155 + * fyi: sym->st_shndx is uint16, SHN_LORESERVE = ff00, SHN_HIRESERVE = ffff,
  156 + * so basically we map 0000..feff -> 0000..feff
  157 + * ff00..ffff -> (you are a bad boy, dont do it)
  158 + * 10000..xxxx -> ff00..(xxxx-0x100)
  159 + */
  160 +static inline unsigned int shndx2secindex(unsigned int i)
  161 +{
  162 + if (i <= SHN_HIRESERVE)
  163 + return i;
  164 + return i - (SHN_HIRESERVE + 1 - SHN_LORESERVE);
  165 +}
  166 +
  167 +/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
  168 +static inline unsigned int get_secindex(const struct elf_info *info,
  169 + const Elf_Sym *sym)
  170 +{
  171 + if (sym->st_shndx != SHN_XINDEX)
  172 + return sym->st_shndx;
  173 + return shndx2secindex(info->symtab_shndx_start[sym -
  174 + info->symtab_start]);
  175 +}
133 176  
134 177 /* file2alias.c */
135 178 extern unsigned int cross_build;