x86: Don't change r_type when performing TLS transitions

Don't change r_type when performing TLS transitions to avoid getting
the relocation type with ELF32_R_TYPE again.

	* elf32-i386.c (elf_i386_relocate_section): Don't change r_type
	when calling elf_i386_tls_transition.  Don't use ELF32_R_TYPE
	to get the relocation type again.
	* elf64-x86-64.c (elf_x86_64_relocate_section): Don't change
	r_type when calling elf_x86_64_tls_transition.  Don't use
	ELF32_R_TYPE to get the relocation type again.
This commit is contained in:
H.J. Lu
2017-09-06 04:49:47 -07:00
parent fbd1b77155
commit 419414eafc
3 changed files with 36 additions and 25 deletions

View File

@ -1,3 +1,12 @@
2017-09-06 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_relocate_section): Don't change r_type
when calling elf_i386_tls_transition. Don't use ELF32_R_TYPE
to get the relocation type again.
* elf64-x86-64.c (elf_x86_64_relocate_section): Don't change
r_type when calling elf_x86_64_tls_transition. Don't use
ELF32_R_TYPE to get the relocation type again.
2017-09-05 H.J. Lu <hongjiu.lu@intel.com> 2017-09-05 H.J. Lu <hongjiu.lu@intel.com>
* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Properly set * elf64-x86-64.c (elf_x86_64_convert_load_reloc): Properly set

View File

