diff options
author | Anders Kaseorg <andersk@ksplice.com> | 2011-05-19 18:55:27 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2011-05-19 03:25:28 -0400 |
commit | 6845756b29e4c4e7db41e2d75cafa9d091bc1c07 (patch) | |
tree | cceb66e295b238d2ab62a9ca77c9b6adce867935 /scripts/mod | |
parent | 9d63487f86115b1d3ef69670043bcf2b83c4d227 (diff) |
modpost: Update 64k section support for binutils 2.18.50
Binutils 2.18.50 made a backwards-incompatible change in the way it
writes ELF objects with over 65280 sections, to improve conformance
with the ELF specification and interoperability with other ELF tools.
Specifically, it no longer adds 256 to section indices SHN_LORESERVE
and higher to skip over the reserved range SHN_LORESERVE through
SHN_HIRESERVE; those values are only considered special in the
st_shndx field, and not in other places where section indices are
stored. See:
http://sourceware.org/bugzilla/show_bug.cgi?id=5900
http://groups.google.com/group/generic-abi/browse_thread/thread/e8bb63714b072e67/6c63738f12cc8a17
Signed-off-by: Anders Kaseorg <andersk@ksplice.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'scripts/mod')
-rw-r--r-- | scripts/mod/modpost.c | 16 | ||||
-rw-r--r-- | scripts/mod/modpost.h | 27 |
2 files changed, 14 insertions, 29 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index cd104afcc5f2..413c53693e62 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -420,11 +420,10 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
420 | return 0; | 420 | return 0; |
421 | } | 421 | } |
422 | 422 | ||
423 | if (hdr->e_shnum == 0) { | 423 | if (hdr->e_shnum == SHN_UNDEF) { |
424 | /* | 424 | /* |
425 | * There are more than 64k sections, | 425 | * There are more than 64k sections, |
426 | * read count from .sh_size. | 426 | * read count from .sh_size. |
427 | * note: it doesn't need shndx2secindex() | ||
428 | */ | 427 | */ |
429 | info->num_sections = TO_NATIVE(sechdrs[0].sh_size); | 428 | info->num_sections = TO_NATIVE(sechdrs[0].sh_size); |
430 | } | 429 | } |
@@ -432,8 +431,7 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
432 | info->num_sections = hdr->e_shnum; | 431 | info->num_sections = hdr->e_shnum; |
433 | } | 432 | } |
434 | if (hdr->e_shstrndx == SHN_XINDEX) { | 433 | if (hdr->e_shstrndx == SHN_XINDEX) { |
435 | info->secindex_strings = | 434 | info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link); |
436 | shndx2secindex(TO_NATIVE(sechdrs[0].sh_link)); | ||
437 | } | 435 | } |
438 | else { | 436 | else { |
439 | info->secindex_strings = hdr->e_shstrndx; | 437 | info->secindex_strings = hdr->e_shstrndx; |
@@ -489,7 +487,7 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
489 | sechdrs[i].sh_offset; | 487 | sechdrs[i].sh_offset; |
490 | info->symtab_stop = (void *)hdr + | 488 | info->symtab_stop = (void *)hdr + |
491 | sechdrs[i].sh_offset + sechdrs[i].sh_size; | 489 | sechdrs[i].sh_offset + sechdrs[i].sh_size; |
492 | sh_link_idx = shndx2secindex(sechdrs[i].sh_link); | 490 | sh_link_idx = sechdrs[i].sh_link; |
493 | info->strtab = (void *)hdr + | 491 | info->strtab = (void *)hdr + |
494 | sechdrs[sh_link_idx].sh_offset; | 492 | sechdrs[sh_link_idx].sh_offset; |
495 | } | 493 | } |
@@ -516,11 +514,9 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
516 | 514 | ||
517 | if (symtab_shndx_idx != ~0U) { | 515 | if (symtab_shndx_idx != ~0U) { |
518 | Elf32_Word *p; | 516 | Elf32_Word *p; |
519 | if (symtab_idx != | 517 | if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link) |
520 | shndx2secindex(sechdrs[symtab_shndx_idx].sh_link)) | ||
521 | fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n", | 518 | fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n", |
522 | filename, | 519 | filename, sechdrs[symtab_shndx_idx].sh_link, |
523 | shndx2secindex(sechdrs[symtab_shndx_idx].sh_link), | ||
524 | symtab_idx); | 520 | symtab_idx); |
525 | /* Fix endianness */ | 521 | /* Fix endianness */ |
526 | for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; | 522 | for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; |
@@ -1446,7 +1442,7 @@ static unsigned int *reloc_location(struct elf_info *elf, | |||
1446 | Elf_Shdr *sechdr, Elf_Rela *r) | 1442 | Elf_Shdr *sechdr, Elf_Rela *r) |
1447 | { | 1443 | { |
1448 | Elf_Shdr *sechdrs = elf->sechdrs; | 1444 | Elf_Shdr *sechdrs = elf->sechdrs; |
1449 | int section = shndx2secindex(sechdr->sh_info); | 1445 | int section = sechdr->sh_info; |
1450 | 1446 | ||
1451 | return (void *)elf->hdr + sechdrs[section].sh_offset + | 1447 | return (void *)elf->hdr + sechdrs[section].sh_offset + |
1452 | r->r_offset; | 1448 | r->r_offset; |
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 0388cfccac8d..2031119080dc 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
@@ -145,33 +145,22 @@ static inline int is_shndx_special(unsigned int i) | |||
145 | return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; | 145 | return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; |
146 | } | 146 | } |
147 | 147 | ||
148 | /* shndx is in [0..SHN_LORESERVE) U (SHN_HIRESERVE, 0xfffffff], thus: | 148 | /* |
149 | * shndx == 0 <=> sechdrs[0] | 149 | * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of |
150 | * ...... | 150 | * the way to -256..-1, to avoid conflicting with real section |
151 | * shndx == SHN_LORESERVE-1 <=> sechdrs[SHN_LORESERVE-1] | 151 | * indices. |
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 | */ | 152 | */ |
160 | static inline unsigned int shndx2secindex(unsigned int i) | 153 | #define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1)) |
161 | { | ||
162 | if (i <= SHN_HIRESERVE) | ||
163 | return i; | ||
164 | return i - (SHN_HIRESERVE + 1 - SHN_LORESERVE); | ||
165 | } | ||
166 | 154 | ||
167 | /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ | 155 | /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ |
168 | static inline unsigned int get_secindex(const struct elf_info *info, | 156 | static inline unsigned int get_secindex(const struct elf_info *info, |
169 | const Elf_Sym *sym) | 157 | const Elf_Sym *sym) |
170 | { | 158 | { |
159 | if (is_shndx_special(sym->st_shndx)) | ||
160 | return SPECIAL(sym->st_shndx); | ||
171 | if (sym->st_shndx != SHN_XINDEX) | 161 | if (sym->st_shndx != SHN_XINDEX) |
172 | return sym->st_shndx; | 162 | return sym->st_shndx; |
173 | return shndx2secindex(info->symtab_shndx_start[sym - | 163 | return info->symtab_shndx_start[sym - info->symtab_start]; |
174 | info->symtab_start]); | ||
175 | } | 164 | } |
176 | 165 | ||
177 | /* file2alias.c */ | 166 | /* file2alias.c */ |