Copying symbol type in ld script assignments
authorAlan Modra <amodra@gmail.com>
Mon, 27 Nov 2017 08:13:03 +0000 (18:43 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 28 Nov 2017 12:26:59 +0000 (22:56 +1030)
There is a call to update_definedness between code that evaluates an
assignment expression value and code that transfers symbol
attributes.  When script assignment expressions contain DEFINED, that
can mean the wrong symbol type is copied.  This patch tracks symbols
read during expression evaluation, rather than examining the
expression and re-evaluating conditionals.  Not only does this
simplify the code, it also means ld can now copy symbol types in more
complex expressions.

An unfortunate side effect of copying symbol type for more complex
expressions affects mmix, which uses
 PROVIDE (Main = DEFINED (Main) ? Main : (DEFINED (_start) ? _start : _start.));
in a default script.  So now _start or _start. symbol type may be
copied, losing the function type specially set up for Main.  This can
be avoided by making bfd_copy_link_hash_symbol_type do nothing for
mmix.

bfd/
* elf64-mmix.c (bfd_elf64_bfd_copy_link_hash_symbol_type): Define.
ld/
* ldexp.h (struct ldexp_control): Add "assign_src".
* ldexp.c (fold_trinary): Save and restore assign_src around
condition evaluation.
(fold_name <NAME>): Set expld.assign_src.
(try_copy_symbol_type): Delete.
(exp_fold_tree_1): Set symbol type using expld.assign_src.

bfd/ChangeLog
bfd/elf64-mmix.c
ld/ChangeLog
ld/ldexp.c
ld/ldexp.h

index abd7c96ac9c7ec57bea9292de0a541f98a05bfba..dc3aa2f0d9dc1149cb63e3498b6b8949b082a7f6 100644 (file)
@@ -1,3 +1,7 @@
+2017-11-28  Alan Modra  <amodra@gmail.com>
+
+       * elf64-mmix.c (bfd_elf64_bfd_copy_link_hash_symbol_type): Define.
+
 2017-11-28  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/22502
index c057d34904c3f3a8b9243299dcf4640be392da80..ae6afc20f1e0d0c8b22b789086afa71b59839505 100644 (file)
@@ -2908,6 +2908,9 @@ mmix_elf_relax_section (bfd *abfd,
 #define elf_backend_omit_section_dynsym \
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 
+#define bfd_elf64_bfd_copy_link_hash_symbol_type \
+  _bfd_generic_copy_link_hash_symbol_type
+
 #define bfd_elf64_bfd_is_local_label_name \
        mmix_elf_is_local_label_name
 
index ed63236e5b0c6d8748432aef099bf9fd58406be7..058318dfabab3710baf2c78b95e168fa54229ae5 100644 (file)
@@ -1,3 +1,12 @@
+2017-11-28  Alan Modra  <amodra@gmail.com>
+
+       * ldexp.h (struct ldexp_control): Add "assign_src".
+       * ldexp.c (fold_trinary): Save and restore assign_src around
+       condition evaluation.
+       (fold_name <NAME>): Set expld.assign_src.
+       (try_copy_symbol_type): Delete.
+       (exp_fold_tree_1): Set symbol type using expld.assign_src.
+
 2017-11-28  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/22502
index 83d9f8f2a7fddf38ac21a1a7f712f92250932b34..33ca289682cd0dc0fe15f2d9b3143f4417546ea7 100644 (file)
@@ -673,7 +673,10 @@ fold_binary (etree_type *tree)
 static void
 fold_trinary (etree_type *tree)
 {
+  struct bfd_link_hash_entry *save = expld.assign_src;
+
   exp_fold_tree_1 (tree->trinary.cond);
+  expld.assign_src = save;
   if (expld.result.valid_p)
     exp_fold_tree_1 (expld.result.value
                     ? tree->trinary.lhs
@@ -790,6 +793,10 @@ fold_name (etree_type *tree)
              if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
                bfd_link_add_undef (link_info.hash, h);
            }
+         if (expld.assign_src == NULL)
+           expld.assign_src = h;
+         else
+           expld.assign_src = (struct bfd_link_hash_entry *) 0 - 1;
        }
       break;
 
@@ -1001,19 +1008,6 @@ is_align_conditional (const etree_type *tree)
   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)
-{
-  struct bfd_link_hash_entry *hsrc;
-
-  hsrc = bfd_link_hash_lookup (link_info.hash, src->name.name,
-                              FALSE, FALSE, TRUE);
-  if (hsrc != NULL)
-    bfd_copy_link_hash_symbol_type (link_info.output_bfd, h, hsrc);
-}
-
 static void
 exp_fold_tree_1 (etree_type *tree)
 {
@@ -1162,6 +1156,7 @@ exp_fold_tree_1 (etree_type *tree)
            }
 
          expld.assign_name = tree->assign.dst;
+         expld.assign_src = NULL;
          exp_fold_tree_1 (tree->assign.src);
          /* expld.assign_name remaining equal to tree->assign.dst
             below indicates the evaluation of tree->assign.src did
@@ -1209,27 +1204,15 @@ exp_fold_tree_1 (etree_type *tree)
              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.  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)
-               {
-                 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);
-                   }
-               }
+             /* Copy the symbol type if this is an expression only
+                referencing a single symbol.  (If the expression
+                contains ternary conditions, ignoring symbols on
+                false branches.)  */
+             if (expld.result.valid_p
+                 && expld.assign_src != NULL
+                 && expld.assign_src != (struct bfd_link_hash_entry *) 0 - 1)
+               bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
+                                               expld.assign_src);
            }
          else if (expld.phase == lang_final_phase_enum)
            {
index 5ff0fa0a1fc6105fd0acacce62ecf82d968b3ec9..189570aaf72a92e4466269f472c27abb8f166383 100644 (file)
@@ -163,6 +163,11 @@ struct ldexp_control {
      does the false branch of a trinary expression.  */
   const char *assign_name;
 
+  /* If evaluating an assignment, the source if it is an expression
+     referencing single etree_name NAME, or a trinary expression where
+     the true branch references a single etree_name NAME.  */
+  struct bfd_link_hash_entry *assign_src;
+
   /* Working results.  */
   etree_value_type result;
   bfd_vma dot;