From: Alan Modra Date: Tue, 14 Jun 2011 02:45:12 +0000 (+0000) Subject: PR ld/12851 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7f6ab9f8b9a5164d34c5d0b85ad4bfb8d51d89fb;p=binutils-gdb.git PR ld/12851 * elflink.c (_bfd_elf_gc_mark_extra_sections): New function. (elf_gc_sweep): Don't treat debug and sections like .comment specially here. (bfd_elf_gc_sections): Treat note sections as gc roots only when not part of a group. Always call gc_mark_extra_sections. * elf-bfd.h (_bfd_elf_gc_mark_extra_sections): Declare. * elfxx-target.h (elf_backend_gc_mark_extra_sections): Default to _bfd_elf_gc_mark_extra_sections. * elf32-arm.c (elf32_arm_gc_mark_extra_sections): Call _bfd_elf_gc_mark_extra_sections. * elf32-tic6x.c (elf32_tic6x_gc_mark_extra_sections): Likewise. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 90cdbb48592..74e161939ad 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2011-06-14 Alan Modra + + PR ld/12851 + * elflink.c (_bfd_elf_gc_mark_extra_sections): New function. + (elf_gc_sweep): Don't treat debug and sections like .comment + specially here. + (bfd_elf_gc_sections): Treat note sections as gc roots only when + not part of a group. Always call gc_mark_extra_sections. + * elf-bfd.h (_bfd_elf_gc_mark_extra_sections): Declare. + * elfxx-target.h (elf_backend_gc_mark_extra_sections): Default to + _bfd_elf_gc_mark_extra_sections. + * elf32-arm.c (elf32_arm_gc_mark_extra_sections): Call + _bfd_elf_gc_mark_extra_sections. + * elf32-tic6x.c (elf32_tic6x_gc_mark_extra_sections): Likewise. + 2011-06-13 Nick Clifton * elf32-tilepro.c (tilepro_elf_check_relocs): Delete unused local diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 55522296b90..f2d73ac0499 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2171,6 +2171,9 @@ extern bfd_boolean _bfd_elf_gc_mark_fdes extern bfd_boolean _bfd_elf_gc_mark (struct bfd_link_info *, asection *, elf_gc_mark_hook_fn); +extern bfd_boolean _bfd_elf_gc_mark_extra_sections + (struct bfd_link_info *, elf_gc_mark_hook_fn); + extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets (bfd *, struct bfd_link_info *); diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index f5b31c6cc69..b0f315b97f6 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -229,8 +229,8 @@ static reloc_howto_type elf32_arm_howto_table_1[] = bfd_elf_generic_reloc, /* special_function */ "R_ARM_THM_CALL", /* name */ FALSE, /* partial_inplace */ - 0x07ff07ff, /* src_mask */ - 0x07ff07ff, /* dst_mask */ + 0x07ff2fff, /* src_mask */ + 0x07ff2fff, /* dst_mask */ TRUE), /* pcrel_offset */ HOWTO (R_ARM_THM_PC8, /* type */ @@ -293,7 +293,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] = HOWTO (R_ARM_XPC25, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 25, /* bitsize */ + 24, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed,/* complain_on_overflow */ @@ -308,15 +308,15 @@ static reloc_howto_type elf32_arm_howto_table_1[] = HOWTO (R_ARM_THM_XPC22, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 22, /* bitsize */ + 24, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed,/* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_ARM_THM_XPC22", /* name */ FALSE, /* partial_inplace */ - 0x07ff07ff, /* src_mask */ - 0x07ff07ff, /* dst_mask */ + 0x07ff2fff, /* src_mask */ + 0x07ff2fff, /* dst_mask */ TRUE), /* pcrel_offset */ /* Dynamic TLS relocations. */ @@ -12467,6 +12467,8 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info, Elf_Internal_Shdr **elf_shdrp; bfd_boolean again; + _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook); + /* Marking EH data may cause additional code sections to be marked, requiring multiple passes. */ again = TRUE; diff --git a/bfd/elf32-tic6x.c b/bfd/elf32-tic6x.c index b31e6409394..4e9d202138a 100644 --- a/bfd/elf32-tic6x.c +++ b/bfd/elf32-tic6x.c @@ -1921,6 +1921,8 @@ elf32_tic6x_gc_mark_extra_sections (struct bfd_link_info *info, Elf_Internal_Shdr **elf_shdrp; bfd_boolean again; + _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook); + /* Marking EH data may cause additional code sections to be marked, requiring multiple passes. */ again = TRUE; diff --git a/bfd/elflink.c b/bfd/elflink.c index 9d2d68a3397..a4b7a7ab992 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11633,6 +11633,49 @@ _bfd_elf_gc_mark (struct bfd_link_info *info, return ret; } +/* Keep debug and special sections. */ + +bfd_boolean +_bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, + elf_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED) +{ + bfd *ibfd; + + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + { + asection *isec; + bfd_boolean some_kept; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) + continue; + + /* Ensure all linker created sections are kept, and see whether + any other section is already marked. */ + some_kept = FALSE; + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + { + if ((isec->flags & SEC_LINKER_CREATED) != 0) + isec->gc_mark = 1; + else if (isec->gc_mark) + some_kept = TRUE; + } + + /* If no section in this file will be kept, then we can + toss out debug sections. */ + if (!some_kept) + continue; + + /* Keep debug and special sections like .comment when they are + not part of a group. */ + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + if (elf_next_in_group (isec) == NULL + && ((isec->flags & SEC_DEBUGGING) != 0 + || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)) + isec->gc_mark = 1; + } + return TRUE; +} + /* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */ struct elf_gc_sweep_symbol_info @@ -11690,12 +11733,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) asection *first = elf_next_in_group (o); o->gc_mark = first->gc_mark; } - else if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0 - || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) - { - /* Keep debug and special sections. */ - o->gc_mark = 1; - } if (o->gc_mark) continue; @@ -11966,19 +12003,23 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) if (bfd_get_flavour (sub) != bfd_target_elf_flavour) continue; - /* Also keep SHT_NOTE sections. */ + /* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep). + Also treat note sections as a root, if the section is not part + of a group. */ for (o = sub->sections; o != NULL; o = o->next) - if ((o->flags & SEC_EXCLUDE) == 0 + if (!o->gc_mark + && (o->flags & SEC_EXCLUDE) == 0 && ((o->flags & SEC_KEEP) != 0 - || elf_section_data (o)->this_hdr.sh_type == SHT_NOTE) - && !o->gc_mark) - if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) - return FALSE; + || (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE + && elf_next_in_group (o) == NULL ))) + { + if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) + return FALSE; + } } /* Allow the backend to mark additional target specific sections. */ - if (bed->gc_mark_extra_sections) - bed->gc_mark_extra_sections (info, gc_mark_hook); + bed->gc_mark_extra_sections (info, gc_mark_hook); /* ... and mark SEC_EXCLUDE for those that go. */ return elf_gc_sweep (abfd, info); diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index b92e2a635fc..b033c176550 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -143,7 +143,7 @@ #define elf_backend_gc_mark_hook _bfd_elf_gc_mark_hook #endif #ifndef elf_backend_gc_mark_extra_sections -#define elf_backend_gc_mark_extra_sections NULL +#define elf_backend_gc_mark_extra_sections _bfd_elf_gc_mark_extra_sections #endif #ifndef elf_backend_gc_sweep_hook #define elf_backend_gc_sweep_hook NULL