Fix support for i386 TLS GD-to-IE optimization.
There are two cases to support, one with an SIB-form (6-byte) LEA, the other with a 5-byte LEA and a NOP after the call __tls_get_addr. Gold did not yet support the second case. This patch adds that support. gold/ PR gold/18106 * i386.cc (Target_i386::Relocate::tls_gd_to_ie): Fix support for non-SIB form of lea, with nop after the call.
This commit is contained in:
parent
bccffdfdf2
commit
152f702439
2 changed files with 14 additions and 19 deletions
|
@ -1,3 +1,9 @@
|
|||
2015-03-22 Cary Coutant <cary@google.com>
|
||||
|
||||
PR gold/18106
|
||||
* i386.cc (Target_i386::Relocate::tls_gd_to_ie): Fix support for
|
||||
non-SIB form of lea, with nop after the call.
|
||||
|
||||
2015-03-21 Cary Coutant <cary@google.com>
|
||||
|
||||
PR gold/14217
|
||||
|
|
27
gold/i386.cc
27
gold/i386.cc
|
@ -3253,6 +3253,8 @@ Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo,
|
|||
{
|
||||
// leal foo(,%ebx,1),%eax; call ___tls_get_addr
|
||||
// ==> movl %gs:0,%eax; addl foo@gotntpoff(%ebx),%eax
|
||||
// leal foo(%ebx),%eax; call ___tls_get_addr; nop
|
||||
// ==> movl %gs:0,%eax; addl foo@gotntpoff(%ebx),%eax
|
||||
|
||||
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
|
||||
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 9);
|
||||
|
@ -3264,10 +3266,7 @@ Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo,
|
|||
op2 == 0x8d || op2 == 0x04);
|
||||
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
|
||||
|
||||
int roff = 5;
|
||||
|
||||
// FIXME: For now, support only the first (SIB) form.
|
||||
tls::check_tls(relinfo, relnum, rel.get_r_offset(), op2 == 0x04);
|
||||
int roff;
|
||||
|
||||
if (op2 == 0x04)
|
||||
{
|
||||
|
@ -3275,28 +3274,18 @@ Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo,
|
|||
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d);
|
||||
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
|
||||
((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
|
||||
memcpy(view - 3, "\x65\xa1\0\0\0\0\x03\x83\0\0\0", 12);
|
||||
roff = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 10);
|
||||
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
|
||||
(op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
|
||||
if (rel.get_r_offset() + 9 < view_size
|
||||
&& view[9] == 0x90)
|
||||
{
|
||||
// FIXME: This is not the right instruction sequence.
|
||||
// There is a trailing nop. Use the size byte subl.
|
||||
memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
|
||||
roff = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: This is not the right instruction sequence.
|
||||
// Use the five byte subl.
|
||||
memcpy(view - 2, "\x65\xa1\0\0\0\0\x2d\0\0\0", 11);
|
||||
}
|
||||
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[9] == 0x90);
|
||||
roff = 6;
|
||||
}
|
||||
|
||||
memcpy(view + roff - 8, "\x65\xa1\0\0\0\0\x03\x83\0\0\0", 12);
|
||||
Relocate_functions<32, false>::rel32(view + roff, value);
|
||||
|
||||
// The next reloc should be a PLT32 reloc against __tls_get_addr.
|
||||
|
|
Loading…
Reference in a new issue