Separate the new FP16 instructions backported from Armv8.4-a to Armv8.2-a into a...
[deliverable/binutils-gdb.git] / ld / ldexp.c
index f2c8620a4651aa2604b66291513db4c69697ad76..83d9f8f2a7fddf38ac21a1a7f712f92250932b34 100644 (file)
@@ -1,5 +1,5 @@
 /* This module handles expression trees.
-   Copyright (C) 1991-2015 Free Software Foundation, Inc.
+   Copyright (C) 1991-2017 Free Software Foundation, Inc.
    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
 
    This file is part of the GNU Binutils.
@@ -49,13 +49,25 @@ segment_type *segments;
 struct ldexp_control expld;
 
 /* This structure records symbols for which we need to keep track of
-   definedness for use in the DEFINED () test.  */
+   definedness for use in the DEFINED () test.  It is also used in
+   making absolute symbols section relative late in the link.   */
 
 struct definedness_hash_entry
 {
   struct bfd_hash_entry root;
+
+  /* If this symbol was assigned from "dot" outside of an output
+     section statement, the section we'd like it relative to.  */
+  asection *final_sec;
+
+  /* Symbol was defined by an object file.  */
   unsigned int by_object : 1;
+
+  /* Symbols was defined by a script.  */
   unsigned int by_script : 1;
+
+  /* Low bit of iteration count.  Symbols with matching iteration have
+     been defined in this pass over the script.  */
   unsigned int iteration : 1;
 };
 
@@ -70,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[] =
   {
@@ -174,6 +186,7 @@ make_abs (void)
   if (expld.result.section != NULL)
     expld.result.value += expld.result.section->vma;
   expld.result.section = bfd_abs_section_ptr;
+  expld.rel_from_abs = FALSE;
 }
 
 static void
@@ -249,8 +262,7 @@ new_rel_from_abs (bfd_vma value)
 {
   asection *s = expld.section;
 
-  if (s == bfd_abs_section_ptr && expld.phase == lang_final_phase_enum)
-    s = section_for_dot ();
+  expld.rel_from_abs = TRUE;
   expld.result.valid_p = TRUE;
   expld.result.value = value - s->vma;
   expld.result.str = NULL;
@@ -322,9 +334,38 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
 
   defentry->by_script = 1;
   defentry->iteration = lang_statement_iteration;
+  defentry->final_sec = bfd_abs_section_ptr;
+  if (expld.phase == lang_final_phase_enum
+      && expld.rel_from_abs
+      && expld.result.section == bfd_abs_section_ptr)
+    defentry->final_sec = section_for_dot ();
   return ret;
 }
 
