This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ld: fix ABSOLUTE for general expressions


Hello,

it appears that ABSOLUTE(x) doesn't generate an absolute value when X is not a symbol, it looks like it works only for symbols.
See the testcase for an example.

I fixed that issue by defining a new node ABSINT, which is like INT except it is an absolute value.

No regression on powerpc-elf.

A very different way to fix this issue: allow only ABSOLUTE on symbols. Might even make the definition of ABSOLUTE clearer.  What is the meaning of ABSOLUTE (a + b) ? 

Tristan.

ld/
	* ldgram.y (ABSINT): Declare.
	Adjust calls to exp_intop.
	* ldexp.h (exp_intop): Add IS_ABS argument.
	* ldexp.c (exp_intop): Likewise.
	(make_int): New function to factorize code.
	(exp_fold_tree_1): Handle ABSINT node.
	(exp_trinop, exp_unop, exp_nameop, exp_binop): Call make_int.
	* ldlang.c (lang_insert_orphan, lang_size_sections_1)
	(ldlang_place_orphan): Adjust calls to exp_intop.
	* lexsup.c (set_section_start, set_segment_start): Ditto.
	* ldctor.c (ldctor_build_sets): Ditto.
	* testsuite/ld-scripts/absolute1.s: New test.
	* testsuite/ld-scripts/absolute1.d: New test.
	* testsuite/ld-scripts/absolute1.t: New test.
	* testsuite/ld-scripts/expr.exp: Run new test.

diff --git a/ld/ldctor.c b/ld/ldctor.c
index 2075ad3..3aff582 100644
--- a/ld/ldctor.c
+++ b/ld/ldctor.c
@@ -319,12 +319,12 @@ ldctor_build_sets (void)
 
       lang_add_assignment (exp_assign (".",
 				       exp_unop (ALIGN_K,
-						 exp_intop (reloc_size)),
+						 exp_intop (reloc_size, FALSE)),
 				       FALSE));
       lang_add_assignment (exp_assign (p->h->root.string,
 				       exp_nameop (NAME, "."),
 				       FALSE));
-      lang_add_data (size, exp_intop (p->count));
+      lang_add_data (size, exp_intop (p->count, FALSE));
 
       for (e = p->elements; e != NULL; e = e->next)
 	{
@@ -364,12 +364,12 @@ ldctor_build_sets (void)
 
 	  if (bfd_link_relocatable (&link_info))
 	    lang_add_reloc (p->reloc, howto, e->section, e->name,
-			    exp_intop (e->value));
+			    exp_intop (e->value, FALSE));
 	  else
 	    lang_add_data (size, exp_relop (e->section, e->value));
 	}
 
-      lang_add_data (size, exp_intop (0));
+      lang_add_data (size, exp_intop (0, FALSE));
     }
 
   pop_stat_ptr ();
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 68c4bc5..5913dc5 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -199,10 +199,10 @@ new_abs (bfd_vma value)
 }
 
 etree_type *
-exp_intop (bfd_vma value)
+exp_intop (bfd_vma value, bfd_boolean is_abs)
 {
   etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
-  new_e->type.node_code = INT;
+  new_e->type.node_code = is_abs ? ABSINT : INT;
   new_e->type.filename = ldlex_filename ();
   new_e->type.lineno = lineno;
   new_e->value.value = value;
@@ -211,6 +211,13 @@ exp_intop (bfd_vma value)
   return new_e;
 }
 
