2016-08-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
[deliverable/binutils-gdb.git] / ld / ldexp.c
index b7b6e6c57c9d0c31fa8d3ca376b652cb8f14f2f3..a560643fb330e014bfd21521b16e2e76261cfe80 100644 (file)
@@ -1,5 +1,5 @@
 /* This module handles expression trees.
-   Copyright (C) 1991-2015 Free Software Foundation, Inc.
+   Copyright (C) 1991-2016 Free Software Foundation, Inc.
    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
 
    This file is part of the GNU Binutils.
@@ -82,7 +82,7 @@ exp_print_token (token_code_type code, int infix_p)
   static const struct
   {
     token_code_type code;
-    const char * name;
+    const char *name;
   }
   table[] =
   {
@@ -441,7 +441,8 @@ fold_binary (etree_type *tree)
            if (!seg->used
                && config.magic_demand_paged
                && (seg->value % config.maxpagesize) != 0)
-             einfo (_("%P: warning: address of `%s' isn't multiple of maximum page size\n"),
+             einfo (_("%P: warning: address of `%s' "
+                      "isn't multiple of maximum page size\n"),
                     segment_name);
            seg->used = TRUE;
            new_rel_from_abs (seg->value);
@@ -848,17 +849,17 @@ fold_name (etree_type *tree)
     case LENGTH:
       {
       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);
-        }
+       {
+         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;
 
@@ -973,7 +974,24 @@ is_align_conditional (const etree_type *tree)
              && is_dot_ne_0 (tree->trinary.cond)
              && is_value (tree->trinary.rhs, 1));
     }
-  return 0;
+  return FALSE;
+}
+
+/* Subroutine of exp_fold_tree_1 for copying a symbol type.  */
+
+static void
+try_copy_symbol_type (struct bfd_link_hash_entry *h, etree_type *src)
+{
+  if (src->type.node_class == etree_name)
+    {
+      struct bfd_link_hash_entry *hsrc;
+
+      hsrc = bfd_link_hash_lookup (link_info.hash, src->name.name,
+                                   FALSE, FALSE, TRUE);
+      if (hsrc)
+       bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
+                                                   hsrc);
+    }
 }
 
 static void
@@ -1109,11 +1127,14 @@ exp_fold_tree_1 (etree_type *tree)
              if (h == NULL
                  || !(h->type == bfd_link_hash_new
                       || h->type == bfd_link_hash_undefined
+                      || h->type == bfd_link_hash_undefweak
                       || h->linker_def))
                {
                  /* Do nothing.  The symbol was never referenced, or
-                    was defined in some object file.  Undefined weak
-                    symbols stay undefined.  */
+                    was defined in some object file.  Note that
+                    undefweak symbols are defined by PROVIDE.  This
+                    is to support glibc use of __rela_iplt_start and
+                    similar weak references.  */
                  break;
                }
            }
@@ -1161,23 +1182,31 @@ exp_fold_tree_1 (etree_type *tree)
              h->type = bfd_link_hash_defined;
              h->u.def.value = expld.result.value;
              h->u.def.section = expld.result.section;
-             h->linker_def = 0;
+             h->linker_def = ! tree->assign.type.lineno;
+             h->ldscript_def = 1;
              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
-                (e.g. a ?: operator with NAMEs in each branch).  */
+                one symbol to another.  Also, handle the case of a foldable
+                ternary conditional with names on either side.  */
              if (tree->assign.src->type.node_class == etree_name)
+               try_copy_symbol_type (h, tree->assign.src);
+             else if (tree->assign.src->type.node_class == etree_trinary)
                {
-                 struct bfd_link_hash_entry *hsrc;
-
-                 hsrc = bfd_link_hash_lookup (link_info.hash,
-                                              tree->assign.src->name.name,
-                                              FALSE, FALSE, TRUE);
-                 if (hsrc)
-                   bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
-                                                   hsrc);
+                 exp_fold_tree_1 (tree->assign.src->trinary.cond);
+                 if (expld.result.valid_p)
+                   {
+                     if (expld.result.value
+                         && tree->assign.src->trinary.lhs->type.node_class
+                            == etree_name)
+                       try_copy_symbol_type (h, tree->assign.src->trinary.lhs);
+
+                     if (!expld.result.value
+                         && tree->assign.src->trinary.rhs->type.node_class
+                            == etree_name)
+                       try_copy_symbol_type (h, tree->assign.src->trinary.rhs);
+                   }
                }
            }
          else if (expld.phase == lang_final_phase_enum)
