bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 14 Aug 2007 19:48:21 +0000 (19:48 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 14 Aug 2007 19:48:21 +0000 (19:48 +0000)
2007-08-14  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/4918
* elf32-i386.c (elf_i386_relocate_section): Allow R_386_PC32
on ___tls_get_addr for GD->LE/LD->LE transitions when not
building shared library.

* elf64-x86-64.c (elf64_x86_64_relocate_section): Allow
R_X86_64_PC32 on __tls_get_addr for GD->LE/LD->LE transitions
when not building shared library.

ld/testsuite/

2007-08-14  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/4918
* ld-i386/i386.exp (i386tests): Add tlsgd1 and tlsld1 tests.
* ld-x86-64/x86-64.exp (x86_64tests): Likewise.

* ld-i386/tlsgd1.dd: New file.
* ld-i386/tlsgd1.s: Likewise.
* ld-i386/tlsld1.dd: Likewise.
* ld-i386/tlsld1.s: Likewise.
* ld-x86-64/tlsgd1.dd: Likewise.
* ld-x86-64/tlsgd1.s: Likewise.
* ld-x86-64/tlsld1.dd: Likewise.
* ld-x86-64/tlsld1.s: Likewise.

14 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
ld/testsuite/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/tlsgd1.dd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsgd1.s [new file with mode: 0644]
ld/testsuite/ld-i386/tlsld1.dd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsld1.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/tlsgd1.dd [new file with mode: 0644]
ld/testsuite/ld-x86-64/tlsgd1.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/tlsld1.dd [new file with mode: 0644]
ld/testsuite/ld-x86-64/tlsld1.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 33e787113782220ea227e645c19667590f3143bd..5f5d291c7f62539f2857263355836641eaa30d8e 100644 (file)
@@ -1,3 +1,14 @@
+2007-08-14  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/4918
+       * elf32-i386.c (elf_i386_relocate_section): Allow R_386_PC32
+       on ___tls_get_addr for GD->LE/LD->LE transitions when not
+       building shared library.
+
+       * elf64-x86-64.c (elf64_x86_64_relocate_section): Allow
+       R_X86_64_PC32 on __tls_get_addr for GD->LE/LD->LE transitions
+       when not building shared library.
+
 2007-08-14  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * elfcode.h (NAME(_bfd_elf,bfd_from_remote_memory)): LOADBASE is now
index c50e98d92bf357d76cc7a30b0caa12d4295e212a..0e50e9ea1c71d648dd1ced45cffd142ebab36aa9 100644 (file)
@@ -2652,6 +2652,8 @@ elf_i386_relocate_section (bfd *output_bfd,
                {
                  unsigned int val, type;
                  bfd_vma roff;
+                 unsigned long tls_r_symndx;
+                 struct elf_link_hash_entry *tls_h;
 
                  /* GD->LE transition.  */
                  BFD_ASSERT (rel->r_offset >= 2);
@@ -2662,7 +2664,16 @@ elf_i386_relocate_section (bfd *output_bfd,
                                         contents + rel->r_offset + 4)
                              == 0xe8);
                  BFD_ASSERT (rel + 1 < relend);
-                 BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
+                 tls_r_symndx = ELF32_R_SYM (rel[1].r_info);
+                 BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+                 tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+                 BFD_ASSERT (tls_h != NULL
+                             && tls_h->root.root.string != NULL
+                             && strcmp (tls_h->root.root.string,
+                                        "___tls_get_addr") == 0);
+                 BFD_ASSERT ((! info->shared
+                              && ELF32_R_TYPE (rel[1].r_info) == R_386_PC32)
+                             || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
                  roff = rel->r_offset + 5;
                  val = bfd_get_8 (input_bfd,
                                   contents + rel->r_offset - 1);
@@ -2707,7 +2718,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                    }
                  bfd_put_32 (output_bfd, tpoff (info, relocation),
                              contents + roff);
-                 /* Skip R_386_PLT32.  */
+                 /* Skip R_386_PC32/R_386_PLT32.  */
                  rel++;
                  continue;
                }
@@ -3191,6 +3202,8 @@ elf_i386_relocate_section (bfd *output_bfd,
          if (! info->shared)
            {
              unsigned int val;
+             unsigned long tls_r_symndx;
+             struct elf_link_hash_entry *tls_h;
 
              /* LD->LE transition:
                 Ensure it is:
@@ -3206,10 +3219,18 @@ elf_i386_relocate_section (bfd *output_bfd,
              BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
                          == 0xe8);
              BFD_ASSERT (rel + 1 < relend);
-             BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
+             tls_r_symndx = ELF32_R_SYM (rel[1].r_info);
+             BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+             tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+             BFD_ASSERT (tls_h != NULL
+                         && tls_h->root.root.string != NULL
+                         && strcmp (tls_h->root.root.string,
+                                    "___tls_get_addr") == 0);
+             BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
+                         || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
              memcpy (contents + rel->r_offset - 2,
                      "\x65\xa1\0\0\0\0\x90\x8d\x74\x26", 11);
-             /* Skip R_386_PLT32.  */
+             /* Skip R_386_PC32/R_386_PLT32.  */
              rel++;
              continue;
            }
index 389c89a9615be70b401e24388173382b2b72c4a0..6d2d59d6b76476ccd25eb7c751723d8f49d05031 100644 (file)
@@ -2527,10 +2527,12 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                  unsigned int i;
                  static unsigned char tlsgd[8]
                    = { 0x66, 0x48, 0x8d, 0x3d, 0x66, 0x66, 0x48, 0xe8 };
+                 unsigned long tls_r_symndx;
+                 struct elf_link_hash_entry *tls_h;
 
                  /* GD->LE transition.
                     .byte 0x66; leaq foo@tlsgd(%rip), %rdi
-                    .word 0x6666; rex64; call __tls_get_addr@plt
+                    .word 0x6666; rex64; call __tls_get_addr
                     Change it into:
                     movq %fs:0, %rax
                     leaq foo@tpoff(%rax), %rax */
@@ -2545,13 +2547,22 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                           contents + rel->r_offset + 4 + i)
                                == tlsgd[i+4]);
                  BFD_ASSERT (rel + 1 < relend);
