PR gdb/18021 - defend against "static virtual" methods
[deliverable/binutils-gdb.git] / ld / ldexp.c
index b4af893c86e083bab4753e3889f50c65d827b3a1..ac66cc02aef23556cf6b3d8b8c104498a4026d21 100644 (file)
@@ -1,5 +1,5 @@
 /* This module handles expression trees.
-   Copyright (C) 1991-2014 Free Software Foundation, Inc.
+   Copyright (C) 1991-2015 Free Software Foundation, Inc.
    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
 
    This file is part of the GNU Binutils.
@@ -291,11 +291,13 @@ symbol_defined (const char *name)
          bfd_hash_lookup (&definedness_table, name, FALSE, FALSE));
 }
 
-/* Update the definedness state of NAME.  */
+/* Update the definedness state of NAME.  Return FALSE if script symbol
+   is multiply defining a strong symbol in an object.  */
 
-static void
+static bfd_boolean
 update_definedness (const char *name, struct bfd_link_hash_entry *h)
 {
+  bfd_boolean ret;
   struct definedness_hash_entry *defentry
     = (struct definedness_hash_entry *)
     bfd_hash_lookup (&definedness_table, name, TRUE, FALSE);
@@ -305,14 +307,22 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
 
   /* If the symbol was already defined, and not by a script, then it
      must be defined by an object file or by the linker target code.  */
+  ret = TRUE;
   if (!defentry->by_script
       && (h->type == bfd_link_hash_defined
          || h->type == bfd_link_hash_defweak
          || h->type == bfd_link_hash_common))
-    defentry->by_object = 1;
+    {
+      defentry->by_object = 1;
+      if (h->type == bfd_link_hash_defined
+         && h->u.def.section->output_section != NULL
+         && !h->linker_def)
+       ret = FALSE;
+    }
 
   defentry->by_script = 1;
   defentry->iteration = lang_statement_iteration;
+  return ret;
 }
 
 static void
@@ -818,15 +828,18 @@ fold_name (etree_type *tree)
 
     case LENGTH:
       {
-        lang_memory_region_type *mem;
-
-        mem = lang_memory_region_lookup (tree->name.name, FALSE);
-        if (mem != NULL)
-          new_number (mem->length);
-        else
-          einfo (_("%F%S: undefined MEMORY region `%s'"
-                  " referenced in expression\n"),
-                tree, tree->name.name);
+      if (expld.phase != lang_first_phase_enum)
+        {
+          lang_memory_region_type *mem;
+
+          mem = lang_memory_region_lookup (tree->name.name, FALSE);
+          if (mem != NULL)
+            new_number (mem->length);
+          else
+            einfo (_("%F%S: undefined MEMORY region `%s'"
+             " referenced in expression\n"),
+           tree, tree->name.name);
+        }
       }
       break;
 
@@ -1108,19 +1121,27 @@ exp_fold_tree_1 (etree_type *tree)
                           tree->assign.dst);
                }
 
-             /* FIXME: Should we worry if the symbol is already
-                defined?  */
-             update_definedness (tree->assign.dst, h);
-             h->type = bfd_link_hash_defined;
-             h->u.def.value = expld.result.value;
              if (expld.result.section == NULL)
                expld.result.section = expld.section;
+             if (!update_definedness (tree->assign.dst, h) && 0)
+               {
+                 /* Symbol was already defined.  For now this error
+                    is disabled because it causes failures in the ld
+                    testsuite: ld-elf/var1, ld-scripts/defined5, and
+                    ld-scripts/pr14962.  Some of these no doubt
+                    reflect scripts used in the wild.  */
+                 (*link_info.callbacks->multiple_definition)
+                   (&link_info, h, link_info.output_bfd,
+                    expld.result.section, expld.result.value);
+               }
+             h->type = bfd_link_hash_defined;
+             h->u.def.value = expld.result.value;
              h->u.def.section = expld.result.section;
              if (tree->type.node_class == etree_provide)
                tree->type.node_class = etree_provided;
 
              /* Copy the symbol type if this is a simple assignment of
-                one symbol to another.  This could be more general
+                one symbol to another.  This could be more general
                 (e.g. a ?: operator with NAMEs in each branch).  */
              if (tree->assign.src->type.node_class == etree_name)
                {
This page took 0.024416 seconds and 4 git commands to generate.