include/opcode/
[deliverable/binutils-gdb.git] / ld / ldexp.c
index 3bddc813e0d50b8bca8e86a52d0930cbf243ca4e..ae3919b5502a762d13cecd15f4b6d4678928b97e 100644 (file)
@@ -213,10 +213,14 @@ new_rel (bfd_vma value, asection *section)
 static void
 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.result.valid_p = TRUE;
-  expld.result.value = value - expld.section->vma;
+  expld.result.value = value - s->vma;
   expld.result.str = NULL;
-  expld.result.section = expld.section;
+  expld.result.section = s;
 }
 
 static void
@@ -308,7 +312,7 @@ fold_binary (etree_type *tree)
       /* Check to see if the user has overridden the default
         value.  */
       segment_name = tree->binary.rhs->name.name;
-      for (seg = segments; seg; seg = seg->next) 
+      for (seg = segments; seg; seg = seg->next)
        if (strcmp (seg->name, segment_name) == 0)
          {
            if (!seg->used
@@ -568,6 +572,9 @@ fold_name (etree_type *tree)
       break;
 
     case NAME:
+      if (expld.assign_name != NULL
+         && strcmp (expld.assign_name, tree->name.name) == 0)
+       expld.assign_name = NULL;
       if (expld.phase == lang_first_phase_enum)
        ;
       else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
@@ -681,7 +688,7 @@ fold_name (etree_type *tree)
                       tree, tree->name.name);
              new_number (0);
            }
-         else if (os->processed_vma)
+         else if (os->bfd_section != NULL)
            {
              bfd_vma val;
 
@@ -690,20 +697,22 @@ fold_name (etree_type *tree)
                       / bfd_octets_per_byte (link_info.output_bfd));
              else
                val = (bfd_vma)1 << os->bfd_section->alignment_power;
-             
+
              new_number (val);
            }
+         else
+           new_number (0);
        }
       break;
 
     case LENGTH:
       {
         lang_memory_region_type *mem;
-        
-        mem = lang_memory_region_lookup (tree->name.name, FALSE);  
-        if (mem != NULL) 
+
+        mem = lang_memory_region_lookup (tree->name.name, FALSE);
+        if (mem != NULL)
           new_number (mem->length);
-        else          
+        else
           einfo (_("%F%S: undefined MEMORY region `%s'"
                   " referenced in expression\n"),
                 tree, tree->name.name);
@@ -714,11 +723,11 @@ fold_name (etree_type *tree)
       if (expld.phase != lang_first_phase_enum)
        {
          lang_memory_region_type *mem;
-        
-         mem = lang_memory_region_lookup (tree->name.name, FALSE);  
-         if (mem != NULL) 
+
+         mem = lang_memory_region_lookup (tree->name.name, FALSE);
+         if (mem != NULL)
            new_rel_from_abs (mem->origin);
-         else          
+         else
            einfo (_("%F%S: undefined MEMORY region `%s'"
                     " referenced in expression\n"),
                   tree, tree->name.name);
@@ -846,8 +855,6 @@ exp_fold_tree_1 (etree_type *tree)
        }
       else
        {
-         etree_type *name;
-
          struct bfd_link_hash_entry *h = NULL;
 
          if (tree->type.node_class == etree_provide)
@@ -865,28 +872,23 @@ exp_fold_tree_1 (etree_type *tree)
                }
            }
 
-         name = tree->assign.src;
-         if (name->type.node_class == etree_trinary)
-           {
-             exp_fold_tree_1 (name->trinary.cond);
-             if (expld.result.valid_p)
-               name = (expld.result.value
-                       ? name->trinary.lhs : name->trinary.rhs);
-           }
-
-         if (name->type.node_class == etree_name
-             && name->type.node_code == NAME
-             && strcmp (tree->assign.dst, name->name.name) == 0)
-           /* Leave it alone.  Do not replace a symbol with its own
-              output address, in case there is another section sizing
-              pass.  Folding does not preserve input sections.  */
-           break;
-
+         expld.assign_name = tree->assign.dst;
          exp_fold_tree_1 (tree->assign.src);
-         if (expld.result.valid_p
+         /* expld.assign_name remaining equal to tree->assign.dst
+            below indicates the evaluation of tree->assign.src did
+            not use the value of tree->assign.dst.  We don't allow
+            self assignment until the final phase for two reasons:
+            1) Expressions are evaluated multiple times.  With
+            relaxation, the number of times may vary.
+            2) Section relative symbol values cannot be correctly
+            converted to absolute values, as is required by many
+            expressions, until final section sizing is complete.  */
+         if ((expld.result.valid_p
+              && (expld.phase == lang_final_phase_enum
+                  || expld.assign_name != NULL))
              || (expld.phase <= lang_mark_phase_enum
                  && tree->type.node_class == etree_assign
-                 && tree->assign.hidden))
+                 && tree->assign.defsym))
            {
              if (h == NULL)
                {
@@ -931,6 +933,7 @@ exp_fold_tree_1 (etree_type *tree)
                  && h->type == bfd_link_hash_new)
                h->type = bfd_link_hash_undefined;
            }
+         expld.assign_name = NULL;
        }
       break;
 
@@ -1048,6 +1051,7 @@ static etree_type *
 exp_assop (const char *dst,
           etree_type *src,
           enum node_tree_enum class,
+          bfd_boolean defsym,
           bfd_boolean hidden)
 {
   etree_type *n;
@@ -1059,20 +1063,25 @@ exp_assop (const char *dst,
   n->assign.type.node_class = class;
   n->assign.src = src;
   n->assign.dst = dst;
+  n->assign.defsym = defsym;
   n->assign.hidden = hidden;
   return n;
 }
 
+/* Handle linker script assignments and HIDDEN.  */
+
 etree_type *
-exp_assign (const char *dst, etree_type *src)
+exp_assign (const char *dst, etree_type *src, bfd_boolean hidden)
 {
-  return exp_assop (dst, src, etree_assign, FALSE);
+  return exp_assop (dst, src, etree_assign, FALSE, hidden);
 }
 
+/* Handle --defsym command-line option.  */
+
 etree_type *
 exp_defsym (const char *dst, etree_type *src)
 {
-  return exp_assop (dst, src, etree_assign, TRUE);
+  return exp_assop (dst, src, etree_assign, TRUE, FALSE);
 }
 
 /* Handle PROVIDE.  */
@@ -1080,7 +1089,7 @@ exp_defsym (const char *dst, etree_type *src)
 etree_type *
 exp_provide (const char *dst, etree_type *src, bfd_boolean hidden)
 {
-  return exp_assop (dst, src, etree_provide, hidden);
+  return exp_assop (dst, src, etree_provide, FALSE, hidden);
 }
 
 /* Handle ASSERT.  */
This page took 0.026529 seconds and 4 git commands to generate.