2013-07-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Fri, 5 Jul 2013 09:51:00 +0000 (09:51 +0000)
committerAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Fri, 5 Jul 2013 09:51:00 +0000 (09:51 +0000)
bfd/
* elf32-s390.c: Rewrite GOT accesses using larl if possible.
* elf64-s390.c: Likewise.

ld/testsuite/
* ld-s390/gotreloc-1.s: New file.
* ld-s390/gotreloc-1.ver: New file.
* ld-s390/gotreloc_31-1.dd: New file.
* ld-s390/gotreloc_64-1.dd: New file.
* ld-s390/s390.exp: Run the new tests. Run 31 bit tests also on 64
bit.

bfd/elf32-s390.c
bfd/elf64-s390.c
ld/testsuite/ld-s390/gotreloc-1.s [new file with mode: 0644]
ld/testsuite/ld-s390/gotreloc-1.ver [new file with mode: 0644]
ld/testsuite/ld-s390/gotreloc_31-1.dd [new file with mode: 0644]
ld/testsuite/ld-s390/gotreloc_64-1.dd [new file with mode: 0644]
ld/testsuite/ld-s390/s390.exp

index bee532d..6467b03 100644 (file)
@@ -2536,6 +2536,36 @@ elf_s390_relocate_section (bfd *output_bfd,
                                  base_got->contents + off);
                      h->got.offset |= 1;
                    }
+
+                 if ((h->def_regular
+                      && info->shared
+                      && SYMBOL_REFERENCES_LOCAL (info, h))
+                     /* lrl rx,sym@GOTENT -> larl rx, sym */
+                     && ((r_type == R_390_GOTENT
+                          && (bfd_get_16 (input_bfd,
+                                          contents + rel->r_offset - 2)
+                              & 0xff0f) == 0xc40d)
+                         /* ly rx, sym@GOT(r12) -> larl rx, sym */
+                         || (r_type == R_390_GOT20
+                             && (bfd_get_32 (input_bfd,
+                                             contents + rel->r_offset - 2)
+                                 & 0xff00f000) == 0xe300c000
+                             && bfd_get_8 (input_bfd,
+                                           contents + rel->r_offset + 3) == 0x58)))
+                   {
+                     unsigned short new_insn =
+                       (0xc000 | (bfd_get_8 (input_bfd,
+                                             contents + rel->r_offset - 1) & 0xf0));
+                     bfd_put_16 (output_bfd, new_insn,
+                                 contents + rel->r_offset - 2);
+                     r_type = R_390_PC32DBL;
+                     rel->r_addend = 2;
+                     howto = elf_howto_table + r_type;
+                     relocation = h->root.u.def.value
+                       + h->root.u.def.section->output_section->vma
+                       + h->root.u.def.section->output_offset;
+                     goto do_relocation;
+                   }
                }
              else
                unresolved_reloc = FALSE;
index bba6cec..75413e0 100644 (file)
@@ -2496,6 +2496,37 @@ elf_s390_relocate_section (bfd *output_bfd,
                                  base_got->contents + off);
                      h->got.offset |= 1;
                    }
+
+                 if ((h->def_regular
+                      && info->shared
+                      && SYMBOL_REFERENCES_LOCAL (info, h))
+                     /* lgrl rx,sym@GOTENT -> larl rx, sym */
+                     && ((r_type == R_390_GOTENT
+                          && (bfd_get_16 (input_bfd,
+                                          contents + rel->r_offset - 2)
+                              & 0xff0f) == 0xc408)
+                         /* lg rx, sym@GOT(r12) -> larl rx, sym */
+                         || (r_type == R_390_GOT20
+                             && (bfd_get_32 (input_bfd,
+                                             contents + rel->r_offset - 2)
+                                 & 0xff00f000) == 0xe300c000
+                             && bfd_get_8 (input_bfd,
+                                           contents + rel->r_offset + 3) == 0x04)))
+
+                   {
+                     unsigned short new_insn =
+                       (0xc000 | (bfd_get_8 (input_bfd,
+                                             contents + rel->r_offset - 1) & 0xf0));
+                     bfd_put_16 (output_bfd, new_insn,
+                                 contents + rel->r_offset - 2);
+                     r_type = R_390_PC32DBL;
+                     rel->r_addend = 2;
+                     howto = elf_howto_table + r_type;
+                     relocation = h->root.u.def.value
+                       + h->root.u.def.section->output_section->vma
+                       + h->root.u.def.section->output_offset;
+                     goto do_relocation;
+                   }
                }
              else
                unresolved_reloc = FALSE;
