PR ld/12851
authorAlan Modra <amodra@gmail.com>
Tue, 14 Jun 2011 02:45:12 +0000 (02:45 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 14 Jun 2011 02:45:12 +0000 (02:45 +0000)
* 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.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf32-arm.c
bfd/elf32-tic6x.c
bfd/elflink.c
bfd/elfxx-target.h

index 90cdbb4859269300bdb4d6c6f27584495c4bafa5..74e161939ad49432d499befd91e92932b8fe2b43 100644 (file)
@@ -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
index 55522296b9075ad30704f193a657b63a924f6b0d..f2d73ac049983efd4fb432e32c8a6c1b34b40f73 100644 (file)
@@ -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 *);
 
index f5b31c6cc692ebfaf6f85d17175535180e21adb2..b0f315b97f624b8551e8746510d81a348345ce21 100644 (file)
@@ -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;
index b31e640939486a6a8344010d45da6a27620e911b..4e9d202138a79563a556efbfdecdb46e97f97a7b 100644 (file)
@@ -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;
index 9d2d68a3397766d08ccdb23c655bd89e9a59bf1e..a4b7a7ab9921c62f7ffaba86e0561f7c5c29f6ae 100644 (file)
@@ -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);
index b92e2a635fc3c7f284ae78794f4343da759940c8..b033c17655021b30006c7b4040861b6783ea79f8 100644 (file)
 #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