Support i386 TLS code sequences without PLT
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 8 Jun 2016 18:59:47 +0000 (11:59 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 8 Jun 2016 19:01:50 +0000 (12:01 -0700)
commit6eaa7fb59b32beaca017abf139a67bbe87592d9b
tree41d99fa60a1380cb5acc9290a014508f2852859b
parent010bc3ce6c651455e3a27c0857021c228780523c
Support i386 TLS code sequences without PLT

We can generate i386 TLS code sequences for general and local dynamic
models without PLT, which uses indirect call via GOT:

call *___tls_get_addr@GOT(%reg)

where EBX register isn't required as GOT base, instead of direct call:

call ___tls_get_addr[@PLT]

which requires EBX register 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.  Since linker may convert

call ___tls_get_addr[@PLT]

to

addr32 call ____tls_get_addr

when producing static executable, both patterns are recognized.

bfd/

* elf64-i386.c (elf_i386_link_hash_entry): Add tls_get_addr.
(elf_i386_link_hash_newfunc): Initialize tls_get_addr to 2.
(elf_i386_check_tls_transition): Check indirect call and direct
call with the addr32 prefix for general and local dynamic models.
Set the tls_get_addr feild.
(elf_i386_convert_load_reloc): Always use addr32 prefix for
indirect ___tls_get_addr call via GOT.
(elf_i386_relocate_section): Handle GD->LE, GD->IE and LD->LE
transitions with indirect call and direct call with the addr32
prefix.

ld/

* testsuite/ld-i386/i386.exp: Run libtlspic2.so, tlsbin2,
tlsgd3, tlsld2, tlsgd4, tlspie3a, tlspie3b and tlspie3c.
* testsuite/ld-i386/pass.out: New file.
* testsuite/ld-i386/tls-def1.c: Likewise.
* testsuite/ld-i386/tls-gd1.S: Likewise.
* testsuite/ld-i386/tls-ld1.S: Likewise.
* testsuite/ld-i386/tls-main1.c: Likewise.
* testsuite/ld-i386/tls.exp: Likewise.
* testsuite/ld-i386/tlsbin2-nacl.rd: Likewise.
* testsuite/ld-i386/tlsbin2.dd: Likewise.
* testsuite/ld-i386/tlsbin2.rd: Likewise.
* testsuite/ld-i386/tlsbin2.sd: Likewise.
* testsuite/ld-i386/tlsbin2.td: Likewise.
* testsuite/ld-i386/tlsbinpic2.s: Likewise.
* testsuite/ld-i386/tlsgd3.dd: Likewise.
* testsuite/ld-i386/tlsgd3.s: Likewise.
* testsuite/ld-i386/tlsgd4.d: Likewise.
* testsuite/ld-i386/tlsgd4.s: Likewise.
* testsuite/ld-i386/tlsld2.s: Likewise.
* testsuite/ld-i386/tlspic2-nacl.rd: Likewise.
* testsuite/ld-i386/tlspic2.dd: Likewise.
* testsuite/ld-i386/tlspic2.rd: Likewise.
* testsuite/ld-i386/tlspic2.sd: Likewise.
* testsuite/ld-i386/tlspic2.td: Likewise.
* testsuite/ld-i386/tlspic3.s: Likewise.
* testsuite/ld-i386/tlspie3.s: Likewise.
* testsuite/ld-i386/tlspie3a.d: Likewise.
* testsuite/ld-i386/tlspie3b.d: Likewise.
* testsuite/ld-i386/tlspie3c.d: Likewise.
32 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
ld/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pass.out [new file with mode: 0644]
ld/testsuite/ld-i386/tls-def1.c [new file with mode: 0644]
ld/testsuite/ld-i386/tls-gd1.S [new file with mode: 0644]
ld/testsuite/ld-i386/tls-ld1.S [new file with mode: 0644]
ld/testsuite/ld-i386/tls-main1.c [new file with mode: 0644]
ld/testsuite/ld-i386/tls.exp [new file with mode: 0644]
ld/testsuite/ld-i386/tlsbin2-nacl.rd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsbin2.dd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsbin2.rd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsbin2.sd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsbin2.td [new file with mode: 0644]
ld/testsuite/ld-i386/tlsbinpic2.s [new file with mode: 0644]
ld/testsuite/ld-i386/tlsgd3.dd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsgd3.s [new file with mode: 0644]
ld/testsuite/ld-i386/tlsgd4.d [new file with mode: 0644]
ld/testsuite/ld-i386/tlsgd4.s [new file with mode: 0644]
ld/testsuite/ld-i386/tlsld2.dd [new file with mode: 0644]
ld/testsuite/ld-i386/tlsld2.s [new file with mode: 0644]
ld/testsuite/ld-i386/tlspic2-nacl.rd [new file with mode: 0644]
ld/testsuite/ld-i386/tlspic2.dd [new file with mode: 0644]
ld/testsuite/ld-i386/tlspic2.rd [new file with mode: 0644]
ld/testsuite/ld-i386/tlspic2.sd [new file with mode: 0644]
ld/testsuite/ld-i386/tlspic2.td [new file with mode: 0644]
ld/testsuite/ld-i386/tlspic3.s [new file with mode: 0644]
ld/testsuite/ld-i386/tlspie3.s [new file with mode: 0644]
ld/testsuite/ld-i386/tlspie3a.d [new file with mode: 0644]
ld/testsuite/ld-i386/tlspie3b.d [new file with mode: 0644]
ld/testsuite/ld-i386/tlspie3c.d [new file with mode: 0644]