-                 BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+                 tls_r_symndx = ELF64_R_SYM (rel[1].r_info);
+                 BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+                 tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+                 BFD_ASSERT (tls_h != NULL
+                             && tls_h->root.root.string != NULL
+                             && strcmp (tls_h->root.root.string,
+                                        "__tls_get_addr") == 0);
+                 BFD_ASSERT ((! info->shared
+                              && ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32)
+                             || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
                  memcpy (contents + rel->r_offset - 4,
                          "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
                          16);
                  bfd_put_32 (output_bfd, tpoff (info, relocation),
                              contents + rel->r_offset + 8);
-                 /* Skip R_X86_64_PLT32.  */
+                 /* Skip R_X86_64_PC32/R_X86_64_PLT32.  */
                  rel++;
                  continue;
                }
@@ -2919,9 +2930,12 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_X86_64_TLSLD:
          if (! info->shared)
            {
+             unsigned long tls_r_symndx;
+             struct elf_link_hash_entry *tls_h;
+
              /* LD->LE transition:
                 Ensure it is:
-                leaq foo@tlsld(%rip), %rdi; call __tls_get_addr@plt.
+                leaq foo@tlsld(%rip), %rdi; call __tls_get_addr.
                 We change it into:
                 .word 0x6666; .byte 0x66; movl %fs:0, %rax.  */
              BFD_ASSERT (rel->r_offset >= 3);
@@ -2935,10 +2949,18 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
                          == 0xe8);
              BFD_ASSERT (rel + 1 < relend);
