aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2011-06-14 02:45:12 +0000
committerAlan Modra <amodra@gmail.com>2011-06-14 02:45:12 +0000
commit7f6ab9f8b9a5164d34c5d0b85ad4bfb8d51d89fb (patch)
treea6bbfb3426ae13110d87c3a0b45b79498d0682ca
parentc6431bc3708cda380b0bdc35d11827882e803f2d (diff)
downloadbinutils-7f6ab9f8b9a5164d34c5d0b85ad4bfb8d51d89fb.zip
binutils-7f6ab9f8b9a5164d34c5d0b85ad4bfb8d51d89fb.tar.gz
binutils-7f6ab9f8b9a5164d34c5d0b85ad4bfb8d51d89fb.tar.bz2
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.
-rw-r--r--bfd/ChangeLog15
-rw-r--r--bfd/elf-bfd.h3
-rw-r--r--bfd/elf32-arm.c14
-rw-r--r--bfd/elf32-tic6x.c2
-rw-r--r--bfd/elflink.c69
-rw-r--r--bfd/elfxx-target.h2
6 files changed, 84 insertions, 21 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 90cdbb4..74e1619 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,18 @@
+2011-06-14 Alan Modra <amodra@gmail.com>
+
+ 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 <nickc@redhat.com>
* elf32-tilepro.c (tilepro_elf_check_relocs): Delete unused local
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 5552229..f2d73ac 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 f5b31c6..b0f315b 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 b31e640..4e9d202 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 9d2d68a..a4b7a7a 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 b92e2a6..b033c17 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