* elflink.c (_bfd_elf_gc_mark): Mark sections referenced by
authorAlan Modra <amodra@gmail.com>
Wed, 29 Jun 2005 14:05:21 +0000 (14:05 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 29 Jun 2005 14:05:21 +0000 (14:05 +0000)
.eh_frame specially..
(bfd_elf_gc_sections): ..rather than totally ignoring .eh_frame.
Don't recheck sections we have already marked.
(elf_gc_sweep): Keep non-code sections referenced from .eh_frame.
* section.c (struct bfd_section): Add gc_mark_from_eh.
(STD_SECTION): Adjust.
* ecoff.c (bfd_debug_section): Adjust.
* bfd-in2.h: Regenerate.

bfd/ChangeLog
bfd/bfd-in2.h
bfd/ecoff.c
bfd/elflink.c
bfd/section.c

index 769534b..f4e4944 100644 (file)
@@ -1,5 +1,17 @@
 2005-06-29  Alan Modra  <amodra@bigpond.net.au>
 
+       * elflink.c (_bfd_elf_gc_mark): Mark sections referenced by
+       .eh_frame specially..
+       (bfd_elf_gc_sections): ..rather than totally ignoring .eh_frame.
+       Don't recheck sections we have already marked.
+       (elf_gc_sweep): Keep non-code sections referenced from .eh_frame.
+       * section.c (struct bfd_section): Add gc_mark_from_eh.
+       (STD_SECTION): Adjust.
+       * ecoff.c (bfd_debug_section): Adjust.
+       * bfd-in2.h: Regenerate.
+
+2005-06-29  Alan Modra  <amodra@bigpond.net.au>
+
        * elflink.c (elf_gc_sweep): Do not refcount on sections that have
        not been processed by check_relocs.
 
index a1ca958..7d16049 100644 (file)
@@ -1262,8 +1262,9 @@ typedef struct bfd_section
      output sections that have an input section.  */
   unsigned int linker_has_input : 1;
 
-  /* A mark flag used by some linker backends for garbage collection.  */
+  /* Mark flags used by some linker backends for garbage collection.  */
   unsigned int gc_mark : 1;
+  unsigned int gc_mark_from_eh : 1;
 
   /* The following flags are used by the ELF linker. */
 
index 74098ed..832b22f 100644 (file)
@@ -54,12 +54,12 @@ static asection bfd_debug_section =
 {
   /* name,      id,  index, next, prev, flags, user_set_vma,       */
      "*DEBUG*", 0,   0,     NULL, NULL, 0,     0,
-  /* linker_mark, linker_has_input, gc_mark, segment_mark,         */
-     0,           0,                0,       0,
-  /* sec_info_type, use_rela_p, has_tls_reloc, has_gp_reloc,       */
-     0,                    0,          0,             0,
-  /* need_finalize_relax, reloc_done,                              */
-     0,                          0,
+  /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      */
+     0,           0,                1,       0,
+  /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       */
+     0,            0,             0,          0,
+  /* has_gp_reloc, need_finalize_relax, reloc_done,                */
+     0,            0,                   0,
   /* vma, lma, size, rawsize,                                      */
      0,   0,   0,    0,
   /* output_offset, output_section, alignment_power,               */
@@ -68,7 +68,7 @@ static asection bfd_debug_section =
      NULL,       NULL,        0,           0,       0,
   /* line_filepos, userdata, contents, lineno, lineno_count,       */
      0,            NULL,     NULL,     NULL,   0,
-  /* entsize, kept_section, moving_line_filepos,                  */
+  /* entsize, kept_section, moving_line_filepos,                   */
      0,       NULL,         0,
   /* target_index, used_by_bfd, constructor_chain, owner,          */
      0,            NULL,        NULL,              NULL,
index b561b1f..8870857 100644 (file)
@@ -8733,6 +8733,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
                  gc_mark_hook_fn gc_mark_hook)
 {
   bfd_boolean ret;
+  bfd_boolean is_eh;
   asection *group_sec;
 
   sec->gc_mark = 1;
@@ -8745,6 +8746,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
 
   /* Look through the section relocs.  */
   ret = TRUE;
+  is_eh = strcmp (sec->name, ".eh_frame") == 0;
   if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
     {
       Elf_Internal_Rela *relstart, *rel, *relend;
@@ -8821,6 +8823,8 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
            {
              if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour)
                rsec->gc_mark = 1;
+             else if (is_eh)
+               rsec->gc_mark_from_eh = 1;
              else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
                {
                  ret = FALSE;
@@ -8891,6 +8895,41 @@ elf_gc_sweep (struct bfd_link_info *info, gc_sweep_hook_fn gc_sweep_hook)
          if (o->gc_mark)
            continue;
 
+         /* Keep .gcc_except_table.* if the associated .text.* is
+            marked.  This isn't very nice, but the proper solution,
+            splitting .eh_frame up and using comdat doesn't pan out 
+            easily due to needing special relocs to handle the
+            difference of two symbols in separate sections.
+            Don't keep code sections referenced by .eh_frame.  */
+         if (o->gc_mark_from_eh && (o->flags & SEC_CODE) == 0)
+           {
+             if (strncmp (o->name, ".gcc_except_table.", 18) == 0)
+               {
+                 unsigned long len;
+                 char *fn_name;
+                 asection *fn_text;
+
+                 len = strlen (o->name + 18) + 1;
+                 fn_name = bfd_malloc (len + 6);
+                 if (fn_name == NULL)
+                   return FALSE;
+                 memcpy (fn_name, ".text.", 6);
+                 memcpy (fn_name + 6, o->name + 18, len);
+                 fn_text = bfd_get_section_by_name (sub, fn_name);
+                 free (fn_name);
+                 if (fn_text != NULL && fn_text->gc_mark)
+                   o->gc_mark = 1;
+               }
+
+             /* If not using specially named exception table section,
+                then keep whatever we are using.  */
+             else
+               o->gc_mark = 1;
+
+             if (o->gc_mark)
+               continue;
+           }
+
          /* Skip sweeping sections already excluded.  */
          if (o->flags & SEC_EXCLUDE)
            continue;
@@ -9125,18 +9164,9 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
        continue;
 
       for (o = sub->sections; o != NULL; o = o->next)
-       {
-         if (o->flags & SEC_KEEP)
-           {
-             /* _bfd_elf_discard_section_eh_frame knows how to discard
-                orphaned FDEs so don't mark sections referenced by the
-                EH frame section.  */
-             if (strcmp (o->name, ".eh_frame") == 0)
-               o->gc_mark = 1;
-             else if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
-               return FALSE;
-           }
-       }
+       if ((o->flags & SEC_KEEP) != 0 && !o->gc_mark)
+         if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+           return FALSE;
     }
 
   /* ... and mark SEC_EXCLUDE for those that go.  */
index 75acad7..aeb63a6 100644 (file)
@@ -354,8 +354,9 @@ CODE_FRAGMENT
 .     output sections that have an input section.  *}
 .  unsigned int linker_has_input : 1;
 .
-.  {* A mark flag used by some linker backends for garbage collection.  *}
+.  {* Mark flags used by some linker backends for garbage collection.  *}
 .  unsigned int gc_mark : 1;
+.  unsigned int gc_mark_from_eh : 1;
 .
 .  {* The following flags are used by the ELF linker. *}
 .
@@ -661,18 +662,18 @@ static const asymbol global_syms[] =
 
 #define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX)                                \
   const asymbol * const SYM = (asymbol *) &global_syms[IDX];           \
-  asection SEC =                                                       \
+  asection SEC =                                                       \
     /* name, id,  index, next, prev, flags, user_set_vma,            */        \
     { NAME,  IDX, 0,     NULL, NULL, FLAGS, 0,                         \
                                                                        \
-    /* linker_mark, linker_has_input, gc_mark, segment_mark,         */        \
+    /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh,      */        \
        0,           0,                1,       0,                      \
                                                                        \
-    /* sec_info_type, use_rela_p, has_tls_reloc, has_gp_reloc,       */ \
-       0,            0,          0,             0,                     \
+    /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc,       */        \
+       0,            0,             0,          0,                     \
                                                                        \
-    /* need_finalize_relax, reloc_done,                              */ \
-       0,                  0,                                          \
+    /* has_gp_reloc, need_finalize_relax, reloc_done,                */        \
+       0,            0,                   0,                           \
                                                                        \
     /* vma, lma, size, rawsize                                       */        \
        0,   0,   0,    0,                                              \
@@ -686,8 +687,8 @@ static const asymbol global_syms[] =
     /* line_filepos, userdata, contents, lineno, lineno_count,       */        \
        0,            NULL,     NULL,     NULL,   0,                    \
                                                                        \
-    /* entsize, kept_section, moving_line_filepos,                */   \
-       0,       NULL,        0,                                        \
+    /* entsize, kept_section, moving_line_filepos,                   */        \
+       0,       NULL,         0,                                       \
                                                                        \
     /* target_index, used_by_bfd, constructor_chain, owner,          */        \
        0,            NULL,        NULL,              NULL,             \