LD: Always make a SEGMENT_START expression section-relative
authorMaciej W. Rozycki <macro@mips.com>
Fri, 14 Sep 2018 19:22:56 +0000 (20:22 +0100)
committerMaciej W. Rozycki <macro@linux-mips.org>
Fri, 14 Sep 2018 19:22:56 +0000 (20:22 +0100)
Fix an issue with the SEGMENT_START builtin function where its result is
absolute when taken from the default supplied, and section-relative when
taken from a `-T' command-line override.  This is against documentation,
inconsistent and unexpected, and with PIE executables gives an incorrect
result with the `__executable_start' symbol.

Make the result of SEGMENT_START always section-relative then.

ld/
* ldexp.c (fold_binary): Always make the result of SEGMENT_START
section-relative.
* testsuite/ld-scripts/segment-start.d: New test.
* testsuite/ld-scripts/segment-start.ld: New test linker script.
* testsuite/ld-scripts/segment-start.s: New test source.
* testsuite/ld-scripts/script.exp: Run the new test.

ld/ChangeLog
ld/ldexp.c
ld/testsuite/ld-scripts/script.exp
ld/testsuite/ld-scripts/segment-start.d [new file with mode: 0644]
ld/testsuite/ld-scripts/segment-start.ld [new file with mode: 0644]
ld/testsuite/ld-scripts/segment-start.s [new file with mode: 0644]

index bda269c5a846b60be5250610d76b0ed31f6ac534..528ba3c255cde15712df12e3a3d54d2891c33e14 100644 (file)
@@ -1,3 +1,13 @@
+2018-09-14  Maciej W. Rozycki  <macro@mips.com>
+           Maciej W. Rozycki  <macro@linux-mips.org>
+
+       * ldexp.c (fold_binary): Always make the result of SEGMENT_START
+       section-relative.
+       * testsuite/ld-scripts/segment-start.d: New test.
+       * testsuite/ld-scripts/segment-start.ld: New test linker script.
+       * testsuite/ld-scripts/segment-start.s: New test source.
+       * testsuite/ld-scripts/script.exp: Run the new test.
+
 2018-09-14  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * ldexp.c (fold_binary): Check that `config.maxpagesize' is
index 4b9676ecbab6cef813aa0ed92d682a9a46bdd76a..f6446dcd202738de6dcb9c198ec289f4944e04ba 100644 (file)
@@ -534,6 +534,7 @@ fold_binary (etree_type *tree)
      operand, binary.rhs is first operand.  */
   if (expld.result.valid_p && tree->type.node_code == SEGMENT_START)
     {
+      bfd_vma value = expld.result.value;
       const char *segment_name;
       segment_type *seg;
 
@@ -551,9 +552,10 @@ fold_binary (etree_type *tree)
                       "isn't multiple of maximum page size\n"),
                     segment_name);
            seg->used = TRUE;
-           new_rel_from_abs (seg->value);
+           value = seg->value;
            break;
          }
+      new_rel_from_abs (value);
       return;
     }
 
index 4b781d4d38673afdac8548d1e0d290c3dbd0c105..6663633627fed3561dea494e1c7f5dc6c645b468 100644 (file)
@@ -231,3 +231,7 @@ foreach test_script $test_script_list {
 
 run_dump_test "align-with-input"
 run_dump_test "pr20302"
+
+run_dump_test "segment-start" {{name (default)}}
+run_dump_test "segment-start" {{name (overridden)} \
+                              {ld -Ttext-segment=0x10000000}}
diff --git a/ld/testsuite/ld-scripts/segment-start.d b/ld/testsuite/ld-scripts/segment-start.d
new file mode 100644 (file)
index 0000000..fcbcfb3
--- /dev/null
@@ -0,0 +1,19 @@
+#PROG: nm
+#name: SEGMENT_START expression not absolute
+#source: segment-start.s
+#ld: -e 0 -u __executable_start -T segment-start.ld
+#xfail: mmix-*-* pdp11-*-* powerpc-*-aix* powerpc-*-beos* rs6000-*-* sh-*-pe
+#xfail: c30-*-*aout* tic30-*-*aout* c54x*-*-*coff* tic54x-*-*coff*
+# XFAIL targets that are not expected to handle SEGMENT_START correctly.
+
+# Make sure `__executable_start' is regular:
+#
+# 10000000 T __executable_start
+#
+# not absolute:
+#
+# 10000000 A __executable_start
+
+#...
+0*10000000 T __executable_start
+#pass
diff --git a/ld/testsuite/ld-scripts/segment-start.ld b/ld/testsuite/ld-scripts/segment-start.ld
new file mode 100644 (file)
index 0000000..6202d19
--- /dev/null
@@ -0,0 +1,12 @@
+SECTIONS
+{
+  PROVIDE (__executable_start = SEGMENT_START ("text-segment", 0x10000000));
+  .text : { *(.text) }
+  .data : { *(.data) }
+  .bss : { *(.bss) }
+  .loader : { *(.loader) }
+  .symtab : { *(.symtab) }
+  .strtab : { *(.strtab) }
+  .shstrtab : { *(.shstrtab) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-scripts/segment-start.s b/ld/testsuite/ld-scripts/segment-start.s
new file mode 100644 (file)
index 0000000..5d785b4
--- /dev/null
@@ -0,0 +1,2 @@
+       .text
+       .space  16