ld: Don't evaluate unneeded PROVIDE expressions.
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 7 Jan 2015 10:51:35 +0000 (10:51 +0000)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 20 Jan 2015 09:49:27 +0000 (09:49 +0000)
When creating a linker mapfile (using -Map=MAPFILE), we previously would
always try to evaluate the expression from a PROVIDE statement.

However, this is not always safe, consider:

  PROVIDE (foo = 0x10);
  PROVIDE (bar = foo);

In this example, if neither 'foo' or 'bar' is needed, then while
generating the linker mapfile evaluating the expression for 'foo' is
harmless (just the value 0x10).  However, evaluating the expression for
'bar' requires the symbol 'foo', which is undefined.  This used to cause
a fatal error.

This patch changes the behaviour, so that when the destination of the
PROVIDE is not defined (that is the PROVIDE is not going to provide
anything) the expression is not evaluated, and instead a special string
is displayed to indicate that the linker is discarding the PROVIDE
statement.

This change not only fixes the spurious undefined symbol error, but also
means that a user can now tell if a PROVIDE statement has provided
anything by inspecting the linker mapfile, something that could not be
done before.

ld/ChangeLog:

* ldlang.c (print_assignment): Only evaluate the expression for a
PROVIDE'd assignment when the destination is being defined.
Display a special message for PROVIDE'd symbols that are not being
provided.

ld/testsuite/ChangeLog:

* ld-scripts/provide-4.d: New file.
* ld-scripts/provide-4-map.d: New file.
* ld-scripts/provide-4.t: New file.
* ld-scripts/provide-5.d: New file.
* ld-scripts/provide-5.s: New file.
* ld-scripts/provide-5-map.d: New file.
* ld-scripts/provide-5.t: New file.
* ld-scripts/provide.exp: Run the provide-4.d and provide-5.d
tests.