+static void
+fold_segment_end (seg_align_type *seg)
+{
+  if (expld.phase == lang_first_phase_enum
+      || expld.section != bfd_abs_section_ptr)
+    {
+      expld.result.valid_p = FALSE;
+    }
+  else if (seg->phase == exp_seg_align_seen
+          || seg->phase == exp_seg_relro_seen)
+    {
+      seg->phase = exp_seg_end_seen;
+      seg->end = expld.result.value;
+    }
+  else if (seg->phase == exp_seg_done
+          || seg->phase == exp_seg_adjust
+          || seg->phase == exp_seg_relro_adjust)
+    {
+      /* OK.  */
+    }
+  else
+    expld.result.valid_p = FALSE;
+}
+
 static void
 fold_unary (etree_type *tree)
 {
@@ -372,32 +413,118 @@ fold_unary (etree_type *tree)
          break;
 
        case DATA_SEGMENT_END:
-         if (expld.phase == lang_first_phase_enum
-             || expld.section != bfd_abs_section_ptr)
-           {
-             expld.result.valid_p = FALSE;
-           }
-         else if (expld.dataseg.phase == exp_dataseg_align_seen
-                  || expld.dataseg.phase == exp_dataseg_relro_seen)
+         fold_segment_end (&expld.dataseg);
+         break;
+
+       default:
+         FAIL ();
+         break;
+       }
+    }
+}
+
+/* Arithmetic operators, bitwise AND, bitwise OR and XOR keep the
+   section of one of their operands only when the other operand is a
+   plain number.  Losing the section when operating on two symbols,
+   ie. a result of a plain number, is required for subtraction and
+   XOR.  It's justifiable for the other operations on the grounds that
+   adding, multiplying etc. two section relative values does not
+   really make sense unless they are just treated as numbers.
+   The same argument could be made for many expressions involving one
+   symbol and a number.  For example, "1 << x" and "100 / x" probably
+   should not be given the section of x.  The trouble is that if we
+   fuss about such things the rules become complex and it is onerous
+   to document ld expression evaluation.  */
+static void
+arith_result_section (const etree_value_type *lhs)
+{
+  if (expld.result.section == lhs->section)
+    {
+      if (expld.section == bfd_abs_section_ptr
+         && !config.sane_expr)
+       /* Duplicate the insanity in exp_fold_tree_1 case etree_value.  */
+       expld.result.section = bfd_abs_section_ptr;
+      else
+       expld.result.section = NULL;
+    }
+}
+
+static void
+fold_segment_align (seg_align_type *seg, etree_value_type *lhs)
+{
+  seg->relro = exp_seg_relro_start;
+  if (expld.phase == lang_first_phase_enum
+      || expld.section != bfd_abs_section_ptr)
+    expld.result.valid_p = FALSE;
+  else
+    {
+      bfd_vma maxpage = lhs->value;
+      bfd_vma commonpage = expld.result.value;
+
+      expld.result.value = align_n (expld.dot, maxpage);
+      if (seg->phase == exp_seg_relro_adjust)
+       expld.result.value = seg->base;
+      else if (seg->phase == exp_seg_adjust)
+       {
+         if (commonpage < maxpage)
+           expld.result.value += ((expld.dot + commonpage - 1)
+                                  & (maxpage - commonpage));
+       }
+      else
+       {
+         expld.result.value += expld.dot & (maxpage - 1);
+         if (seg->phase == exp_seg_done)
            {
-             expld.dataseg.phase = exp_dataseg_end_seen;
-             expld.dataseg.end = expld.result.value;
+             /* OK.  */
            }
-         else if (expld.dataseg.phase == exp_dataseg_done
-                  || expld.dataseg.phase == exp_dataseg_adjust
-                  || expld.dataseg.phase == exp_dataseg_relro_adjust)
+         else if (seg->phase == exp_seg_none)
            {
-             /* OK.  */
+             seg->phase = exp_seg_align_seen;
+             seg->base = expld.result.value;
+             seg->pagesize = commonpage;
+             seg->maxpagesize = maxpage;
+             seg->relro_end = 0;
            }
          else
            expld.result.valid_p = FALSE;
-         break;
+       }
+    }
+}
 
-       default:
-         FAIL ();
-         break;
+static void
+fold_segment_relro_end (seg_align_type *seg, etree_value_type *lhs)
+{
+  /* Operands swapped!  XXX_SEGMENT_RELRO_END(offset,exp) has offset
+     in expld.result and exp in lhs.  */
+  seg->relro = exp_seg_relro_end;
+  seg->relro_offset = expld.result.value;
+  if (expld.phase == lang_first_phase_enum
+      || expld.section != bfd_abs_section_ptr)
+    expld.result.valid_p = FALSE;
+  else if (seg->phase == exp_seg_align_seen
+          || seg->phase == exp_seg_adjust
+          || seg->phase == exp_seg_relro_adjust
+          || seg->phase == exp_seg_done)
+    {
+      if (seg->phase == exp_seg_align_seen
+         || seg->phase == exp_seg_relro_adjust)
+       seg->relro_end = lhs->value + expld.result.value;
+
+      if (seg->phase == exp_seg_relro_adjust
+         && (seg->relro_end & (seg->pagesize - 1)))
+       {
+         seg->relro_end += seg->pagesize - 1;
+         seg->relro_end &= ~(seg->pagesize - 1);
+         expld.result.value = seg->relro_end - expld.result.value;
        }
+      else
+       expld.result.value = lhs->value;
+
+      if (seg->phase == exp_seg_align_seen)
+       seg->phase = exp_seg_relro_seen;
     }
+  else
+    expld.result.valid_p = FALSE;
 }
 
 static void
