MIPS/LD: Accept high-part relocations in PIC code with absolute symbols
authorMaciej W. Rozycki <macro@linux-mips.org>
Tue, 27 Nov 2018 16:34:03 +0000 (16:34 +0000)
committerMaciej W. Rozycki <macro@linux-mips.org>
Tue, 27 Nov 2018 16:34:03 +0000 (16:34 +0000)
Accept R_MIPS_HI16, R_MIPS_HIGHER and R_MIPS_HIGHEST relocations and
their compressed counterparts in PIC code where the symbol referred is
absolute.  Such an operation is meaningful, because an absolute symbol
effectively is a constant the calculation of the value of which has been
deferred to the static link time, and which is not going to change any
further at the dynamic load time.  Therefore there is no need ever to
refuse the use of these relocations with such symbols, as the resulting
run-time value observed by the program will be correct even in PIC code.

This is not the case with R_MIPS_26 and its compressed counterparts,
because the run-time value calculated by the instructions these
relocations are used with depends on the address of the instruction
itself, and that can change according to the base address used by the
dynamic loader.  Therefore these relocations have to continue being
rejected in PIC code even with absolute symbols.

This allows successful linking of code that relies on previous linker
behavior up to commit 861fb55ab50a ("Defer allocation of R_MIPS_REL32
GOT slots"), <https://sourceware.org/ml/binutils/2008-08/msg00096.html>,
which introduced the problematic check missing this special exception
for absolute symbols.

bfd/
* elfxx-mips.c (_bfd_mips_elf_check_relocs) <R_MIPS16_HI16>
<R_MIPS_HI16, R_MIPS_HIGHER, R_MIPS_HIGHEST, R_MICROMIPS_HI16>
<R_MICROMIPS_HIGHER, R_MICROMIPS_HIGHEST>: Also accept an
absolute symbol in PIC code.

ld/
* testsuite/ld-mips-elf/pic-reloc-0.d: New test.
* testsuite/ld-mips-elf/pic-reloc-1.d: New test.
* testsuite/ld-mips-elf/pic-reloc-2.d: New test.
* testsuite/ld-mips-elf/pic-reloc-3.d: New test.
* testsuite/ld-mips-elf/pic-reloc-4.d: New test.
* testsuite/ld-mips-elf/pic-reloc-absolute-hi.ld: New test
linker script.
* testsuite/ld-mips-elf/pic-reloc-absolute-lo.ld: New test
linker script.
* testsuite/ld-mips-elf/pic-reloc-ordinary.ld: New test linker
script.
* testsuite/ld-mips-elf/pic-reloc-j.s: New test source.
* testsuite/ld-mips-elf/pic-reloc-lui.s: New test source.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.

14 files changed:
bfd/ChangeLog
bfd/elfxx-mips.c
ld/ChangeLog
ld/testsuite/ld-mips-elf/mips-elf.exp
ld/testsuite/ld-mips-elf/pic-reloc-0.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-1.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-2.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-3.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-4.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-absolute-hi.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-absolute-lo.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-j.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-lui.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/pic-reloc-ordinary.ld [new file with mode: 0644]

index e737f35e4b255adbff72176b99a2679f56082fb0..60eceaa2b5879702f072b72e00b370e6cfd27eec 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-27  Maciej W. Rozycki  <macro@linux-mips.org>
+
+       * elfxx-mips.c (_bfd_mips_elf_check_relocs) <R_MIPS16_HI16>
+       <R_MIPS_HI16, R_MIPS_HIGHER, R_MIPS_HIGHEST, R_MICROMIPS_HI16>
+       <R_MICROMIPS_HIGHER, R_MICROMIPS_HIGHEST>: Also accept an
+       absolute symbol in PIC code.
+
 2018-11-27  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * elfxx-mips.c (_bfd_mips_elf_check_relocs) <R_MIPS16_26>
index 298f465e432e1b36753016b1bfb972d486555e9c..1d789db1f23375c2d34975dced245ec30eaf8ed4 100644 (file)
@@ -9061,6 +9061,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              if (r_symndx == STN_UNDEF)
                break;
 
+             /* Likewise an absolute symbol.  */
+             if (bfd_is_abs_symbol (&h->root))
+               break;
+
              /* R_MIPS_HI16 against _gp_disp is used for $gp setup,
                 and has a special meaning.  */
              if (!NEWABI_P (abfd) && h != NULL
index 667bc05e1d8ecf9f5a68506502e6469ed407b723..38a88df8a0db5f4f824e231ea6101e64b2c63401 100644 (file)
@@ -1,3 +1,20 @@
+2018-11-27  Maciej W. Rozycki  <macro@linux-mips.org>
+
+       * testsuite/ld-mips-elf/pic-reloc-0.d: New test.
+       * testsuite/ld-mips-elf/pic-reloc-1.d: New test.
+       * testsuite/ld-mips-elf/pic-reloc-2.d: New test.
+       * testsuite/ld-mips-elf/pic-reloc-3.d: New test.
+       * testsuite/ld-mips-elf/pic-reloc-4.d: New test.
+       * testsuite/ld-mips-elf/pic-reloc-absolute-hi.ld: New test
+       linker script.
+       * testsuite/ld-mips-elf/pic-reloc-absolute-lo.ld: New test
+       linker script.
+       * testsuite/ld-mips-elf/pic-reloc-ordinary.ld: New test linker
+       script.
+       * testsuite/ld-mips-elf/pic-reloc-j.s: New test source.
+       * testsuite/ld-mips-elf/pic-reloc-lui.s: New test source.
+       * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
+
 2018-11-27  Maciej W. Rozycki  <macro@linux-mips.org>
 
        * ldmain.c (reloc_overflow): Use `%H:' rather than `%P: %H:'
index d4298102910cbc85aa5f68a4db777c76482cfd01..17fb1baafb7b1a3c7dfa5fed57d772964d215110 100644 (file)
@@ -1629,3 +1629,10 @@ if $has_abi(n64) {
     run_mips_undefweak_test "shared library (n64, microMIPS, hidden)" \
                                                    n64 dso umips hidden
 }
+
+# PIC relocation acceptance tests.
+run_dump_test "pic-reloc-0"
+run_dump_test "pic-reloc-1"
+run_dump_test "pic-reloc-2"
+run_dump_test "pic-reloc-3"
+run_dump_test "pic-reloc-4"
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-0.d b/ld/testsuite/ld-mips-elf/pic-reloc-0.d
new file mode 100644 (file)
index 0000000..0b2ee82
--- /dev/null
@@ -0,0 +1,7 @@
+#name: MIPS PIC relocation 0
+#ld: -shared -T pic-reloc-ordinary.ld
+#target: [check_shared_lib_support]
+#source: pic-reloc-lui.s
+#error: \A[^\n]*: in function `foo':\n
+#error:   \(\.text\+0x0\): relocation R_MIPS_HI16 against `bar' cannot be used when making a shared object; recompile with -fPIC\n
+#error:   \(\.text\+0x8\): relocation R_MIPS_HI16 against `bar' cannot be used when making a shared object; recompile with -fPIC\Z
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-1.d b/ld/testsuite/ld-mips-elf/pic-reloc-1.d
new file mode 100644 (file)
index 0000000..d84a090
--- /dev/null
@@ -0,0 +1,14 @@
+#name: MIPS PIC relocation 1
+#ld: -shared -T pic-reloc-absolute-hi.ld
+#objdump: -d --prefix-addresses --show-raw-insn
+#target: [check_shared_lib_support]
+#source: pic-reloc-lui.s
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 3c021234     lui     v0,0x1234
+[0-9a-f]+ <[^>]*> 24425678     addiu   v0,v0,22136
+[0-9a-f]+ <[^>]*> 3c021234     lui     v0,0x1234
+[0-9a-f]+ <[^>]*> 24425678     addiu   v0,v0,22136
+       \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-2.d b/ld/testsuite/ld-mips-elf/pic-reloc-2.d
new file mode 100644 (file)
index 0000000..fabc071
--- /dev/null
@@ -0,0 +1,7 @@
+#name: MIPS PIC relocation 2
+#ld: -shared -T pic-reloc-ordinary.ld
+#target: [check_shared_lib_support]
+#source: pic-reloc-j.s
+#error: \A[^\n]*: in function `foo':\n
+#error:   \(\.text\+0x0\): relocation R_MIPS_26 against `bar' cannot be used when making a shared object; recompile with -fPIC\n
+#error:   \(\.text\+0x8\): relocation R_MIPS_26 against `bar' cannot be used when making a shared object; recompile with -fPIC\Z
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-3.d b/ld/testsuite/ld-mips-elf/pic-reloc-3.d
new file mode 100644 (file)
index 0000000..74fc877
--- /dev/null
@@ -0,0 +1,7 @@
+#name: MIPS PIC relocation 3
+#ld: -shared -T pic-reloc-absolute-lo.ld
+#target: [check_shared_lib_support]
+#source: pic-reloc-j.s
+#error: \A[^\n]*: in function `foo':\n
+#error:   \(\.text\+0x0\): relocation R_MIPS_26 against `bar' cannot be used when making a shared object; recompile with -fPIC\n
+#error:   \(\.text\+0x8\): relocation R_MIPS_26 against `bar' cannot be used when making a shared object; recompile with -fPIC\Z
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-4.d b/ld/testsuite/ld-mips-elf/pic-reloc-4.d
new file mode 100644 (file)
index 0000000..0e43570
--- /dev/null
@@ -0,0 +1,9 @@
+#name: MIPS PIC relocation 4
+#ld: -shared -T pic-reloc-absolute-hi.ld
+#target: [check_shared_lib_support]
+#source: pic-reloc-j.s
+#error: \A[^\n]*: in function `foo':\n
+#error:   \(\.text\+0x0\): relocation R_MIPS_26 against `bar' cannot be used when making a shared object; recompile with -fPIC\n
+#error:   \(\.text\+0x8\): relocation R_MIPS_26 against `bar' cannot be used when making a shared object; recompile with -fPIC\n
+#error:   \(\.text\+0x0\): relocation truncated to fit: R_MIPS_26 against `bar'\n
+#error:   \(\.text\+0x8\): relocation truncated to fit: R_MIPS_26 against `bar'\Z
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-absolute-hi.ld b/ld/testsuite/ld-mips-elf/pic-reloc-absolute-hi.ld
new file mode 100644 (file)
index 0000000..c8848c4
--- /dev/null
@@ -0,0 +1,6 @@
+SECTIONS
+{
+  bar = 0x12345678;
+  .text : { *(.text) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-absolute-lo.ld b/ld/testsuite/ld-mips-elf/pic-reloc-absolute-lo.ld
new file mode 100644 (file)
index 0000000..592926e
--- /dev/null
@@ -0,0 +1,6 @@
+SECTIONS
+{
+  bar = 0x2345678;
+  .text : { *(.text) }
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-j.s b/ld/testsuite/ld-mips-elf/pic-reloc-j.s
new file mode 100644 (file)
index 0000000..2e8f9e7
--- /dev/null
@@ -0,0 +1,11 @@
+       .text
+       .globl  foo
+       .ent    foo
+foo:
+       j       bar
+       j       bar
+       .end    foo
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+       .align  4, 0
+       .space  16
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-lui.s b/ld/testsuite/ld-mips-elf/pic-reloc-lui.s
new file mode 100644 (file)
index 0000000..3ad3570
--- /dev/null
@@ -0,0 +1,13 @@
+       .text
+       .globl  foo
+       .ent    foo
+foo:
+       lui     $2, %hi(bar)
+       addiu   $2, %lo(bar)
+       lui     $2, %hi(bar)
+       addiu   $2, %lo(bar)
+       .end    foo
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+       .align  4, 0
+       .space  16
diff --git a/ld/testsuite/ld-mips-elf/pic-reloc-ordinary.ld b/ld/testsuite/ld-mips-elf/pic-reloc-ordinary.ld
new file mode 100644 (file)
index 0000000..a3ed51a
--- /dev/null
@@ -0,0 +1,6 @@
+SECTIONS
+{
+  bar = foo;
+  .text : { *(.text) }
+  /DISCARD/ : { *(*) }
+}