Relative expressions and ASSERT

H.J. Lu hjl.tools@gmail.com
Fri Dec 17 19:55:00 GMT 2010


On Thu, Dec 16, 2010 at 4:06 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Dec 16, 2010 at 4:01 PM, Alan Modra <amodra@gmail.com> wrote:
>> On Thu, Dec 16, 2010 at 03:14:38PM -0800, H.J. Lu wrote:
>>> Your patch doesn't work. I got
>>>
>>> ./ld: kernel image bigger than KERNEL_IMAGE_SIZE
>>>
>>> due to arch/x86/kernel/vmlinux.lds:
>>>
>>> ----
>>> /*
>>>  * Build-time check on the image size:
>>>  */
>>> . = ASSERT((_end - _text <= (512 * 1024 * 1024)),
>>>     "kernel image bigger than KERNEL_IMAGE_SIZE");
>>
>> Extracting the relevant parts from the kernel link script:
>>
>> SECTIONS
>> {
>>  . = 0xc000;
>>  .text :
>>  {
>>    _text = .;
>>    *(.text)
>>  }
>>  _end = .;
>> }
>> ASSERT (_end - _text <= 0x100, "fail");
>>
>> You'd think that under the new rules, this ought to work.  "_end" is
>> an absolute address, so when evaluating "_end - _text", "_text" ought
>> to be converted from relative to absolute, the subtraction resuling in
>> an absolute address.  Then 0x100 gets converted from a number to
>> absolute address before being compared.
>>
>> The trouble is that "_end" is *not* treated as an absolute address but
>> as a plain number.  That makes ld convert "_end" to a .text relative
>> address when evaluation "_end - _text", which doesn't cause a problem
>> at that stage, but the result is a relative address.  That means 0x100
>> is converted to a .text relative address too, which gives the wrong
>> result.
>>
>> The underlying problem is that we don't distinguish between plain
>> numbers and absolute addresses once values are stored in symbols.
>>
>
> I am putting this into the Linux binutils.
>
>
> --
> H.J.
> ---
> ld/
>
> 2010-12-16  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR ld/12327
>        * ldexp.c (exp_fold_tree_1): Only make absolute symbol value
>        absolute.
>
> ld/testsuite/
>
> 2010-12-16  H.J. Lu  <hongjiu.lu@intel.com>
>
>        PR ld/12327
>        * ld-scripts/defined.exp: Run defined4.
>
>        * ld-scripts/defined4.d: New.
>        * ld-scripts/defined4.s: Likewise.
>        * ld-scripts/defined4.t: Likewise.
>

The updated patch with a new testcase.

-- 
H.J.
---
ld/

2010-12-17  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12327
	* ldexp.c (exp_fold_tree_1): Only make absolute symbol value
	absolute.

ld/testsuite/

2010-12-17  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12327
	* ld-scripts/defined4.d: New.
	* ld-scripts/defined4.s: Likewise.
	* ld-scripts/defined4.t: Likewise.
	* ld-scripts/expr2.d: Likewise.
	* ld-scripts/expr2.s: Likewise.
	* ld-scripts/expr2.t: Likewise.

	* ld-scripts/defined.exp: Run defined4.

	* ld-scripts/expr.exp: Run expr2.
-------------- next part --------------
ld/

2010-12-17  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12327
	* ldexp.c (exp_fold_tree_1): Only make absolute symbol value
	absolute.

ld/testsuite/

2010-12-17  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/12327
	* ld-scripts/defined4.d: New.
	* ld-scripts/defined4.s: Likewise.
	* ld-scripts/defined4.t: Likewise.
	* ld-scripts/expr2.d: Likewise.
	* ld-scripts/expr2.s: Likewise.
	* ld-scripts/expr2.t: Likewise.

	* ld-scripts/defined.exp: Run defined4.

	* ld-scripts/expr.exp: Run expr2.

