Add readahead cache to gdb's vFile:pread
[binutils-gdb.git] / ld / ldexp.c
index 28289338decbde86ad356ff980835c084696a717..1140881015dd15e5fda34b702d9ffb3f351c4513 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);
@@ -304,15 +306,23 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
     einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name);
 
   /* If the symbol was already defined, and not by a script, then it
-     must be defined by an object file.  */
+     must be defined by an object file or by the linker target code.  */
+  ret = TRUE;
   if (!defentry->by_script
-      && h->type != bfd_link_hash_undefined
-      && h->type != bfd_link_hash_common
-      && h->type != bfd_link_hash_new)
-    defentry->by_object = 1;
+      && (h->type == bfd_link_hash_defined
+         || h->type == bfd_link_hash_defweak
+         || h->type == bfd_link_hash_common))
+    {
+      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
@@ -565,7 +575,6 @@ fold_binary (etree_type *tree)
                  else if (expld.dataseg.phase == exp_dataseg_none)
                    {
                      expld.dataseg.phase = exp_dataseg_align_seen;
-                     expld.dataseg.min_base = expld.dot;
                      expld.dataseg.base = expld.result.value;
                      expld.dataseg.pagesize = commonpage;
                      expld.dataseg.maxpagesize = maxpage;
@@ -578,7 +587,10 @@ fold_binary (etree_type *tree)
          break;
 
        case DATA_SEGMENT_RELRO_END:
+         /* Operands swapped!  DATA_SEGMENT_RELRO_END(offset,exp)
+            has offset in expld.result and exp in lhs.  */
          expld.dataseg.relro = exp_dataseg_relro_end;
+         expld.dataseg.relro_offset = expld.result.value;
          if (expld.phase == lang_first_phase_enum
              || expld.section != bfd_abs_section_ptr)
            expld.result.valid_p = FALSE;
@@ -818,15 +830,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;
 
@@ -862,7 +877,7 @@ fold_name (etree_type *tree)
 }
 
 /* Return true if TREE is '.'.  */
+
 static bfd_boolean
 is_dot (const etree_type *tree)
 {
@@ -1011,7 +1026,12 @@ exp_fold_tree_1 (etree_type *tree)
              /* If we are assigning to dot inside an output section
                 arrange to keep the section, except for certain
                 expressions that evaluate to zero.  We ignore . = 0,
-                . = . + 0, and . = ALIGN (. != 0 ? expr : 1).  */
+                . = . + 0, and . = ALIGN (. != 0 ? expr : 1).
+                We can't ignore all expressions that evaluate to zero
+                because an otherwise empty section might have padding
+                added by an alignment expression that changes with
+                relaxation.  Such a section might have zero size
+                before relaxation and so be stripped incorrectly.  */
              if (expld.phase == lang_mark_phase_enum
                  && expld.section != bfd_abs_section_ptr
                  && !(expld.result.valid_p
@@ -1070,15 +1090,13 @@ exp_fold_tree_1 (etree_type *tree)
              h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
                                        FALSE, FALSE, TRUE);
              if (h == NULL
-                 || (h->type != bfd_link_hash_new
-                     && h->type != bfd_link_hash_undefined
-                     && h->type != bfd_link_hash_common
-                     && !(h->type == bfd_link_hash_defined
-                          && (h->u.def.section->flags
-                              & SEC_LINKER_CREATED) != 0)))
+                 || !(h->type == bfd_link_hash_new
+                      || h->type == bfd_link_hash_undefined
+                      || h->linker_def))
                {
-                 /* Do nothing.  The symbol was never referenced, or was
-                    defined by some object.  */
+                 /* Do nothing.  The symbol was never referenced, or
+                    was defined in some object file.  Undefined weak
+                    symbols stay undefined.  */
                  break;
                }
            }
@@ -1110,19 +1128,28 @@ 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;
+             h->linker_def = 0;
              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)
                {