mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 15:18:37 +08:00
x86: Lookup __tls_get_addr or ___tls_get_addr once
Instead of checking if a symbol is __tls_get_addr or ___tls_get_addr, we check if there is a reference to __tls_get_addr or ___tls_get_addr before starting relocation check. * elf32-i386.c (elf_i386_link_hash_entry): Change tls_get_addr to 1 bit. (elf_i386_link_hash_newfunc): Initialize tls_get_addr to 0. (elf_i386_check_tls_transition): Check tls_get_addr directly. (elf_i386_convert_load_reloc): Update tls_get_addr check. (elf_i386_link_check_relocs): New function. (bfd_elf32_bfd_link_check_relocs): New. * elf64-x86-64.c (elf_x86_64_link_hash_entry): Change tls_get_addr to 1 bit. (elf_x86_64_link_hash_newfunc): Initialize tls_get_addr to 0. (elf_x86_64_check_tls_transition): Check tls_get_addr directly. (elf_x86_64_convert_load_reloc): Update tls_get_addr check. (elf_x86_64_link_check_relocs): New function. (bfd_elf64_bfd_link_check_relocs): New. (bfd_elf32_bfd_link_check_relocs): Likewise.
This commit is contained in:
@ -1,3 +1,21 @@
|
|||||||
|
2017-08-06 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* elf32-i386.c (elf_i386_link_hash_entry): Change tls_get_addr
|
||||||
|
to 1 bit.
|
||||||
|
(elf_i386_link_hash_newfunc): Initialize tls_get_addr to 0.
|
||||||
|
(elf_i386_check_tls_transition): Check tls_get_addr directly.
|
||||||
|
(elf_i386_convert_load_reloc): Update tls_get_addr check.
|
||||||
|
(elf_i386_link_check_relocs): New function.
|
||||||
|
(bfd_elf32_bfd_link_check_relocs): New.
|
||||||
|
* elf64-x86-64.c (elf_x86_64_link_hash_entry): Change tls_get_addr
|
||||||
|
to 1 bit.
|
||||||
|
(elf_x86_64_link_hash_newfunc): Initialize tls_get_addr to 0.
|
||||||
|
(elf_x86_64_check_tls_transition): Check tls_get_addr directly.
|
||||||
|
(elf_x86_64_convert_load_reloc): Update tls_get_addr check.
|
||||||
|
(elf_x86_64_link_check_relocs): New function.
|
||||||
|
(bfd_elf64_bfd_link_check_relocs): New.
|
||||||
|
(bfd_elf32_bfd_link_check_relocs): Likewise.
|
||||||
|
|
||||||
2017-08-06 H.J. Lu <hongjiu.lu@intel.com>
|
2017-08-06 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR ld/21903:
|
PR ld/21903:
|
||||||
|
@ -995,10 +995,8 @@ struct elf_i386_link_hash_entry
|
|||||||
/* Don't call finish_dynamic_symbol on this symbol. */
|
/* Don't call finish_dynamic_symbol on this symbol. */
|
||||||
unsigned int no_finish_dynamic_symbol : 1;
|
unsigned int no_finish_dynamic_symbol : 1;
|
||||||
|
|
||||||
/* 0: symbol isn't ___tls_get_addr.
|
/* TRUE if symbol symbol is __tls_get_addr. */
|
||||||
1: symbol is ___tls_get_addr.
|
unsigned int tls_get_addr : 1;
|
||||||
2: symbol is unknown. */
|
|
||||||
unsigned int tls_get_addr : 2;
|
|
||||||
|
|
||||||
/* Reference count of C/C++ function pointer relocations in read-write
|
/* Reference count of C/C++ function pointer relocations in read-write
|
||||||
section which can be resolved at run-time. */
|
section which can be resolved at run-time. */
|
||||||
@ -1149,7 +1147,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
|
|||||||
eh->has_got_reloc = 0;
|
eh->has_got_reloc = 0;
|
||||||
eh->has_non_got_reloc = 0;
|
eh->has_non_got_reloc = 0;
|
||||||
eh->no_finish_dynamic_symbol = 0;
|
eh->no_finish_dynamic_symbol = 0;
|
||||||
eh->tls_get_addr = 2;
|
eh->tls_get_addr = 0;
|
||||||
eh->func_pointer_refcount = 0;
|
eh->func_pointer_refcount = 0;
|
||||||
eh->plt_got.offset = (bfd_vma) -1;
|
eh->plt_got.offset = (bfd_vma) -1;
|
||||||
eh->tlsdesc_got = (bfd_vma) -1;
|
eh->tlsdesc_got = (bfd_vma) -1;
|
||||||
@ -1378,7 +1376,7 @@ elf_i386_check_tls_transition (asection *sec,
|
|||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
bfd_vma offset;
|
bfd_vma offset;
|
||||||
bfd_byte *call;
|
bfd_byte *call;
|
||||||
bfd_boolean indirect_call, tls_get_addr;
|
bfd_boolean indirect_call;
|
||||||
|
|
||||||
offset = rel->r_offset;
|
offset = rel->r_offset;
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
@ -1483,29 +1481,9 @@ elf_i386_check_tls_transition (asection *sec,
|
|||||||
if (r_symndx < symtab_hdr->sh_info)
|
if (r_symndx < symtab_hdr->sh_info)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
tls_get_addr = FALSE;
|
|
||||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||||
if (h != NULL && h->root.root.string != NULL)
|
if (h == NULL
|
||||||
{
|
|| !((struct elf_i386_link_hash_entry *) h)->tls_get_addr)
|
||||||
struct elf_i386_link_hash_entry *eh
|
|
||||||
= (struct elf_i386_link_hash_entry *) h;
|
|
||||||
tls_get_addr = eh->tls_get_addr == 1;
|
|
||||||
if (eh->tls_get_addr > 1)
|
|
||||||
{
|
|
||||||
/* Use strncmp to check ___tls_get_addr since
|
|
||||||
___tls_get_addr may be versioned. */
|
|
||||||
if (strncmp (h->root.root.string, "___tls_get_addr", 15)
|
|
||||||
== 0)
|
|
||||||
{
|
|
||||||
eh->tls_get_addr = 1;
|
|
||||||
tls_get_addr = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
eh->tls_get_addr = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tls_get_addr)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else if (indirect_call)
|
else if (indirect_call)
|
||||||
return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X);
|
return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X);
|
||||||
@ -1863,7 +1841,7 @@ convert_branch:
|
|||||||
modrm = 0xe8;
|
modrm = 0xe8;
|
||||||
/* To support TLS optimization, always use addr32 prefix
|
/* To support TLS optimization, always use addr32 prefix
|
||||||
for "call *___tls_get_addr@GOT(%reg)". */
|
for "call *___tls_get_addr@GOT(%reg)". */
|
||||||
if (eh && eh->tls_get_addr == 1)
|
if (eh && eh->tls_get_addr)
|
||||||
{
|
{
|
||||||
nop = 0x67;
|
nop = 0x67;
|
||||||
nop_offset = irel->r_offset - 2;
|
nop_offset = irel->r_offset - 2;
|
||||||
@ -7148,6 +7126,23 @@ error_alignment:
|
|||||||
return pbfd;
|
return pbfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
elf_i386_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
if (!bfd_link_relocatable (info))
|
||||||
|
{
|
||||||
|
/* Check for ___tls_get_addr reference. */
|
||||||
|
struct elf_link_hash_entry *h;
|
||||||
|
h = elf_link_hash_lookup (elf_hash_table (info), "___tls_get_addr",
|
||||||
|
FALSE, FALSE, FALSE);
|
||||||
|
if (h != NULL)
|
||||||
|
((struct elf_i386_link_hash_entry *) h)->tls_get_addr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke the regular ELF backend linker to do all the work. */
|
||||||
|
return _bfd_elf_link_check_relocs (abfd, info);
|
||||||
|
}
|
||||||
|
|
||||||
#define TARGET_LITTLE_SYM i386_elf32_vec
|
#define TARGET_LITTLE_SYM i386_elf32_vec
|
||||||
#define TARGET_LITTLE_NAME "elf32-i386"
|
#define TARGET_LITTLE_NAME "elf32-i386"
|
||||||
#define ELF_ARCH bfd_arch_i386
|
#define ELF_ARCH bfd_arch_i386
|
||||||
@ -7178,6 +7173,7 @@ error_alignment:
|
|||||||
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
|
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
|
||||||
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
|
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
|
||||||
#define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab
|
#define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab
|
||||||
|
#define bfd_elf32_bfd_link_check_relocs elf_i386_link_check_relocs
|
||||||
|
|
||||||
#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol
|
#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol
|
||||||
#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible
|
#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible
|
||||||
|
@ -1101,10 +1101,8 @@ struct elf_x86_64_link_hash_entry
|
|||||||
/* Don't call finish_dynamic_symbol on this symbol. */
|
/* Don't call finish_dynamic_symbol on this symbol. */
|
||||||
unsigned int no_finish_dynamic_symbol : 1;
|
unsigned int no_finish_dynamic_symbol : 1;
|
||||||
|
|
||||||
/* 0: symbol isn't __tls_get_addr.
|
/* TRUE if symbol symbol is __tls_get_addr. */
|
||||||
1: symbol is __tls_get_addr.
|
unsigned int tls_get_addr : 1;
|
||||||
2: symbol is unknown. */
|
|
||||||
unsigned int tls_get_addr : 2;
|
|
||||||
|
|
||||||
/* Reference count of C/C++ function pointer relocations in read-write
|
/* Reference count of C/C++ function pointer relocations in read-write
|
||||||
section which can be resolved at run-time. */
|
section which can be resolved at run-time. */
|
||||||
@ -1264,7 +1262,7 @@ elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry,
|
|||||||
eh->has_got_reloc = 0;
|
eh->has_got_reloc = 0;
|
||||||
eh->has_non_got_reloc = 0;
|
eh->has_non_got_reloc = 0;
|
||||||
eh->no_finish_dynamic_symbol = 0;
|
eh->no_finish_dynamic_symbol = 0;
|
||||||
eh->tls_get_addr = 2;
|
eh->tls_get_addr = 0;
|
||||||
eh->func_pointer_refcount = 0;
|
eh->func_pointer_refcount = 0;
|
||||||
eh->plt_second.offset = (bfd_vma) -1;
|
eh->plt_second.offset = (bfd_vma) -1;
|
||||||
eh->plt_got.offset = (bfd_vma) -1;
|
eh->plt_got.offset = (bfd_vma) -1;
|
||||||
@ -1527,7 +1525,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|||||||
bfd_vma offset;
|
bfd_vma offset;
|
||||||
struct elf_x86_64_link_hash_table *htab;
|
struct elf_x86_64_link_hash_table *htab;
|
||||||
bfd_byte *call;
|
bfd_byte *call;
|
||||||
bfd_boolean indirect_call, tls_get_addr;
|
bfd_boolean indirect_call;
|
||||||
|
|
||||||
htab = elf_x86_64_hash_table (info);
|
htab = elf_x86_64_hash_table (info);
|
||||||
offset = rel->r_offset;
|
offset = rel->r_offset;
|
||||||
@ -1667,29 +1665,9 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|||||||
if (r_symndx < symtab_hdr->sh_info)
|
if (r_symndx < symtab_hdr->sh_info)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
tls_get_addr = FALSE;
|
|
||||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||||
if (h != NULL && h->root.root.string != NULL)
|
if (h == NULL
|
||||||
{
|
|| !((struct elf_x86_64_link_hash_entry *) h)->tls_get_addr)
|
||||||
struct elf_x86_64_link_hash_entry *eh
|
|
||||||
= (struct elf_x86_64_link_hash_entry *) h;
|
|
||||||
tls_get_addr = eh->tls_get_addr == 1;
|
|
||||||
if (eh->tls_get_addr > 1)
|
|
||||||
{
|
|
||||||
/* Use strncmp to check __tls_get_addr since
|
|
||||||
__tls_get_addr may be versioned. */
|
|
||||||
if (strncmp (h->root.root.string, "__tls_get_addr", 14)
|
|
||||||
== 0)
|
|
||||||
{
|
|
||||||
eh->tls_get_addr = 1;
|
|
||||||
tls_get_addr = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
eh->tls_get_addr = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tls_get_addr)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else if (largepic)
|
else if (largepic)
|
||||||
return ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLTOFF64;
|
return ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLTOFF64;
|
||||||
@ -2253,7 +2231,7 @@ convert:
|
|||||||
modrm = 0xe8;
|
modrm = 0xe8;
|
||||||
/* To support TLS optimization, always use addr32 prefix for
|
/* To support TLS optimization, always use addr32 prefix for
|
||||||
"call *__tls_get_addr@GOTPCREL(%rip)". */
|
"call *__tls_get_addr@GOTPCREL(%rip)". */
|
||||||
if (eh && eh->tls_get_addr == 1)
|
if (eh && eh->tls_get_addr)
|
||||||
{
|
{
|
||||||
nop = 0x67;
|
nop = 0x67;
|
||||||
nop_offset = irel->r_offset - 2;
|
nop_offset = irel->r_offset - 2;
|
||||||
@ -7715,6 +7693,23 @@ error_alignment:
|
|||||||
return pbfd;
|
return pbfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
elf_x86_64_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
|
||||||
|
{
|
||||||
|
if (!bfd_link_relocatable (info))
|
||||||
|
{
|
||||||
|
/* Check for __tls_get_addr reference. */
|
||||||
|
struct elf_link_hash_entry *h;
|
||||||
|
h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr",
|
||||||
|
FALSE, FALSE, FALSE);
|
||||||
|
if (h != NULL)
|
||||||
|
((struct elf_x86_64_link_hash_entry *) h)->tls_get_addr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke the regular ELF backend linker to do all the work. */
|
||||||
|
return _bfd_elf_link_check_relocs (abfd, info);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct bfd_elf_special_section
|
static const struct bfd_elf_special_section
|
||||||
elf_x86_64_special_sections[]=
|
elf_x86_64_special_sections[]=
|
||||||
{
|
{
|
||||||
@ -7779,6 +7774,7 @@ elf_x86_64_special_sections[]=
|
|||||||
#define elf_backend_object_p elf64_x86_64_elf_object_p
|
#define elf_backend_object_p elf64_x86_64_elf_object_p
|
||||||
#define bfd_elf64_mkobject elf_x86_64_mkobject
|
#define bfd_elf64_mkobject elf_x86_64_mkobject
|
||||||
#define bfd_elf64_get_synthetic_symtab elf_x86_64_get_synthetic_symtab
|
#define bfd_elf64_get_synthetic_symtab elf_x86_64_get_synthetic_symtab
|
||||||
|
#define bfd_elf64_bfd_link_check_relocs elf_x86_64_link_check_relocs
|
||||||
|
|
||||||
#define elf_backend_section_from_shdr \
|
#define elf_backend_section_from_shdr \
|
||||||
elf_x86_64_section_from_shdr
|
elf_x86_64_section_from_shdr
|
||||||
@ -8078,6 +8074,8 @@ elf32_x86_64_nacl_elf_object_p (bfd *abfd)
|
|||||||
elf_x86_64_mkobject
|
elf_x86_64_mkobject
|
||||||
#define bfd_elf32_get_synthetic_symtab \
|
#define bfd_elf32_get_synthetic_symtab \
|
||||||
elf_x86_64_get_synthetic_symtab
|
elf_x86_64_get_synthetic_symtab
|
||||||
|
#define bfd_elf32_bfd_link_check_relocs \
|
||||||
|
elf_x86_64_link_check_relocs
|
||||||
|
|
||||||
#undef elf_backend_object_p
|
#undef elf_backend_object_p
|
||||||
#define elf_backend_object_p \
|
#define elf_backend_object_p \
|
||||||
|
Reference in New Issue
Block a user