+static etree_type *
+make_int (void)
+{
+  return exp_intop (expld.result.value,
+		    expld.result.section == bfd_abs_section_ptr);
+}
+
 etree_type *
 exp_bigintop (bfd_vma value, char *str)
 {
@@ -1006,8 +1013,8 @@ exp_fold_tree_1 (etree_type *tree)
   switch (tree->type.node_class)
     {
     case etree_value:
-      if (expld.section == bfd_abs_section_ptr
-	  && !config.sane_expr)
+      if (tree->type.node_code == ABSINT
+	  || (expld.section == bfd_abs_section_ptr && !config.sane_expr))
 	new_abs (tree->value.value);
       else
 	new_number (tree->value.value);
@@ -1265,7 +1272,7 @@ exp_binop (int code, etree_type *lhs, etree_type *rhs)
   value.type.node_class = etree_binary;
   exp_fold_tree_no_dot (&value);
   if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
+    return make_int ();
 
   new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
   memcpy (new_e, &value, sizeof (new_e->binary));
@@ -1286,7 +1293,7 @@ exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
   value.type.node_class = etree_trinary;
   exp_fold_tree_no_dot (&value);
   if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
+    return make_int ();
 
   new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
   memcpy (new_e, &value, sizeof (new_e->trinary));
@@ -1305,7 +1312,7 @@ exp_unop (int code, etree_type *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);
+    return make_int ();
 
   new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
   memcpy (new_e, &value, sizeof (new_e->unary));
@@ -1325,7 +1332,7 @@ exp_nameop (int code, const char *name)
 
   exp_fold_tree_no_dot (&value);
   if (expld.result.valid_p)
-    return exp_intop (expld.result.value);
+    return make_int ();
 
   new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
   memcpy (new_e, &value, sizeof (new_e->name));
diff --git a/ld/ldexp.h b/ld/ldexp.h
index 0da3981..2093e3f 100644
--- a/ld/ldexp.h
+++ b/ld/ldexp.h
@@ -194,7 +194,7 @@ extern segment_type *segments;
 typedef struct _fill_type fill_type;
 
 etree_type *exp_intop
-  (bfd_vma);
+  (bfd_vma, bfd_boolean);
 etree_type *exp_bigintop
   (bfd_vma, char *);
 etree_type *exp_relop
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 9973b07..31c2941 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -99,7 +99,7 @@ static int error_index;
 %type <name> memspec_at_opt
 %type <cname> wildcard_name
 %type <wildcard> wildcard_spec
-%token <bigint> INT
+%token <bigint> INT ABSINT
 %token <name> NAME LNAME
 %type <integer> length
 %type <phdr> phdr_qualifiers
@@ -1235,21 +1235,21 @@ phdr_type:
 			   i++)
 			if (strcmp (s, phdr_types[i]) == 0)
 			  {
-			    $$ = exp_intop (i);
+			    $$ = exp_intop (i, TRUE);
 			    break;
 			  }
 		      if (i == sizeof phdr_types / sizeof phdr_types[0])
 			{
 			  if (strcmp (s, "PT_GNU_EH_FRAME") == 0)
-			    $$ = exp_intop (0x6474e550);
+			    $$ = exp_intop (0x6474e550, TRUE);
 			  else if (strcmp (s, "PT_GNU_STACK") == 0)
-			    $$ = exp_intop (0x6474e551);
+			    $$ = exp_intop (0x6474e551, TRUE);
 			  else
 			    {
 			      einfo (_("\
 %X%P:%S: unknown phdr type `%s' (try integer literal)\n"),
 				     NULL, s);
-			      $$ = exp_intop (0);
+			      $$ = exp_intop (0, TRUE);
 			    }
 			}
 		    }
