diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-06-29 08:38:43 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-06-29 08:38:58 -0700 |
commit | b287eca391bbb10e709fb8ba9a56be166ab2ff1d (patch) | |
tree | 5a26635b87621c0df49ebaac6ccdcc456f92e974 /gold/testsuite/pr20308_ld.S | |
parent | ad961eab9a010e79d17a4ea7e6bb977fe6dd86c2 (diff) | |
download | fsf-binutils-gdb-b287eca391bbb10e709fb8ba9a56be166ab2ff1d.zip fsf-binutils-gdb-b287eca391bbb10e709fb8ba9a56be166ab2ff1d.tar.gz fsf-binutils-gdb-b287eca391bbb10e709fb8ba9a56be166ab2ff1d.tar.bz2 |
gold: Support 386 TLS code sequences without PLT
There are extensions to 386 psABI:
https://groups.google.com/forum/#!topic/ia32-abi/awsRSvJOJfs
to call tls_get_addr via GOT:
call *___tls_get_addr@GOT(%reg)
where EBX register isn't required as GOT base.
Since direct call is 4-byte long and indirect call, is 5-byte long, the
extra one byte must be handled properly.
For general dynamic model, 7-byte lea instruction before call
instruction is replaced by 6-byte one to make room for indirect call.
For local dynamic model, we simply use 5-byte indirect call.
TLS linker optimization is updated to recognize new instruction
patterns. For local dynamic model to local exec model transition,
we generate a 6-byte lea instruction as nop, instead of a 1-byte nop
plus a 4-byte lea instruction.
PR gold/20308
* i386.cc (Target_i386::Relocate::relocate): Allow
R_386_GOT32X relocation against ___tls_get_addr.
(Target_i386::Relocate::tls_gd_to_ie): Support indirect
call to __tls_get_addr.
(Target_i386::Relocate::tls_gd_to_le): Likewise.
(Target_i386::Relocate::tls_ld_to_le): Likewise.
* testsuite/Makefile.am (check_PROGRAMS): Add pr20308a_test,
pr20308b_test, pr20308c_test, pr20308d_test, pr20308e_test.
(pr20308a_test_SOURCES): New.
(pr20308a_test_DEPENDENCIES): Likewise.
(pr20308a_test_CFLAGS): Likewise.
(pr20308a_test_LDFLAGS): Likewise.
(pr20308a_test_LDADD): Likewise.
(pr20308b_test_SOURCES): Likewise.
(pr20308b_test_DEPENDENCIES): Likewise.
(pr20308b_test_CFLAGS): Likewise.
(pr20308b_test_LDFLAGS): Likewise.
(pr20308b_test_LDADD): Likewise.
(pr20308c_test_SOURCES): Likewise.
(pr20308c_test_DEPENDENCIES): Likewise.
(pr20308c_test_CFLAGS): Likewise.
(pr20308c_test_LDFLAGS): Likewise.
(pr20308c_test_LDADD): Likewise.
(pr20308d_test_SOURCES): Likewise.
(pr20308d_test_DEPENDENCIES): Likewise.
(pr20308d_test_CFLAGS): Likewise.
(pr20308d_test_LDFLAGS): Likewise.
(pr20308d_test_LDADD): Likewise.
(pr20308e_test_SOURCES): Likewise.
(pr20308e_test_DEPENDENCIES): Likewise.
(pr20308e_test_CFLAGS): Likewise.
(pr20308e_test_LDFLAGS): Likewise.
(pr20308e_test_LDADD): Likewise.
(pr20308a.so): Likewise.
(pr20308b.so): Likewise.
(pr20308_gd.o): Likewise.
(pr20308_ld.o): Likewise.
(MOSTLYCLEANFILES): Add pr20308a.so pr20308b.so.
* testsuite/Makefile.in: Regenerated.
* testsuite/pr20308_def.c: New file.
* testsuite/pr20308_gd.S: Likewise.
* testsuite/pr20308_ld.S: Likewise.
* testsuite/pr20308_main.c: Likewise.
Diffstat (limited to 'gold/testsuite/pr20308_ld.S')
-rw-r--r-- | gold/testsuite/pr20308_ld.S | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/gold/testsuite/pr20308_ld.S b/gold/testsuite/pr20308_ld.S new file mode 100644 index 0000000..f1295cf --- /dev/null +++ b/gold/testsuite/pr20308_ld.S @@ -0,0 +1,71 @@ + .text + .p2align 4,,15 + .globl get_ld + .type get_ld, @function +get_ld: + pushl %ebx + call __x86.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + subl $8, %esp + leal ld@tlsldm(%ebx), %eax + call ___tls_get_addr@PLT + leal ld@dtpoff(%eax), %eax + addl $8, %esp + popl %ebx + ret + .size get_ld, .-get_ld + .p2align 4,,15 + .globl set_ld + .type set_ld, @function +set_ld: + pushl %ebx + call __x86.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + subl $8, %esp + leal ld@tlsldm(%ebx), %eax + call ___tls_get_addr@PLT + movl 16(%esp), %edx + leal ld@dtpoff(%eax), %eax + movl %edx, (%eax) + addl $8, %esp + popl %ebx + ret + .size set_ld, .-set_ld + .p2align 4,,15 + .globl test_ld + .type test_ld, @function +test_ld: + call __x86.get_pc_thunk.cx + addl $_GLOBAL_OFFSET_TABLE_, %ecx + subl $12, %esp + leal ld@tlsldm(%ecx), %eax + call *___tls_get_addr@GOT(%ecx) + movl 16(%esp), %ecx + leal ld@dtpoff(%eax), %eax + cmpl %ecx, (%eax) + sete %al + addl $12, %esp + movzbl %al, %eax + ret + .size test_ld, .-test_ld + .section .tbss,"awT",@nobits + .align 4 + .type ld, @object + .size ld, 4 +ld: + .zero 4 + .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat + .globl __x86.get_pc_thunk.bx + .hidden __x86.get_pc_thunk.bx + .type __x86.get_pc_thunk.bx, @function +__x86.get_pc_thunk.bx: + movl (%esp), %ebx + ret + .section .text.__x86.get_pc_thunk.cx,"axG",@progbits,__x86.get_pc_thunk.cx,comdat + .globl __x86.get_pc_thunk.cx + .hidden __x86.get_pc_thunk.cx + .type __x86.get_pc_thunk.cx, @function +__x86.get_pc_thunk.cx: + movl (%esp), %ecx + ret + .section .note.GNU-stack,"",@progbits |