-             BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+             tls_r_symndx = ELF64_R_SYM (rel[1].r_info);
+             BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+             tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+             BFD_ASSERT (tls_h != NULL
+                         && tls_h->root.root.string != NULL
+                         && strcmp (tls_h->root.root.string,
+                                    "__tls_get_addr") == 0);
+             BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32
+                         || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
              memcpy (contents + rel->r_offset - 3,
                      "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12);
-             /* Skip R_X86_64_PLT32.  */
+             /* Skip R_X86_64_PC32/R_X86_64_PLT32.  */
              rel++;
              continue;
            }
index 5e0310f09b47ab2f3dd4b1cecfc1d2e9f3f691b6..b9931cee946e5ae3326a9a0df7b83e6677fc92ef 100644 (file)
@@ -1,3 +1,18 @@
+2007-08-14  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/4918
+       * ld-i386/i386.exp (i386tests): Add tlsgd1 and tlsld1 tests.
+       * ld-x86-64/x86-64.exp (x86_64tests): Likewise.
+
+       * ld-i386/tlsgd1.dd: New file.
+       * ld-i386/tlsgd1.s: Likewise.
+       * ld-i386/tlsld1.dd: Likewise.
+       * ld-i386/tlsld1.s: Likewise.
+       * ld-x86-64/tlsgd1.dd: Likewise.
+       * ld-x86-64/tlsgd1.s: Likewise.
+       * ld-x86-64/tlsld1.dd: Likewise.
+       * ld-x86-64/tlsld1.s: Likewise.
+
 2007-08-13  Richard Sandiford  <richard@codesourcery.com>
 
        * ld-mips-elf/vxworks-forced-local-1.d,
index 6b985197207228585eaaafbff4fb9a81c978fcdf..2c7c14b317ec7d0e651c1b0f1fc0885271fa44cf 100644 (file)
@@ -109,6 +109,12 @@ set i386tests {
      {emit-relocs.s} {{readelf --relocs emit-relocs.d}} "emit-relocs.so"}
     {"-z combreloc relocation sections" "-shared -melf_i386 -z combreloc"
      "--32" {combreloc.s} {{readelf -r combreloc.d}} "combreloc.so"}
+    {"TLS GD->LE transition" "-melf_i386"
+     "--32" {tlsgd1.s}
+     {{objdump -dwr tlsgd1.dd}} "tlsgd1"}
+    {"TLS LD->LE transition" "-melf_i386"
+     "--32" {tlsld1.s}
+     {{objdump -dwr tlsld1.dd}} "tlsld1"}
 }
 
 run_ld_link_tests $i386tests