diff --git a/ld/ldlang.c b/ld/ldlang.c
index aee8720..0833ab5 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1826,7 +1826,7 @@ lang_insert_orphan (asection *s,
 
   if (bfd_link_relocatable (&link_info)
       || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
-    address = exp_intop (0);
+    address = exp_intop (0, FALSE);
 
   os_tail = ((lang_output_section_statement_type **)
 	     lang_output_section_statement.tail);
@@ -4932,7 +4932,7 @@ lang_size_sections_1
 		&& bfd_link_relocatable (&link_info)
 		&& (bfd_get_flavour (link_info.output_bfd)
 		    == bfd_target_coff_flavour))
-	      os->addr_tree = exp_intop (0);
+	      os->addr_tree = exp_intop (0, FALSE);
 	    if (os->addr_tree != NULL)
 	      {
 		os->processed_vma = FALSE;
@@ -6199,7 +6199,7 @@ ldlang_place_orphan (asection *s)
       if (os->addr_tree == NULL
 	  && (bfd_link_relocatable (&link_info)
 	      || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
-	os->addr_tree = exp_intop (0);
+	os->addr_tree = exp_intop (0, FALSE);
       lang_add_section (&os->children, s, NULL, os);
     }
   else
@@ -6222,7 +6222,7 @@ ldlang_place_orphan (asection *s)
 	  if (os->addr_tree == NULL
 	      && (bfd_link_relocatable (&link_info)
 		  || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
-	    os->addr_tree = exp_intop (0);
+	    os->addr_tree = exp_intop (0, FALSE);
 	  lang_add_section (&os->children, s, NULL, os);
 	}
 
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 6e279ae..0ab0a21 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -1671,7 +1671,7 @@ set_section_start (char *sect, char *valstr)
   bfd_vma val = bfd_scan_vma (valstr, &end, 16);
   if (*end)
     einfo (_("%P%F: invalid hex number `%s'\n"), valstr);
-  lang_section_start (sect, exp_intop (val), NULL);
+  lang_section_start (sect, exp_intop (val, TRUE), NULL);
 }
 
 static void
@@ -1691,7 +1691,7 @@ set_segment_start (const char *section, char *valstr)
     if (strcmp (seg->name, name) == 0)
       {
 	seg->value = val;
-	lang_section_start (section, exp_intop (val), seg);
+	lang_section_start (section, exp_intop (val, TRUE), seg);
 	return;
       }
   /* There was no existing value so we must create a new segment
@@ -1707,7 +1707,7 @@ set_segment_start (const char *section, char *valstr)
      particular section.  For backwards compatibility, we still do
      that.  If a SEGMENT_START directive is seen, the section address
      assignment will be disabled.  */
-  lang_section_start (section, exp_intop (val), seg);
+  lang_section_start (section, exp_intop (val, TRUE), seg);
 }
 
 static void
diff --git a/ld/testsuite/ld-scripts/absolute1.d b/ld/testsuite/ld-scripts/absolute1.d
new file mode 100644
index 0000000..a09c318
--- /dev/null
+++ b/ld/testsuite/ld-scripts/absolute1.d
@@ -0,0 +1,9 @@
+# source: absolute1.s
+# ld: -T absolute1.t
+# nm: -B -n
+# notarget: mmix-*
+# mmix symbol sections are wrong
+
+0+0100 t _start
+0+0800 A _stack_start
+#....
\ No newline at end of file
diff --git a/ld/testsuite/ld-scripts/absolute1.s b/ld/testsuite/ld-scripts/absolute1.s
new file mode 100644
index 0000000..44d2748
--- /dev/null
+++ b/ld/testsuite/ld-scripts/absolute1.s
@@ -0,0 +1,4 @@
+        .text
+_start:
+        nop
+        .long   _stack_start
diff --git a/ld/testsuite/ld-scripts/absolute1.t b/ld/testsuite/ld-scripts/absolute1.t
new file mode 100644
index 0000000..060e90a
--- /dev/null
+++ b/ld/testsuite/ld-scripts/absolute1.t
@@ -0,0 +1,8 @@
+SECTIONS
+{
+  .text 0x100 :
+  {
+    *(.text)
+   _stack_start = ABSOLUTE(0x0800);
+  }
+}
diff --git a/ld/testsuite/ld-scripts/expr.exp b/ld/testsuite/ld-scripts/expr.exp
index 7c9b2c4..5f65125 100644
--- a/ld/testsuite/ld-scripts/expr.exp
+++ b/ld/testsuite/ld-scripts/expr.exp
@@ -25,6 +25,7 @@ run_dump_test sane1
 run_dump_test assign-loc
 run_dump_test pr14962
 run_dump_test pr14962-2
+run_dump_test absolute1
 
 set old_ldflags $LDFLAGS
 if { [istarget spu*-*-*] } {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]