diff --git a/ld/testsuite/ld-s390/gotreloc-1.s b/ld/testsuite/ld-s390/gotreloc-1.s
new file mode 100644 (file)
index 0000000..b60d6c1
--- /dev/null
@@ -0,0 +1,11 @@
+       .text
+       .globl foo
+foo:
+       lgrl    %r1,bar@GOTENT
+       lg      %r1,bar@GOT(%r12)
+       lrl     %r1,bar@GOTENT
+       l       %r1,bar@GOT(%r12)
+       ly      %r1,bar@GOT(%r12)
+
+.globl bar
+bar:   .long   0x123
diff --git a/ld/testsuite/ld-s390/gotreloc-1.ver b/ld/testsuite/ld-s390/gotreloc-1.ver
new file mode 100644 (file)
index 0000000..1cb06d6
--- /dev/null
@@ -0,0 +1 @@
+{ local: bar; };
diff --git a/ld/testsuite/ld-s390/gotreloc_31-1.dd b/ld/testsuite/ld-s390/gotreloc_31-1.dd
new file mode 100644 (file)
index 0000000..4df4aa5
--- /dev/null
@@ -0,0 +1,14 @@
+
+tmpdir/gotreloc_31-1:     file format elf32-s390
+
+Disassembly of section .text:
+
+.* <foo>:
+.*:    c4 18 00 00             .long   0xc4180000
+.*:    08 4e e3 10             .long   0x084ee310
+.*:    c0 0c 00 04             .long   0xc00c0004
+.*:    c0 10 00 00 00 08 [      ]*larl %r1,168 <bar>
+.*:    58 10 c0 0c [    ]*l    %r1,12\(%r12\)
+.*:    c0 10 00 00 00 03 [      ]*larl %r1,168 <bar>
+.* <bar>:
+.*:    00 00 01 23             .long   0x00000123
diff --git a/ld/testsuite/ld-s390/gotreloc_64-1.dd b/ld/testsuite/ld-s390/gotreloc_64-1.dd
new file mode 100644 (file)
index 0000000..8c8c619
--- /dev/null
@@ -0,0 +1,12 @@
+tmpdir/gotreloc_64-1:     file format elf64-s390
+
+Disassembly of section .text:
+
+.* <foo>:
+.*:    c0 10 00 00 00 0e [      ]*larl %r1,.* <bar>
+.*:    c0 10 00 00 00 0b [      ]*larl %r1,.* <bar>
+.*:    c4 1d 00 00 08 86 [      ]*lrl  %r1,.* <_GLOBAL_OFFSET_TABLE_\+0x18>
+.*:    58 10 c0 18 [    ]*l    %r1,24\(%r12\)
+.*:    e3 10 c0 18 00 58 [      ]*ly   %r1,24\(%r12\)
+.* <bar>:
+.*:    00 00 01 23             .long   0x00000123
index 34c5b33..1ac11c7 100644 (file)
@@ -48,6 +48,11 @@ set s390tests {
      {{readelf -Ssrl tlsbin.rd} {objdump -dzrj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
      "tlsbin"}
+    {"GOT: symbol address load from got to larl"
+     "-shared -melf_s390 --version-script=gotreloc-1.ver" ""
+     "-m31" {gotreloc-1.s}
+     {{objdump -dzrj.text gotreloc_31-1.dd}}
+     "gotreloc_31-1"}
 }
 
 set s390xtests {
@@ -64,6 +69,11 @@ set s390xtests {
      {{readelf -WSsrl tlsbin_64.rd} {objdump -dzrj.text tlsbin_64.dd}
       {objdump -sj.got tlsbin_64.sd} {objdump -sj.tdata tlsbin_64.td}}
      "tlsbin_64"}
+    {"GOT: symbol address load from got to larl"
+     "-shared -melf64_s390 --version-script=gotreloc-1.ver" ""
+     "-m64" {gotreloc-1.s}
+     {{objdump -dzrj.text gotreloc_64-1.dd}}
+     "gotreloc_64-1"}
 }
 
 if [istarget "s390-*-*"] {
@@ -71,5 +81,6 @@ if [istarget "s390-*-*"] {
 }
 
 if [istarget "s390x-*-*"] {
+    run_ld_link_tests $s390tests
     run_ld_link_tests $s390xtests
 }