bfd/
authorAlan Modra <amodra@gmail.com>
Thu, 1 Jul 2004 13:48:53 +0000 (13:48 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 1 Jul 2004 13:48:53 +0000 (13:48 +0000)
* elflink.c (elf_section_ignore_discarded_relocs): Revert last
change.  Comment.
(elf_section_complain_discarded): New function.  Handle
.gcc_except_table too.
(elf_link_input_bfd): Rewrite handling of relocs against symbols
in discarded sections.
* elf-bfd.h (elf_discarded_section): Protect macro arg.
ld/testsuite/
* ld-discard/extern.d: Update.
* ld-discard/start.d: Update.
* ld-discard/static.d: Update.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elflink.c
ld/testsuite/ChangeLog
ld/testsuite/ld-discard/extern.d
ld/testsuite/ld-discard/start.d
ld/testsuite/ld-discard/static.d

index 11bed97504e3701136da0e5ed0409837e5818726..c00435ad412690037c405ec33710399e24e83eed 100644 (file)
@@ -1,3 +1,13 @@
+2004-07-01  Alan Modra  <amodra@bigpond.net.au>
+
+       * elflink.c (elf_section_ignore_discarded_relocs): Revert last
+       change.  Comment.
+       (elf_section_complain_discarded): New function.  Handle
+       .gcc_except_table too.
+       (elf_link_input_bfd): Rewrite handling of relocs against symbols
+       in discarded sections.
+       * elf-bfd.h (elf_discarded_section): Protect macro arg.
+
 2004-06-30  James E Wilson  <wilson@specifixinc.com>
 
        * elfxx-ia64.c (elfNN_ia64_check_relocs): New local pltoff.  Initialize
index 532cdb31607084b16ed343c1c7e2d8ed8d61e8b0..1892cb17420c1f1eb2c6042ce7aab6a327fde5aa 100644 (file)
@@ -1067,8 +1067,8 @@ struct bfd_elf_section_data
 #define elf_discarded_section(sec)                             \
   (!bfd_is_abs_section (sec)                                   \
    && bfd_is_abs_section ((sec)->output_section)               \
-   && sec->sec_info_type != ELF_INFO_TYPE_MERGE                        \
-   && sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS)
+   && (sec)->sec_info_type != ELF_INFO_TYPE_MERGE              \
+   && (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS)
 
 #define get_elf_backend_data(abfd) \
   ((const struct elf_backend_data *) (abfd)->xvec->backend_data)
index e682758728c0501ce54f061f7a3a10a31511ac12..930438dbeba71d43a8859708ae7e41252d3723e2 100644 (file)
@@ -6258,18 +6258,22 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   return TRUE;
 }
 