@@ -424,7 +551,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);
@@ -465,26 +593,10 @@ fold_binary (etree_type *tree)
 
       switch (tree->type.node_code)
        {
-         /* Arithmetic operators, bitwise AND, bitwise OR and XOR
-            keep the section of one of their operands only when the
-            other operand is a plain number.  Losing the section when
-            operating on two symbols, ie. a result of a plain number,
-            is required for subtraction and XOR.  It's justifiable
-            for the other operations on the grounds that adding,
-            multiplying etc. two section relative values does not
-            really make sense unless they are just treated as
-            numbers.
-            The same argument could be made for many expressions
-            involving one symbol and a number.  For example,
-            "1 << x" and "100 / x" probably should not be given the
-            section of x.  The trouble is that if we fuss about such
-            things the rules become complex and it is onerous to
-            document ld expression evaluation.  */
 #define BOP(x, y) \
        case x:                                                 \
          expld.result.value = lhs.value y expld.result.value;  \
-         if (expld.result.section == lhs.section)              \
-           expld.result.section = NULL;                        \
+         arith_result_section (&lhs);                          \
          break;
 
          /* Comparison operators, logical AND, and logical OR always
@@ -518,8 +630,7 @@ fold_binary (etree_type *tree)
                                  % (bfd_signed_vma) expld.result.value);
          else if (expld.phase != lang_mark_phase_enum)
            einfo (_("%F%S %% by zero\n"), tree->binary.rhs);
-         if (expld.result.section == lhs.section)
-           expld.result.section = NULL;
+         arith_result_section (&lhs);
          break;
 
        case '/':
@@ -528,8 +639,7 @@ fold_binary (etree_type *tree)
                                  / (bfd_signed_vma) expld.result.value);
          else if (expld.phase != lang_mark_phase_enum)
            einfo (_("%F%S / by zero\n"), tree->binary.rhs);
-         if (expld.result.section == lhs.section)
-           expld.result.section = NULL;
+         arith_result_section (&lhs);
          break;
 
        case MAX_K:
@@ -547,77 +657,11 @@ fold_binary (etree_type *tree)
          break;
 
        case DATA_SEGMENT_ALIGN:
-         expld.dataseg.relro = exp_dataseg_relro_start;
-         if (expld.phase == lang_first_phase_enum
-             || expld.section != bfd_abs_section_ptr)
-           expld.result.valid_p = FALSE;
-         else
-           {
-             bfd_vma maxpage = lhs.value;
-             bfd_vma commonpage = expld.result.value;
-
-             expld.result.value = align_n (expld.dot, maxpage);
-             if (expld.dataseg.phase == exp_dataseg_relro_adjust)
-               expld.result.value = expld.dataseg.base;
-             else if (expld.dataseg.phase == exp_dataseg_adjust)
-               {
-                 if (commonpage < maxpage)
-                   expld.result.value += ((expld.dot + commonpage - 1)
-                                          & (maxpage - commonpage));
-               }
-             else
-               {
-                 expld.result.value += expld.dot & (maxpage - 1);
-                 if (expld.dataseg.phase == exp_dataseg_done)
-                   {
-                     /* OK.  */
-                   }
-                 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;
-                     expld.dataseg.relro_end = 0;
-                   }
-                 else
-                   expld.result.valid_p = FALSE;
-               }
-           }
+         fold_segment_align (&expld.dataseg, &lhs);
          break;
 
        case DATA_SEGMENT_RELRO_END:
-         expld.dataseg.relro = exp_dataseg_relro_end;
-         if (expld.phase == lang_first_phase_enum
-             || expld.section != bfd_abs_section_ptr)
-           expld.result.valid_p = FALSE;
-         else if (expld.dataseg.phase == exp_dataseg_align_seen
-                  || expld.dataseg.phase == exp_dataseg_adjust
-                  || expld.dataseg.phase == exp_dataseg_relro_adjust
-                  || expld.dataseg.phase == exp_dataseg_done)
-           {
-             if (expld.dataseg.phase == exp_dataseg_align_seen
-                 || expld.dataseg.phase == exp_dataseg_relro_adjust)
-               expld.dataseg.relro_end = lhs.value + expld.result.value;
-
-             if (expld.dataseg.phase == exp_dataseg_relro_adjust
-                 && (expld.dataseg.relro_end
-                     & (expld.dataseg.pagesize - 1)))
-               {
-                 expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
-                 expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
-                 expld.result.value = (expld.dataseg.relro_end
-                                       - expld.result.value);
-               }
-             else
-               expld.result.value = lhs.value;
-
-             if (expld.dataseg.phase == exp_dataseg_align_seen)
-               expld.dataseg.phase = exp_dataseg_relro_seen;
-           }
-         else
-           expld.result.valid_p = FALSE;
+         fold_segment_relro_end (&expld.dataseg, &lhs);
          break;
 
        default:
@@ -828,15 +872,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;
 
@@ -872,7 +919,7 @@ fold_name (etree_type *tree)
 }
 
 /* Return true if TREE is '.'.  */
+
 static bfd_boolean
 is_dot (const etree_type *tree)
 {
@@ -951,7 +998,20 @@ 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)
+{
+  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
@@ -1021,9 +1081,15 @@ 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.section != bfd_und_section_ptr
                  && !(expld.result.valid_p
                       && expld.result.value == 0
                       && (is_value (tree->assign.src, 0)
@@ -1032,7 +1098,8 @@ exp_fold_tree_1 (etree_type *tree)
                           || is_align_conditional (tree->assign.src))))
                expld.section->flags |= SEC_KEEP;
 