diff --git a/ld/ldexp.c b/ld/ldexp.c
index de7f9f2..c8fa331 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -691,12 +691,15 @@ fold_name (etree_type *tree)
 static void
 exp_fold_tree_1 (etree_type *tree)
 {
+  bfd_boolean absolute;
+
   if (tree == NULL)
     {
       memset (&expld.result, 0, sizeof (expld.result));
       return;
     }
 
+  absolute = TRUE;
   switch (tree->type.node_class)
     {
     case etree_value:
@@ -851,6 +854,21 @@ exp_fold_tree_1 (etree_type *tree)
 
     case etree_name:
       fold_name (tree);
+      if (tree->name.name
+	  && tree->name.name[0] != '.'
+	  && tree->name.name[1] != '\0'
+	  && link_info.hash)
+	{
+	  struct bfd_link_hash_entry *h;
+
+	  /* Only make absolute symbol value absolute.  */
+	  h = bfd_link_hash_lookup (link_info.hash, tree->name.name,
+				    FALSE, FALSE, TRUE);
+	  if (h
+	      && (h->type == bfd_link_hash_defined
+		  || h->type == bfd_link_hash_defweak))
+	    absolute = (h->u.def.section == bfd_abs_section_ptr);
+	}
       break;
 
     default:
@@ -861,7 +879,8 @@ exp_fold_tree_1 (etree_type *tree)
 
   /* Any value not inside an output section statement is an
      absolute value.  */
-  if (expld.result.valid_p
+  if (absolute
+      && expld.result.valid_p
       && expld.section == bfd_abs_section_ptr)
     make_abs ();
 }
diff --git a/ld/testsuite/ld-scripts/defined.exp b/ld/testsuite/ld-scripts/defined.exp
index 15cc079..6d0c9d5 100644
--- a/ld/testsuite/ld-scripts/defined.exp
+++ b/ld/testsuite/ld-scripts/defined.exp
@@ -1,6 +1,6 @@
 # Test DEFINED in a linker script.
 # By Ian Lance Taylor, Cygnus Support.
-#   Copyright 2001, 2003. 2005, 2006, 2007
+#   Copyright 2001, 2003, 2005, 2006, 2007, 2010
 #   Free Software Foundation, Inc.
 #
 # This file is part of the GNU Binutils.
@@ -66,4 +66,5 @@ if ![ld_simple_link $ld tmpdir/def "$LDFLAGS -T $srcdir/$subdir/defined.t tmpdir
 set prms_id 0
 run_dump_test "defined2"
 run_dump_test "defined3"
+run_dump_test "defined4"
 set LDFLAGS "$saved_LDFLAGS"
diff --git a/ld/testsuite/ld-scripts/defined4.d b/ld/testsuite/ld-scripts/defined4.d
new file mode 100644
index 0000000..2c3a6ea
--- /dev/null
+++ b/ld/testsuite/ld-scripts/defined4.d
@@ -0,0 +1,10 @@
+#ld: -Tdefined4.t
+#nm: -B
+#source: defined4.s
+
+# Check that arithmetic on DEFINED works.
+#...
+0+0 D defined
+#...
+0+0 D defined1
+#pass
diff --git a/ld/testsuite/ld-scripts/defined4.s b/ld/testsuite/ld-scripts/defined4.s
new file mode 100644
index 0000000..5969a44
--- /dev/null
+++ b/ld/testsuite/ld-scripts/defined4.s
@@ -0,0 +1,4 @@
+	.globl	defined
+	.data
+defined:
+	.word 0
diff --git a/ld/testsuite/ld-scripts/defined4.t b/ld/testsuite/ld-scripts/defined4.t
new file mode 100644
index 0000000..1221df2
--- /dev/null
+++ b/ld/testsuite/ld-scripts/defined4.t
@@ -0,0 +1,6 @@
+SECTIONS {
+	.text : { *(.text) }
+	.data : { *(.data) }
+	.bss : { *(.bss) *(COMMON) }
+}
+defined1 = defined;
diff --git a/ld/testsuite/ld-scripts/expr.exp b/ld/testsuite/ld-scripts/expr.exp
index 34829e5..467abcb 100644
--- a/ld/testsuite/ld-scripts/expr.exp
+++ b/ld/testsuite/ld-scripts/expr.exp
@@ -1,6 +1,6 @@
-# Test ALIGN in a linker script.
+# Test expressions in a linker script.
 # By Nathan Sidwell, CodeSourcery LLC
-#   Copyright 2006, 2007
+#   Copyright 2006, 2007, 2010
 #   Free Software Foundation, Inc.
 #
 # This file is part of the GNU Binutils.
@@ -21,3 +21,4 @@
 # MA 02110-1301, USA.
 
 run_dump_test expr1
+run_dump_test expr2
diff --git a/ld/testsuite/ld-scripts/expr2.d b/ld/testsuite/ld-scripts/expr2.d
new file mode 100644
index 0000000..6f7e253
--- /dev/null
+++ b/ld/testsuite/ld-scripts/expr2.d
@@ -0,0 +1,6 @@
+# ld: -T expr2.t
+#nm: -B
+
+#...
+.* D defined
+#pass
diff --git a/ld/testsuite/ld-scripts/expr2.s b/ld/testsuite/ld-scripts/expr2.s
new file mode 100644
index 0000000..5969a44
--- /dev/null
+++ b/ld/testsuite/ld-scripts/expr2.s
@@ -0,0 +1,4 @@
+	.globl	defined
+	.data
+defined:
+	.word 0
diff --git a/ld/testsuite/ld-scripts/expr2.t b/ld/testsuite/ld-scripts/expr2.t
new file mode 100644
index 0000000..634eab2
--- /dev/null
+++ b/ld/testsuite/ld-scripts/expr2.t
@@ -0,0 +1,11 @@
+SECTIONS
+{
+  . = 0xc000;
+  .text :
+  {
+    _text = .;
+    *(.text)
+  }
+  _end = .;
+}
+ASSERT (_end - _text <= 0x100, "fail");


More information about the Binutils mailing list