ld/ARM: Fix IFUNC and TLS descriptors in the same shared object
authorWill Newton <will.newton@linaro.org>
Mon, 16 Jun 2014 14:49:07 +0000 (15:49 +0100)
committerWill Newton <will.newton@linaro.org>
Mon, 16 Jun 2014 14:51:21 +0000 (15:51 +0100)
Combining TLS descriptors and GNU indirect functions in the same
object could lead to assertions or multiple dynamic relocations
for the same GOT slot. Fix the bookkeeping so this doesn't happen.

This allows building and make checking glibc with -mtls-dialect=gnu2.

bfd/ChangeLog:

2014-06-16  Will Newton  <will.newton@linaro.org>

* elf32-arm.c (elf32_arm_allocate_plt_entry): Increment
htab->next_tls_desc_index in the non-IPLT case.
Calculate GOT offset correctly for the non-IPLT case.
(allocate_dynrelocs_for_symbol): Don't increment
htab->next_tls_desc_index here.

ld/testsuite/ChangeLog:

2014-06-16  Will Newton  <will.newton@linaro.org>

* ld-arm/arm-elf.exp: Add ifunc-gdesc test.
* ld-arm/ifunc-gdesc.r: New file.
* ld-arm/ifunc-gdesc.s: Likewise.
* ld-arm/ifunc-gdesc.ver: Likewise.

bfd/ChangeLog
bfd/elf32-arm.c
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/ifunc-gdesc.r [new file with mode: 0644]
ld/testsuite/ld-arm/ifunc-gdesc.s [new file with mode: 0644]
ld/testsuite/ld-arm/ifunc-gdesc.ver [new file with mode: 0644]

index d08bf24231a1b81636a1ab5591fdfd1ece175979..c56b48d609c6322d39457b2f0efb34b53622e078 100644 (file)
@@ -1,3 +1,11 @@
+2014-06-16  Will Newton  <will.newton@linaro.org>
+
+       * elf32-arm.c (elf32_arm_allocate_plt_entry): Increment
+       htab->next_tls_desc_index in the non-IPLT case.
+       Calculate GOT offset correctly for the non-IPLT case.
+       (allocate_dynrelocs_for_symbol): Don't increment
+       htab->next_tls_desc_index here.
+
 2014-06-16  Alan Modra  <amodra@gmail.com>
 
        * elf32-vax.c (elf_vax_size_dynamic_sections): Clear linker
index ef8bfa656140408ca8feaedc70fdd39e0f937084..ca64c7bf1ae27422336886efd5bbeb110a5db691 100644 (file)
@@ -7522,6 +7522,8 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
         first entry.  */
       if (splt->size == 0)
        splt->size += htab->plt_header_size;
+
+      htab->next_tls_desc_index++;
     }
 
   /* Allocate the PLT entry itself, including any leading Thumb stub.  */
@@ -7534,7 +7536,10 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
     {
       /* We also need to make an entry in the .got.plt section, which
         will be placed in the .got section by the linker script.  */
-      arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc;
+      if (is_iplt_entry)
+       arm_plt->got_offset = sgotplt->size;
+      else
+       arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc;
       sgotplt->size += 4;
     }
 }
@@ -13360,8 +13365,6 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
              h->target_internal = ST_BRANCH_TO_ARM;
            }
 
-         htab->next_tls_desc_index++;
-
          /* VxWorks executables have a second set of relocations for
             each PLT entry.  They go in a separate relocation section,
             which is processed by the kernel loader.  */
index ca10aa1752a42a30f28366b6d6bca23a317d45d8..2ef10c0b601b1e80872845bfb200374ebe3f8db5 100644 (file)
@@ -1,3 +1,10 @@
+2014-06-16  Will Newton  <will.newton@linaro.org>
+
+       * ld-arm/arm-elf.exp: Add ifunc-gdesc test.
+       * ld-arm/ifunc-gdesc.r: New file.
+       * ld-arm/ifunc-gdesc.s: Likewise.
+       * ld-arm/ifunc-gdesc.ver: Likewise.
+
 2014-06-09  Ryan Mansfield  <rmansfield@qnx.com>
 
         * config/default.exp (GASP): Remove.
index c255587ac3826292e4b24253a59f7496a3760e9d..2e7e1648b70c171f93e940178414aff65f749b90 100644 (file)
@@ -460,6 +460,9 @@ set armelftests_nonacl {
      "" {long-plt-format.s}
      {{objdump "-d -j .plt" long-plt-format.d}}
      "long-plt-format"}
+    {"IFUNC and TLS descriptor shared library" "-shared -T arm-lib.ld --version-script=ifunc-gdesc.ver" "" "" {ifunc-gdesc.s}
+     {{objdump "-Rw" ifunc-gdesc.r}}
+     "ifunc-gdesc.so"}
 }
 
 run_ld_link_tests $armelftests_common
diff --git a/ld/testsuite/ld-arm/ifunc-gdesc.r b/ld/testsuite/ld-arm/ifunc-gdesc.r
new file mode 100644 (file)
index 0000000..a49dd2b
--- /dev/null
@@ -0,0 +1,6 @@
+tmpdir/ifunc-gdesc.so:     file format elf32-(big|little)arm
+DYNAMIC RELOCATION RECORDS
+OFFSET   TYPE              VALUE 
+0000825c R_ARM_IRELATIVE   \*ABS\*
+00008248 R_ARM_TLS_DESC    \*ABS\*
+00008250 R_ARM_TLS_DESC    \*ABS\*
diff --git a/ld/testsuite/ld-arm/ifunc-gdesc.s b/ld/testsuite/ld-arm/ifunc-gdesc.s
new file mode 100644 (file)
index 0000000..a07a5d5
--- /dev/null
@@ -0,0 +1,29 @@
+
+       .arm
+
+foo:
+       bl      ifunc1(PLT)
+       ldr     r0,1f
+2:     bl      loc1(tlscall)
+       nop
+1:     .word   loc1(tlsdesc) + (. - 2b)
+
+       ldr     r0,1f
+2:     bl      loc2(tlscall)
+       nop
+1:     .word   loc2(tlsdesc) + (. - 2b)
+
+       .type   ifunc1,%gnu_indirect_function
+       .global ifunc1
+ifunc1:
+       mov     pc,lr
+       .size   ifunc1,.-ifunc1
+
+
+       .section        .tdata,"awT",%progbits
+       .space  8
+       .type   loc1, %object
+loc1:  .space  4
+       .type   loc2, %object
+loc2:  .space  4
+
diff --git a/ld/testsuite/ld-arm/ifunc-gdesc.ver b/ld/testsuite/ld-arm/ifunc-gdesc.ver
new file mode 100644 (file)
index 0000000..a82ffc4
--- /dev/null
@@ -0,0 +1,4 @@
+{
+global: foo;
+local: *;
+};
\ No newline at end of file