-             if (!expld.result.valid_p)
+             if (!expld.result.valid_p
+                 || expld.section == bfd_und_section_ptr)
                {
                  if (expld.phase != lang_mark_phase_enum)
                    einfo (_("%F%S invalid assignment to"
@@ -1082,11 +1149,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;
                }
            }
@@ -1134,22 +1204,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 = ! 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)
@@ -1178,6 +1257,7 @@ exp_fold_tree_1 (etree_type *tree)
 void
 exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
 {
+  expld.rel_from_abs = FALSE;
   expld.dot = *dotp;
   expld.dotp = dotp;
   expld.section = current_section;
@@ -1187,89 +1267,96 @@ exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
 void
 exp_fold_tree_no_dot (etree_type *tree)
 {
+  expld.rel_from_abs = FALSE;
   expld.dot = 0;
   expld.dotp = NULL;
   expld.section = bfd_abs_section_ptr;
   exp_fold_tree_1 (tree);
 }
 
-etree_type *
-exp_binop (int code, etree_type *lhs, etree_type *rhs)
+static void
+exp_value_fold (etree_type *tree)
 {
-  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);
+  exp_fold_tree_no_dot (tree);
   if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
+    {
+      tree->type.node_code = INT;
+      tree->value.value = expld.result.value;
+      tree->value.str = NULL;
+      tree->type.node_class = etree_value;
+    }
+}
 
-  new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
-  memcpy (new_e, &value, sizeof (new_e->binary));
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+etree_type *
+exp_binop (int code, etree_type *lhs, etree_type *rhs)
+{
+  etree_type *new_e = (etree_type *) stat_alloc (MAX (sizeof (new_e->binary),
+                                                     sizeof (new_e->value)));
+  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;
+  if (lhs->type.node_class == etree_value
+      && rhs->type.node_class == etree_value
+      && code != ALIGN_K
+      && code != DATA_SEGMENT_ALIGN
+      && code != DATA_SEGMENT_RELRO_END)
+    exp_value_fold (new_e);
   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 (MAX (sizeof (new_e->trinary),
+                                                     sizeof (new_e->value)));
+  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;
+  if (cond->type.node_class == etree_value
+      && lhs->type.node_class == etree_value
+      && rhs->type.node_class == etree_value)
+    exp_value_fold (new_e);
   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);
-
-  new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
-  memcpy (new_e, &value, sizeof (new_e->unary));
+  etree_type *new_e = (etree_type *) stat_alloc (MAX (sizeof (new_e->unary),
+                                                     sizeof (new_e->value)));
+  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;
+  if (child->type.node_class == etree_value
+      && code != ALIGN_K
+      && code != ABSOLUTE
+      && code != NEXT
+      && code != DATA_SEGMENT_END)
+    exp_value_fold (new_e);
   return new_e;
 }
 
 etree_type *
 exp_nameop (int code, const char *name)
 {
-  etree_type value, *new_e;
+  etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
 
-  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);
-
-  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;
 
 }
@@ -1570,6 +1657,36 @@ ldexp_init (void)
     einfo (_("%P%F: can not create hash table: %E\n"));
 }
 
+/* Convert absolute symbols defined by a script from "dot" (also
+   SEGMENT_START or ORIGIN) outside of an output section statement,
+   to section relative.  */
+
+static bfd_boolean
+set_sym_sections (struct bfd_hash_entry *bh, void *inf ATTRIBUTE_UNUSED)
+{
+  struct definedness_hash_entry *def = (struct definedness_hash_entry *) bh;
+  if (def->final_sec != bfd_abs_section_ptr)
+    {
+      struct bfd_link_hash_entry *h;
+      h = bfd_link_hash_lookup (link_info.hash, bh->string,
+                               FALSE, FALSE, TRUE);
+      if (h != NULL
+         && h->type == bfd_link_hash_defined
+         && h->u.def.section == bfd_abs_section_ptr)
+       {
+         h->u.def.value -= def->final_sec->vma;
+         h->u.def.section = def->final_sec;
+       }
+    }
+  return TRUE;
+}
+
+void
+ldexp_finalize_syms (void)
+{
+  bfd_hash_traverse (&definedness_table, set_sym_sections, NULL);
+}
+
 void
 ldexp_finish (void)
 {
This page took 0.044163 seconds and 4 git commands to generate.