@@ -1226,80 +1255,55 @@ exp_fold_tree_no_dot (etree_type *tree)
 etree_type *
 exp_binop (int code, etree_type *lhs, etree_type *rhs)
 {
-  etree_type value, *new_e;
-
-  value.type.node_code = code;
-  value.type.filename = lhs->type.filename;
-  value.type.lineno = lhs->type.lineno;
-  value.binary.lhs = lhs;
-  value.binary.rhs = rhs;
-  value.type.node_class = etree_binary;
-  exp_fold_tree_no_dot (&value);
-  if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
-
-  new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
-  memcpy (new_e, &value, sizeof (new_e->binary));
+  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
+
+  new_e->type.node_code = code;
+  new_e->type.filename = lhs->type.filename;
+  new_e->type.lineno = lhs->type.lineno;
+  new_e->binary.lhs = lhs;
+  new_e->binary.rhs = rhs;
+  new_e->type.node_class = etree_binary;
   return new_e;
 }
 
 etree_type *
 exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
 {
-  etree_type value, *new_e;
-
-  value.type.node_code = code;
-  value.type.filename = cond->type.filename;
-  value.type.lineno = cond->type.lineno;
-  value.trinary.lhs = lhs;
-  value.trinary.cond = cond;
-  value.trinary.rhs = rhs;
-  value.type.node_class = etree_trinary;
-  exp_fold_tree_no_dot (&value);
-  if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
-
-  new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
-  memcpy (new_e, &value, sizeof (new_e->trinary));
+  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
+
+  new_e->type.node_code = code;
+  new_e->type.filename = cond->type.filename;
+  new_e->type.lineno = cond->type.lineno;
+  new_e->trinary.lhs = lhs;
+  new_e->trinary.cond = cond;
+  new_e->trinary.rhs = rhs;
+  new_e->type.node_class = etree_trinary;
   return new_e;
 }
 
 etree_type *
 exp_unop (int code, etree_type *child)
 {
-  etree_type value, *new_e;
-
-  value.unary.type.node_code = code;
-  value.unary.type.filename = child->type.filename;
-  value.unary.type.lineno = child->type.lineno;
-  value.unary.child = child;
-  value.unary.type.node_class = etree_unary;
-  exp_fold_tree_no_dot (&value);
-  if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
+  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
 
-  new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
-  memcpy (new_e, &value, sizeof (new_e->unary));
+  new_e->unary.type.node_code = code;
+  new_e->unary.type.filename = child->type.filename;
+  new_e->unary.type.lineno = child->type.lineno;
+  new_e->unary.child = child;
+  new_e->unary.type.node_class = etree_unary;
   return new_e;
 }
 
 etree_type *
 exp_nameop (int code, const char *name)
 {
-  etree_type value, *new_e;
-
-  value.name.type.node_code = code;
-  value.name.type.filename = ldlex_filename ();
-  value.name.type.lineno = lineno;
-  value.name.name = name;
-  value.name.type.node_class = etree_name;
-
-  exp_fold_tree_no_dot (&value);
-  if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
+  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
 
-  new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
-  memcpy (new_e, &value, sizeof (new_e->name));
+  new_e->name.type.node_code = code;
+  new_e->name.type.filename = ldlex_filename ();
+  new_e->name.type.lineno = lineno;
+  new_e->name.name = name;
+  new_e->name.type.node_class = etree_name;
   return new_e;
 
 }
This page took 0.027364 seconds and 4 git commands to generate.