+/* Return TRUE if special handling is done for relocs in SEC against
+   symbols defined in discarded sections.  */
+
 static bfd_boolean
 elf_section_ignore_discarded_relocs (asection *sec)
 {
   const struct elf_backend_data *bed;
 
-  if (strncmp (".stab", sec->name, 5) == 0
-      && (!sec->name[5] ||
-         (sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
-    return TRUE;
-
-  if (strcmp (".eh_frame", sec->name) == 0)
-    return TRUE;
+  switch (sec->sec_info_type)
+    {
+    case ELF_INFO_TYPE_STABS:
+    case ELF_INFO_TYPE_EH_FRAME:
+      return TRUE;
+    default:
+      break;
+    }
 
   bed = get_elf_backend_data (sec->owner);
   if (bed->elf_backend_ignore_discarded_relocs != NULL
@@ -6279,6 +6283,26 @@ elf_section_ignore_discarded_relocs (asection *sec)
   return FALSE;
 }
 
+/* Return TRUE if we should complain about a reloc in SEC against a
+   symbol defined in a discarded section.  */
+
+static bfd_boolean
+elf_section_complain_discarded (asection *sec)
+{
+  if (strncmp (".stab", sec->name, 5) == 0
+      && (!sec->name[5] ||
+         (sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
+    return FALSE;
+
+  if (strcmp (".eh_frame", sec->name) == 0)
+    return FALSE;
+
+  if (strcmp (".gcc_except_table", sec->name) == 0)
+    return FALSE;
+
+  return TRUE;
+}
+
 /* Link an input file into the linker output file.  This function
    handles all the sections and relocations of the input file at once.
    This is so that we only have to read the local symbols once, and
@@ -6551,99 +6575,87 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          if (!elf_section_ignore_discarded_relocs (o))
            {
              Elf_Internal_Rela *rel, *relend;
+             bfd_boolean complain = elf_section_complain_discarded (o);
 
              rel = internal_relocs;
              relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
              for ( ; rel < relend; rel++)
                {
                  unsigned long r_symndx = rel->r_info >> r_sym_shift;
-                 asection *sec;
+                 asection **ps, *sec;
+                 struct elf_link_hash_entry *h = NULL;
+                 const char *sym_name;
 
                  if (r_symndx >= locsymcount
                      || (elf_bad_symtab (input_bfd)
                          && finfo->sections[r_symndx] == NULL))
                    {
-                     struct elf_link_hash_entry *h;
-
                      h = sym_hashes[r_symndx - extsymoff];
                      while (h->root.type == bfd_link_hash_indirect
                             || h->root.type == bfd_link_hash_warning)
                        h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-                     /* Complain if the definition comes from a
-                        discarded section.  */
-                     sec = h->root.u.def.section;
-                     if ((h->root.type == bfd_link_hash_defined
-                          || h->root.type == bfd_link_hash_defweak)
-                         && elf_discarded_section (sec))
-                       {
-                         if ((o->flags & SEC_DEBUGGING) != 0)
-                           {
-                             BFD_ASSERT (r_symndx != 0);
-                             /* Try to preserve debug information.  */
-                             if (sec->kept_section != NULL
-                                 && sec->size == sec->kept_section->size)
-                               h->root.u.def.section
-                                 = sec->kept_section;
-                             else
-                               memset (rel, 0, sizeof (*rel));
-                           }
-                         else
-                           {
-                             char *r_name
-                               = xstrdup (bfd_archive_filename (o->owner));
-                             finfo->info->callbacks->error_handler
-                               (LD_DEFINITION_IN_DISCARDED_SECTION,
-                                _("`%T' referenced in section `%s' from %s: discarded in section `%s' from %s\n"),
-                                h->root.root.string,
-                                h->root.root.string,
-                                o->name, r_name,
-                                h->root.u.def.section->name,
-                                bfd_archive_filename (h->root.u.def.section->owner));
-                             if (r_name)
-                               free (r_name);
-                           }
-                       }
+                     if (h->root.type != bfd_link_hash_defined
+                         && h->root.type != bfd_link_hash_defweak)
+                       continue;
+
+                     ps = &h->root.u.def.section;
+                     sym_name = h->root.root.string;
                    }
                  else
                    {
-                     sec = finfo->sections[r_symndx];
+                     Elf_Internal_Sym *sym = isymbuf + r_symndx;
+                     ps = &finfo->sections[r_symndx];
+                     sym_name = bfd_elf_local_sym_name (input_bfd, sym);
+                   }
 
-                     if (sec != NULL && elf_discarded_section (sec))
+                 /* Complain if the definition comes from a
+                    discarded section.  */
+                 if ((sec = *ps) != NULL && elf_discarded_section (sec))
+                   {
+                     if ((o->flags & SEC_DEBUGGING) != 0)
                        {
-                         if ((o->flags & SEC_DEBUGGING) != 0)
-                           {
-                             BFD_ASSERT (r_symndx != 0);
-                             /* Try to preserve debug information.  */
-                             if (sec->kept_section != NULL
-                                 && sec->size == sec->kept_section->size)
-                               finfo->sections[r_symndx]
-                                 = sec->kept_section;
-                             else
-                               {
-                                 rel->r_info &= r_type_mask;
-                                 rel->r_addend = 0;
-                               }
-                           }
-                         else
+                         BFD_ASSERT (r_symndx != 0);
+
+                         /* Try to preserve debug information.
+                            FIXME: This is quite broken.  Modifying
+                            the symbol here means we will be changing
+                            all uses of the symbol, not just those in
+                            debug sections.  The only thing that makes
+                            this half reasonable is that debug sections
+                            tend to come after other sections.  Of
+                            course, that doesn't help with globals.
+                            ??? All link-once sections of the same name
+                            ought to define the same set of symbols, so
+                            it would seem that globals ought to always
+                            be defined in the kept section.  */
+                         if (sec->kept_section != NULL
+                             && sec->size == sec->kept_section->size)
                            {
-                             static int count;
-                             int ok;
-                             char *buf;
-
-                             ok = asprintf (&buf, "local symbol %d",
-                                            count++);
-                             if (ok <= 0)
-                               buf = (char *) "local symbol";
-                             finfo->info->callbacks->error_handler
-                               (LD_DEFINITION_IN_DISCARDED_SECTION,
-                                _("`%T' referenced in section `%s': discarded in section `%s' from %s\n"),
-                                buf, buf, o->name, sec->name,
-                                bfd_archive_filename (input_bfd));
-                             if (ok != -1)
-                               free (buf);
+                             *ps = sec->kept_section;
+                             continue;
                            }
                        }
+                     else if (complain)
+                       {
+                         finfo->info->callbacks->error_handler
+                           (LD_DEFINITION_IN_DISCARDED_SECTION,
+                            _("`%T' referenced in section `%s' of %B: "
+                              "defined in discarded section `%s' of %B\n"),
+                            sym_name,
+                            sym_name, o->name, input_bfd,
+                            sec->name, sec->owner);
+                       }
+
+                     /* Remove the symbol reference from the reloc, but
+                        don't kill the reloc completely.  This is so that
+                        a zero value will be written into the section,
+                        which may have non-zero contents put there by the
+                        assembler.  Zero in things like an eh_frame fde
+                        pc_begin allows stack unwinders to recognize the
+                        fde as bogus.  */
+                     rel->r_info &= r_type_mask;
+                     rel->r_addend = 0;
                    }
                }
            }
index 3dacd1c710a1045abd0ce46bacf078f12ba96b93..5b84ee08ee791fd7def684dda8a657543ce84ed4 100644 (file)
@@ -1,3 +1,9 @@
+2004-07-01  Alan Modra  <amodra@bigpond.net.au>
+
+       * ld-discard/extern.d: Update.
+       * ld-discard/start.d: Update.
+       * ld-discard/static.d: Update.
+
 2004-06-30  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR 233
index df4c7d1ceabb006aa0c95db758144e7e82270acc..3409ad44c7a122ddef45846ce35d698d9864ad30 100644 (file)
@@ -1,3 +1,3 @@
 #source: extern.s
 #ld: -T discard.ld
-#error: `data' referenced in section `\.text' from tmpdir/dump0.o: discarded in section `\.data\.exit' from tmpdir/dump0.o
+#error: `data' referenced in section `\.text' of tmpdir/dump0.o: defined in discarded section `\.data\.exit' of tmpdir/dump0.o
index f9885d40f7bd043984bdd1397d7ff328b88d3e66..3f91738c526acceb0be5d751b4b71181815488df 100644 (file)
@@ -1,4 +1,4 @@
 #source: start.s
 #source: exit.s
 #ld: -T discard.ld
-#error: `data' referenced in section `\.text' from tmpdir/dump0.o: discarded in section `\.data\.exit' from tmpdir/dump1.o
+#error: `data' referenced in section `\.text' of tmpdir/dump0.o: defined in discarded section `\.data\.exit' of tmpdir/dump1.o
index 1aa44cdd1e079811e353e6990bc992a0263b8038..98ef02f1b15027385c3c3921c05ecda7b767edc3 100644 (file)
@@ -1,3 +1,3 @@
 #source: static.s
 #ld: -T discard.ld
-#error: `local symbol 0' referenced in section `\.text': discarded in section `\.data\.exit' from tmpdir/dump0.o
+#error: `\.data\.exit' referenced in section `\.text' of tmpdir/dump0.o: defined in discarded section `\.data\.exit' of tmpdir/dump0.o