ld/ChangeLog
ld/ldlang.c
ld/testsuite/ChangeLog
ld/testsuite/ld-scripts/provide-4-map.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-4.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-4.t [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-5-map.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-5.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-5.s [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-5.t [new file with mode: 0644]
ld/testsuite/ld-scripts/provide.exp

index 1ca6fe39cfd933ab285a21362f3fac21f2df8482..4641ff06c8152d6752f5e746d7b74f62da46c113 100644 (file)
@@ -1,3 +1,10 @@
+2015-01-20  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * ldlang.c (print_assignment): Only evaluate the expression for a
+       PROVIDE'd assignment when the destination is being defined.
+       Display a special message for PROVIDE'd symbols that are not being
+       provided.
+
 2015-01-20  Alan Modra  <amodra@gmail.com>
 
        * emulparams/elf64ppc.sh (BSS_PLT): Don't define.
index 0c72333499c7a7d7667d81e5a82085785da8951e..3ea22c2f530d3d90066dde6c5d358db71ea5a3cb 100644 (file)
@@ -3983,7 +3983,12 @@ print_assignment (lang_assignment_statement_type *assignment,
   osec = output_section->bfd_section;
   if (osec == NULL)
     osec = bfd_abs_section_ptr;
-  exp_fold_tree (tree, osec, &print_dot);
+
+  if (assignment->exp->type.node_class != etree_provide)
+    exp_fold_tree (tree, osec, &print_dot);
+  else
+    expld.result.valid_p = FALSE;
+
   if (expld.result.valid_p)
     {
       bfd_vma value;
@@ -4021,7 +4026,10 @@ print_assignment (lang_assignment_statement_type *assignment,
     }
   else
     {
-      minfo ("*undef*   ");
+      if (assignment->exp->type.node_class == etree_provide)
+        minfo ("[!provide]");
+      else
+        minfo ("*undef*   ");
 #ifdef BFD64
       minfo ("        ");
 #endif
index b6e348101d7e4e52bf0aa243007b9ae05e7de4db..0b474949b0adaf03cd50fc29605596cb507b01d0 100644 (file)
@@ -1,3 +1,15 @@
+2015-01-20  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * ld-scripts/provide-4.d: New file.
+       * ld-scripts/provide-4-map.d: New file.
+       * ld-scripts/provide-4.t: New file.
+       * ld-scripts/provide-5.d: New file.
+       * ld-scripts/provide-5.s: New file.
+       * ld-scripts/provide-5-map.d: New file.
+       * ld-scripts/provide-5.t: New file.
+       * ld-scripts/provide.exp: Run the provide-4.d and provide-5.d
+       tests.
+
 2015-01-20  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * ld-scripts/overlay-size.d: Add 'map' option.
diff --git a/ld/testsuite/ld-scripts/provide-4-map.d b/ld/testsuite/ld-scripts/provide-4-map.d
new file mode 100644 (file)
index 0000000..d8e4a28
--- /dev/null
@@ -0,0 +1,13 @@
+#...
+Linker script and memory map
+#...
+                \[!provide\]                        PROVIDE \(foo, 0x1\)
+                \[!provide\]                        PROVIDE \(bar, 0x2\)
+                0x0+3                PROVIDE \(baz, 0x3\)
+#...
+                0x0+2000                foo
+                \[!provide\]                        PROVIDE \(loc1, ALIGN \(\., 0x10\)\)
+                0x0+2010                PROVIDE \(loc2, ALIGN \(\., 0x10\)\)
+                \[!provide\]                        PROVIDE \(loc3, \(loc1 \+ 0x20\)\)
+                0x0+2030                loc4 = \(loc2 \+ 0x20\)
+#...
diff --git a/ld/testsuite/ld-scripts/provide-4.d b/ld/testsuite/ld-scripts/provide-4.d
new file mode 100644 (file)
index 0000000..a7d37e3
--- /dev/null
@@ -0,0 +1,9 @@
+#source: provide-2.s
+#ld: -T provide-4.t
+#PROG: nm
+#map: provide-4-map.d
+#...
+0+3 A baz
+0+2000 D foo
+0+2010 D loc2
+0+2030 A loc4
diff --git a/ld/testsuite/ld-scripts/provide-4.t b/ld/testsuite/ld-scripts/provide-4.t
new file mode 100644 (file)
index 0000000..424c238
--- /dev/null
@@ -0,0 +1,16 @@
+SECTIONS
+{
+  PROVIDE (foo = 1);
+  PROVIDE (bar = 2);
+  PROVIDE (baz = 3);
+  .data 0x2000 :
+  {
+    *(.data)
+
+    PROVIDE (loc1 = ALIGN (., 0x10));
+    PROVIDE (loc2 = ALIGN (., 0x10));
+  }
+
+  PROVIDE (loc3 = loc1 + 0x20);
+  loc4 = loc2 + 0x20;
+}
diff --git a/ld/testsuite/ld-scripts/provide-5-map.d b/ld/testsuite/ld-scripts/provide-5-map.d
new file mode 100644 (file)
index 0000000..2271dfd
--- /dev/null
@@ -0,0 +1,6 @@
+#...
+Linker script and memory map
+#...
+                0x0+10                foo = 0x10
+                \[!provide\]                        PROVIDE \(foo, bar\)
+#...
diff --git a/ld/testsuite/ld-scripts/provide-5.d b/ld/testsuite/ld-scripts/provide-5.d
new file mode 100644 (file)
index 0000000..1b14fa6
--- /dev/null
@@ -0,0 +1,6 @@
+#source: provide-5.s
+#ld: -T provide-5.t
+#PROG: nm
+#map: provide-5-map.d
+#...
+0+10 A foo
diff --git a/ld/testsuite/ld-scripts/provide-5.s b/ld/testsuite/ld-scripts/provide-5.s
new file mode 100644 (file)
index 0000000..1d05efd
--- /dev/null
@@ -0,0 +1,4 @@
+        .data
+        .global baz
+baz:
+        .word 0
diff --git a/ld/testsuite/ld-scripts/provide-5.t b/ld/testsuite/ld-scripts/provide-5.t
new file mode 100644 (file)
index 0000000..eda741e
--- /dev/null
@@ -0,0 +1,10 @@
+SECTIONS
+{
+  foo = 0x10;
+  PROVIDE (foo = bar);
+
+  .data 0x1000 :
+  {
+    *(.data)
+  }
+}
index 7f45e5892d22654d5e597176b19b553689b6955b..3ddbb2296dbf1fe5b468e2ad7cc20cbf8412c4d4 100644 (file)
@@ -40,5 +40,7 @@ run_dump_test provide-1
 run_dump_test provide-2
 setup_xfail *-*-*
 run_dump_test provide-3
+run_dump_test provide-4
+run_dump_test provide-5
 
 set LDFLAGS "$saved_LDFLAGS"