diff --git a/ld/testsuite/ld-i386/tlsgd1.dd b/ld/testsuite/ld-i386/tlsgd1.dd
new file mode 100644 (file)
index 0000000..54d7416
--- /dev/null
@@ -0,0 +1,14 @@
+#source: tlsgd1.s
+#as: --32
+#ld: -melf_i386 tmpdir/tlsgd1
+#objdump: -drw
+#target: i?86-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[      ]*[a-f0-9]+:    65 a1 00 00 00 00       mov    %gs:0x0,%eax
+[      ]*[a-f0-9]+:    81 e8 04 00 00 00       sub    \$0x4,%eax
+#pass
diff --git a/ld/testsuite/ld-i386/tlsgd1.s b/ld/testsuite/ld-i386/tlsgd1.s
new file mode 100644 (file)
index 0000000..2b3ed0e
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .globl _start
+_start:
+       leal    foo@TLSGD(,%ebx,1), %eax
+       call    ___tls_get_addr
+       .globl foo
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   100
diff --git a/ld/testsuite/ld-i386/tlsld1.dd b/ld/testsuite/ld-i386/tlsld1.dd
new file mode 100644 (file)
index 0000000..782eb5a
--- /dev/null
@@ -0,0 +1,15 @@
+#source: tlsld1.s
+#as: --32
+#ld: -melf_i386 tmpdir/tlsld1
+#objdump: -drw
+#target: i?86-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[      ]*[a-f0-9]+:    65 a1 00 00 00 00       mov    %gs:0x0,%eax
+[      ]*[a-f0-9]+:    90                      nop    
+[      ]*[a-f0-9]+:    8d 74 26 00             lea    0x0\(%esi\),%esi
+#pass
diff --git a/ld/testsuite/ld-i386/tlsld1.s b/ld/testsuite/ld-i386/tlsld1.s
new file mode 100644 (file)
index 0000000..5d57e35
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .globl _start
+_start:
+       leal    foo@TLSLDM(%ebx), %eax
+       call    ___tls_get_addr
+       .globl foo
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   100
diff --git a/ld/testsuite/ld-x86-64/tlsgd1.dd b/ld/testsuite/ld-x86-64/tlsgd1.dd
new file mode 100644 (file)
index 0000000..b4f3c99
--- /dev/null
@@ -0,0 +1,14 @@
+#source: tlsgd1.s
+#as: --64
+#ld: -melf_x86_64 tmpdir/tlsgd1
+#objdump: -drw
+#target: x86_64-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[      ]*[a-f0-9]+:    64 48 8b 04 25 00 00 00 00      mov    %fs:0x0,%rax
+[      ]*[a-f0-9]+:    48 8d 80 fc ff ff ff    lea    -0x4\(%rax\),%rax
+#pass
diff --git a/ld/testsuite/ld-x86-64/tlsgd1.s b/ld/testsuite/ld-x86-64/tlsgd1.s
new file mode 100644 (file)
index 0000000..e5f52ed
--- /dev/null
@@ -0,0 +1,15 @@
+       .text
+       .globl _start
+_start:
+       .byte   0x66
+       leaq    foo@TLSGD(%rip), %rdi
+       .word   0x6666
+       rex64
+       call    __tls_get_addr
+       .globl foo
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   100
diff --git a/ld/testsuite/ld-x86-64/tlsld1.dd b/ld/testsuite/ld-x86-64/tlsld1.dd
new file mode 100644 (file)
index 0000000..c10f7ff
--- /dev/null
@@ -0,0 +1,13 @@
+#source: tlsld1.s
+#as: --64
+#ld: -melf_x86_64 tmpdir/tlsld1
+#objdump: -drw
+#target: x86_64-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[      ]*[a-f0-9]+:    66 66 66 64 48 8b 04 25 00 00 00 00     mov    %fs:0x0,%rax
+#pass
diff --git a/ld/testsuite/ld-x86-64/tlsld1.s b/ld/testsuite/ld-x86-64/tlsld1.s
new file mode 100644 (file)
index 0000000..6dcdd69
--- /dev/null
@@ -0,0 +1,12 @@
+       .text
+       .globl _start
+_start:
+       leaq    foo@TLSLD(%rip), %rdi
+       call    __tls_get_addr
+       .globl foo
+       .section        .tdata,"awT",@progbits
+       .align 4
+       .type   foo, @object
+       .size   foo, 4
+foo:
+       .long   100
index 75c527306ed61d2fa6170d710ccb9687f96c8bec..3d251292a7631ceb696f3ca28708fd0f5ef5262e 100644 (file)
@@ -66,6 +66,12 @@ set x86_64tests {
     {"TLS in debug sections" "-melf_x86_64"
      "--64" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
+    {"TLS GD->LE transition" "-melf_x86_64"
+     "--64" {tlsgd1.s}
+     {{objdump -dwr tlsgd1.dd}} "tlsgd1"}
+    {"TLS LD->LE transition" "-melf_x86_64"
+     "--64" {tlsld1.s}
+     {{objdump -dwr tlsld1.dd}} "tlsld1"}
 }
 
 run_ld_link_tests $x86_64tests