@ -2182,7 +2182,7 @@ elf_i386_relocate_section (bfd *output_bfd,
relend = relocs + input_section->reloc_count; relend = relocs + input_section->reloc_count;
for (; rel < relend; wrel++, rel++) for (; rel < relend; wrel++, rel++)
{ {
unsigned int r_type; unsigned int r_type, r_type_tls;
reloc_howto_type *howto; reloc_howto_type *howto;
unsigned long r_symndx; unsigned long r_symndx;
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
@ -3029,17 +3029,18 @@ disallow_got32:
if (tls_type == GOT_TLS_IE) if (tls_type == GOT_TLS_IE)
tls_type = GOT_TLS_IE_NEG; tls_type = GOT_TLS_IE_NEG;
r_type_tls = r_type;
if (! elf_i386_tls_transition (info, input_bfd, if (! elf_i386_tls_transition (info, input_bfd,
input_section, contents, input_section, contents,
symtab_hdr, sym_hashes, symtab_hdr, sym_hashes,
&r_type, tls_type, rel, &r_type_tls, tls_type, rel,
relend, h, r_symndx, TRUE)) relend, h, r_symndx, TRUE))
return FALSE; return FALSE;
if (r_type == R_386_TLS_LE_32) if (r_type_tls == R_386_TLS_LE_32)
{ {
BFD_ASSERT (! unresolved_reloc); BFD_ASSERT (! unresolved_reloc);
if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) if (r_type == R_386_TLS_GD)
{ {
unsigned int type; unsigned int type;
bfd_vma roff; bfd_vma roff;
@ -3082,7 +3083,7 @@ disallow_got32:
wrel++; wrel++;
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) else if (r_type == R_386_TLS_GOTDESC)
{ {
/* GDesc -> LE transition. /* GDesc -> LE transition.
It's originally something like: It's originally something like:
@ -3107,7 +3108,7 @@ disallow_got32:
contents + roff); contents + roff);
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) else if (r_type == R_386_TLS_DESC_CALL)
{ {
/* GDesc -> LE transition. /* GDesc -> LE transition.
It's originally: It's originally:
@ -3122,7 +3123,7 @@ disallow_got32:
bfd_put_8 (output_bfd, 0x90, contents + roff + 1); bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE) else if (r_type == R_386_TLS_IE)
{ {
unsigned int val; unsigned int val;
@ -3216,7 +3217,7 @@ disallow_got32:
} }
else else
BFD_FAIL (); BFD_FAIL ();
if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE) if (r_type == R_386_TLS_GOTIE)
bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation), bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation),
contents + rel->r_offset); contents + rel->r_offset);
else else
@ -3359,13 +3360,13 @@ disallow_got32:
if (off >= (bfd_vma) -2 if (off >= (bfd_vma) -2
&& ! GOT_TLS_GDESC_P (tls_type)) && ! GOT_TLS_GDESC_P (tls_type))
abort (); abort ();
if (r_type == R_386_TLS_GOTDESC if (r_type_tls == R_386_TLS_GOTDESC
|| r_type == R_386_TLS_DESC_CALL) || r_type_tls == R_386_TLS_DESC_CALL)
{ {
relocation = htab->sgotplt_jump_table_size + offplt; relocation = htab->sgotplt_jump_table_size + offplt;
unresolved_reloc = FALSE; unresolved_reloc = FALSE;
} }
else if (r_type == ELF32_R_TYPE (rel->r_info)) else if (r_type_tls == r_type)
{ {
bfd_vma g_o_t = htab->elf.sgotplt->output_section->vma bfd_vma g_o_t = htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset; + htab->elf.sgotplt->output_offset;
@ -3378,7 +3379,7 @@ disallow_got32:
relocation += g_o_t; relocation += g_o_t;
unresolved_reloc = FALSE; unresolved_reloc = FALSE;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) else if (r_type == R_386_TLS_GD)
{ {
unsigned int val, type; unsigned int val, type;
bfd_vma roff; bfd_vma roff;
@ -3434,7 +3435,7 @@ disallow_got32:
wrel++; wrel++;
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) else if (r_type == R_386_TLS_GOTDESC)
{ {
/* GDesc -> IE transition. /* GDesc -> IE transition.
It's originally something like: It's originally something like:
@ -3473,7 +3474,7 @@ disallow_got32:
contents + roff); contents + roff);
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) else if (r_type == R_386_TLS_DESC_CALL)
{ {
/* GDesc -> IE transition. /* GDesc -> IE transition.
It's originally: It's originally:

View File

@ -2511,7 +2511,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
relend = relocs + input_section->reloc_count; relend = relocs + input_section->reloc_count;
for (; rel < relend; wrel++, rel++) for (; rel < relend; wrel++, rel++)
{ {
unsigned int r_type; unsigned int r_type, r_type_tls;
reloc_howto_type *howto; reloc_howto_type *howto;
unsigned long r_symndx; unsigned long r_symndx;
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
@ -3413,20 +3413,21 @@ direct:
else if (h != NULL) else if (h != NULL)
tls_type = elf_x86_hash_entry (h)->tls_type; tls_type = elf_x86_hash_entry (h)->tls_type;
r_type_tls = r_type;
if (! elf_x86_64_tls_transition (info, input_bfd, if (! elf_x86_64_tls_transition (info, input_bfd,
input_section, contents, input_section, contents,
symtab_hdr, sym_hashes, symtab_hdr, sym_hashes,
&r_type, tls_type, rel, &r_type_tls, tls_type, rel,
relend, h, r_symndx, TRUE)) relend, h, r_symndx, TRUE))
return FALSE; return FALSE;
if (r_type == R_X86_64_TPOFF32) if (r_type_tls == R_X86_64_TPOFF32)
{ {
bfd_vma roff = rel->r_offset; bfd_vma roff = rel->r_offset;
BFD_ASSERT (! unresolved_reloc); BFD_ASSERT (! unresolved_reloc);
if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSGD) if (r_type == R_X86_64_TLSGD)
{ {
/* GD->LE transition. For 64bit, change /* GD->LE transition. For 64bit, change
.byte 0x66; leaq foo@tlsgd(%rip), %rdi .byte 0x66; leaq foo@tlsgd(%rip), %rdi
@ -3489,7 +3490,7 @@ direct:
wrel++; wrel++;
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) else if (r_type == R_X86_64_GOTPC32_TLSDESC)
{ {
/* GDesc -> LE transition. /* GDesc -> LE transition.
It's originally something like: It's originally something like:
@ -3512,7 +3513,7 @@ direct:
contents + roff); contents + roff);
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) else if (r_type == R_X86_64_TLSDESC_CALL)
{ {
/* GDesc -> LE transition. /* GDesc -> LE transition.
It's originally: It's originally:
@ -3523,7 +3524,7 @@ direct:
bfd_put_8 (output_bfd, 0x90, contents + roff + 1); bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTTPOFF) else if (r_type == R_X86_64_GOTTPOFF)
{ {
/* IE->LE transition: /* IE->LE transition:
For 64bit, originally it can be one of: For 64bit, originally it can be one of:
@ -3701,7 +3702,7 @@ direct:
if (off >= (bfd_vma) -2 if (off >= (bfd_vma) -2
&& ! GOT_TLS_GDESC_P (tls_type)) && ! GOT_TLS_GDESC_P (tls_type))
abort (); abort ();
if (r_type == ELF32_R_TYPE (rel->r_info)) if (r_type_tls == r_type)
{ {
if (r_type == R_X86_64_GOTPC32_TLSDESC if (r_type == R_X86_64_GOTPC32_TLSDESC
|| r_type == R_X86_64_TLSDESC_CALL) || r_type == R_X86_64_TLSDESC_CALL)
@ -3717,7 +3718,7 @@ direct:
{ {
bfd_vma roff = rel->r_offset; bfd_vma roff = rel->r_offset;
if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSGD) if (r_type == R_X86_64_TLSGD)
{ {
/* GD->IE transition. For 64bit, change /* GD->IE transition. For 64bit, change
.byte 0x66; leaq foo@tlsgd(%rip), %rdi .byte 0x66; leaq foo@tlsgd(%rip), %rdi
@ -3786,7 +3787,7 @@ direct:
wrel++; wrel++;
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC) else if (r_type == R_X86_64_GOTPC32_TLSDESC)
{ {
/* GDesc -> IE transition. /* GDesc -> IE transition.
It's originally something like: It's originally something like:
@ -3811,7 +3812,7 @@ direct:
contents + roff); contents + roff);
continue; continue;
} }
else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL) else if (r_type == R_X86_64_TLSDESC_CALL)
{ {
/* GDesc -> IE transition. /* GDesc -> IE transition.
It's originally: It's originally: