mirror of
https://git.yoctoproject.org/poky
synced 2026-03-19 05:39:39 +01:00
CVE-2025-1179-pre.patch is dependency patch for CVE-2025-1179.patch Upstream-Status: Submitted [https://sourceware.org/pipermail/binutils/2025-May/141322.html && https://sourceware.org/pipermail/binutils/2025-May/141321.html] CVE: CVE-2025-1179 cherry picked from upstream commit: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=67e30b15212adc1502b898a1ca224fdf65dc110d https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1d68a49ac5d71b648304f69af978fce0f4413800 (From OE-Core rev: 8f54548f784ef60eaf7fb6b3f539d48b0f7192a3) Signed-off-by: Harish Sadineni <Harish.Sadineni@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
1087 lines
35 KiB
Diff
1087 lines
35 KiB
Diff
From 1d68a49ac5d71b648304f69af978fce0f4413800 Mon Sep 17 00:00:00 2001
|
|
From: "H.J. Lu" <hjl.tools@gmail.com>
|
|
Date: Tue, 23 Jul 2024 23:39:50 -0700
|
|
Subject: [PATCH 1/2] x86: Improve TLS transition error check
|
|
|
|
Provide detailed TLS transition errors when unsupported instructions are
|
|
used. Treat R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_6_GOTTPOFF as
|
|
R_X86_64_GOTTPOFF when performing TLS transition.
|
|
|
|
bfd/
|
|
|
|
PR ld/32017
|
|
* elf32-i386.c (elf_i386_check_tls_transition): Return different
|
|
enums for different errors.
|
|
(elf_i386_tls_transition): Change argument from r_symndx to sym.
|
|
Call _bfd_x86_elf_link_report_tls_transition_error to report TLS
|
|
transition errors.
|
|
(elf_i386_scan_relocs): Pass isym instead of r_symndx to
|
|
elf_i386_tls_transition.
|
|
(elf_i386_relocate_section): Pass sym instead of r_symndx to
|
|
elf_i386_tls_transition.
|
|
* elf64-x86-64.c (elf_x86_64_check_tls_transition): Return
|
|
different enums for different errors.
|
|
(elf_x86_64_tls_transition): Change argument from r_symndx to sym.
|
|
Treat R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_6_GOTTPOFF as
|
|
R_X86_64_GOTTPOFF. Call
|
|
_bfd_x86_elf_link_report_tls_transition_error to report TLS
|
|
transition errors.
|
|
(elf_x86_64_scan_relocs): Pass isym instead of r_symndx to
|
|
elf_x86_64_tls_transition.
|
|
(elf_x86_64_relocate_section): Pass sym instead of r_symndx to
|
|
elf_x86_64_tls_transition.
|
|
* elfxx-x86.c (_bfd_x86_elf_link_report_tls_transition_error): New.
|
|
* elfxx-x86.h (elf_x86_tls_error_type): Likewise.
|
|
(_bfd_x86_elf_link_report_tls_transition_error): Likewise.
|
|
|
|
ld/
|
|
|
|
PR ld/32017
|
|
* testsuite/ld-i386/i386.exp: Run tlsgdesc1 and tlsgdesc2.
|
|
* testsuite/ld-i386/tlsie2.d: Updated.
|
|
* testsuite/ld-i386/tlsie3.d: Likewise.
|
|
* testsuite/ld-i386/tlsie4.d: Likewise.
|
|
* testsuite/ld-i386/tlsie5.d: Likewise.
|
|
* testsuite/ld-x86-64/tlsie2.d: Likewise.
|
|
* testsuite/ld-x86-64/tlsie3.d: Likewise.
|
|
* testsuite/ld-i386/tlsgdesc1.d: New file.
|
|
* testsuite/ld-i386/tlsgdesc1.s: Likewise.
|
|
* testsuite/ld-i386/tlsgdesc2.d: Likewise.
|
|
* testsuite/ld-i386/tlsgdesc2.s: Likewise.
|
|
* testsuite/ld-x86-64/tlsdesc3.d: Likewise.
|
|
* testsuite/ld-x86-64/tlsdesc3.s: Likewise.
|
|
* testsuite/ld-x86-64/tlsdesc4.d: Likewise.
|
|
* testsuite/ld-x86-64/tlsdesc4.s: Likewise.
|
|
* testsuite/ld-x86-64/tlsie5.d: Likewise.
|
|
* testsuite/ld-x86-64/tlsie5.s: Likewise.
|
|
* testsuite/ld-x86-64/x86-64.exp: Run tlsie5, tlsdesc3 and
|
|
tlsdesc4.
|
|
|
|
(cherry picked from commit:1d68a49ac5d71b648304f69af978fce0f4413800)
|
|
Upstream-Status: Submitted [https://sourceware.org/pipermail/binutils/2025-May/141322.html]
|
|
CVE: CVE-2025-1179
|
|
|
|
Signed-off-by: Harish Sadineni <Harish.Sadineni@windriver.com>
|
|
---
|
|
bfd/elf32-i386.c | 118 +++++++++++++-------------
|
|
bfd/elf64-x86-64.c | 133 ++++++++++++++++--------------
|
|
bfd/elfxx-x86.c | 85 +++++++++++++++++++
|
|
bfd/elfxx-x86.h | 18 ++++
|
|
ld/testsuite/ld-i386/i386.exp | 2 +
|
|
ld/testsuite/ld-i386/tlsgdesc1.d | 4 +
|
|
ld/testsuite/ld-i386/tlsgdesc1.s | 11 +++
|
|
ld/testsuite/ld-i386/tlsgdesc2.d | 4 +
|
|
ld/testsuite/ld-i386/tlsgdesc2.s | 11 +++
|
|
ld/testsuite/ld-i386/tlsie2.d | 2 +-
|
|
ld/testsuite/ld-i386/tlsie3.d | 2 +-
|
|
ld/testsuite/ld-i386/tlsie4.d | 2 +-
|
|
ld/testsuite/ld-i386/tlsie5.d | 2 +-
|
|
ld/testsuite/ld-x86-64/tlsdesc3.d | 4 +
|
|
ld/testsuite/ld-x86-64/tlsdesc3.s | 13 +++
|
|
ld/testsuite/ld-x86-64/tlsdesc4.d | 4 +
|
|
ld/testsuite/ld-x86-64/tlsdesc4.s | 13 +++
|
|
ld/testsuite/ld-x86-64/tlsie2.d | 2 +-
|
|
ld/testsuite/ld-x86-64/tlsie3.d | 2 +-
|
|
ld/testsuite/ld-x86-64/tlsie5.d | 4 +
|
|
ld/testsuite/ld-x86-64/tlsie5.s | 12 +++
|
|
ld/testsuite/ld-x86-64/x86-64.exp | 3 +
|
|
22 files changed, 319 insertions(+), 132 deletions(-)
|
|
create mode 100644 ld/testsuite/ld-i386/tlsgdesc1.d
|
|
create mode 100644 ld/testsuite/ld-i386/tlsgdesc1.s
|
|
create mode 100644 ld/testsuite/ld-i386/tlsgdesc2.d
|
|
create mode 100644 ld/testsuite/ld-i386/tlsgdesc2.s
|
|
create mode 100644 ld/testsuite/ld-x86-64/tlsdesc3.d
|
|
create mode 100644 ld/testsuite/ld-x86-64/tlsdesc3.s
|
|
create mode 100644 ld/testsuite/ld-x86-64/tlsdesc4.d
|
|
create mode 100644 ld/testsuite/ld-x86-64/tlsdesc4.s
|
|
create mode 100644 ld/testsuite/ld-x86-64/tlsie5.d
|
|
create mode 100644 ld/testsuite/ld-x86-64/tlsie5.s
|
|
|
|
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
|
|
index e2f88a11487..18a28d2491c 100644
|
|
--- a/bfd/elf32-i386.c
|
|
+++ b/bfd/elf32-i386.c
|
|
@@ -839,7 +839,7 @@ static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt =
|
|
/* Return TRUE if the TLS access code sequence support transition
|
|
from R_TYPE. */
|
|
|
|
-static bool
|
|
+static enum elf_x86_tls_error_type
|
|
elf_i386_check_tls_transition (asection *sec,
|
|
bfd_byte *contents,
|
|
Elf_Internal_Shdr *symtab_hdr,
|
|
@@ -861,7 +861,7 @@ elf_i386_check_tls_transition (asection *sec,
|
|
case R_386_TLS_GD:
|
|
case R_386_TLS_LDM:
|
|
if (offset < 2 || (rel + 1) >= relend)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
indirect_call = false;
|
|
call = contents + offset + 4;
|
|
@@ -884,19 +884,19 @@ elf_i386_check_tls_transition (asection *sec,
|
|
can transit to different access model. */
|
|
if ((offset + 10) > sec->size
|
|
|| (type != 0x8d && type != 0x04))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
if (type == 0x04)
|
|
{
|
|
/* leal foo@tlsgd(,%ebx,1), %eax
|
|
call ___tls_get_addr@PLT */
|
|
if (offset < 3)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
if (*(call - 7) != 0x8d
|
|
|| val != 0x1d
|
|
|| call[0] != 0xe8)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
else
|
|
{
|
|
@@ -914,7 +914,7 @@ elf_i386_check_tls_transition (asection *sec,
|
|
is used to pass parameter to ___tls_get_addr. */
|
|
reg = val & 7;
|
|
if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
indirect_call = call[0] == 0xff;
|
|
if (!(reg == 3 && call[0] == 0xe8 && call[5] == 0x90)
|
|
@@ -922,7 +922,7 @@ elf_i386_check_tls_transition (asection *sec,
|
|
&& !(indirect_call
|
|
&& (call[1] & 0xf8) == 0x90
|
|
&& (call[1] & 0x7) == reg))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
}
|
|
else
|
|
@@ -937,13 +937,13 @@ elf_i386_check_tls_transition (asection *sec,
|
|
addr32 call ___tls_get_addr
|
|
can transit to different access model. */
|
|
if (type != 0x8d || (offset + 9) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
/* %eax can't be used as the GOT base register since it is
|
|
used to pass parameter to ___tls_get_addr. */
|
|
reg = val & 7;
|
|
if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
indirect_call = call[0] == 0xff;
|
|
if (!(reg == 3 && call[0] == 0xe8)
|
|
@@ -951,23 +951,27 @@ elf_i386_check_tls_transition (asection *sec,
|
|
&& !(indirect_call
|
|
&& (call[1] & 0xf8) == 0x90
|
|
&& (call[1] & 0x7) == reg))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
|
|
r_symndx = ELF32_R_SYM (rel[1].r_info);
|
|
if (r_symndx < symtab_hdr->sh_info)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
|
if (h == NULL
|
|
|| !((struct elf_x86_link_hash_entry *) h)->tls_get_addr)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
else if (indirect_call)
|
|
- return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X
|
|
- || ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32);
|
|
+ return ((ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X
|
|
+ || ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32)
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
else
|
|
- return (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
|
|
- || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
|
|
+ return ((ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
|
|
+ || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32)
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
|
|
case R_386_TLS_IE:
|
|
/* Check transition from IE access model:
|
|
@@ -977,20 +981,23 @@ elf_i386_check_tls_transition (asection *sec,
|
|
*/
|
|
|
|
if (offset < 1 || (offset + 4) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
/* Check "movl foo@tpoff(%rip), %eax" first. */
|
|
val = bfd_get_8 (abfd, contents + offset - 1);
|
|
if (val == 0xa1)
|
|
- return true;
|
|
+ return elf_x86_tls_error_none;
|
|
|
|
if (offset < 2)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
/* Check movl|addl foo@tpoff(%rip), %reg. */
|
|
type = bfd_get_8 (abfd, contents + offset - 2);
|
|
- return ((type == 0x8b || type == 0x03)
|
|
- && (val & 0xc7) == 0x05);
|
|
+ if (type != 0x8b && type != 0x03)
|
|
+ return elf_x86_tls_error_add_mov;
|
|
+ return ((val & 0xc7) == 0x05
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
|
|
case R_386_TLS_GOTIE:
|
|
case R_386_TLS_IE_32:
|
|
@@ -1001,14 +1008,16 @@ elf_i386_check_tls_transition (asection *sec,
|
|
*/
|
|
|
|
if (offset < 2 || (offset + 4) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
val = bfd_get_8 (abfd, contents + offset - 1);
|
|
if ((val & 0xc0) != 0x80 || (val & 7) == 4)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
type = bfd_get_8 (abfd, contents + offset - 2);
|
|
- return type == 0x8b || type == 0x2b || type == 0x03;
|
|
+ return (type == 0x8b || type == 0x2b || type == 0x03
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_add_sub_mov);
|
|
|
|
case R_386_TLS_GOTDESC:
|
|
/* Check transition from GDesc access model:
|
|
@@ -1019,13 +1028,15 @@ elf_i386_check_tls_transition (asection *sec,
|
|
going to be eax. */
|
|
|
|
if (offset < 2 || (offset + 4) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
|
|
- return false;
|
|
+ return elf_x86_tls_error_lea;
|
|
|
|
val = bfd_get_8 (abfd, contents + offset - 1);
|
|
- return (val & 0xc7) == 0x83;
|
|
+ return ((val & 0xc7) == 0x83
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
|
|
case R_386_TLS_DESC_CALL:
|
|
/* Check transition from GDesc access model:
|
|
@@ -1035,10 +1046,12 @@ elf_i386_check_tls_transition (asection *sec,
|
|
{
|
|
/* Make sure that it's a call *x@tlsdesc(%eax). */
|
|
call = contents + offset;
|
|
- return call[0] == 0xff && call[1] == 0x10;
|
|
+ return (call[0] == 0xff && call[1] == 0x10
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_indirect_call);
|
|
}
|
|
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
default:
|
|
abort ();
|
|
@@ -1057,7 +1070,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
|
|
const Elf_Internal_Rela *rel,
|
|
const Elf_Internal_Rela *relend,
|
|
struct elf_link_hash_entry *h,
|
|
- unsigned long r_symndx,
|
|
+ Elf_Internal_Sym *sym,
|
|
bool from_relocate_section)
|
|
{
|
|
unsigned int from_type = *r_type;
|
|
@@ -1142,43 +1155,24 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
|
|
return true;
|
|
|
|
/* Check if the transition can be performed. */
|
|
+ enum elf_x86_tls_error_type tls_error;
|
|
if (check
|
|
- && ! elf_i386_check_tls_transition (sec, contents,
|
|
- symtab_hdr, sym_hashes,
|
|
- from_type, rel, relend))
|
|
+ && ((tls_error = elf_i386_check_tls_transition (sec, contents,
|
|
+ symtab_hdr,
|
|
+ sym_hashes,
|
|
+ from_type, rel,
|
|
+ relend))
|
|
+ != elf_x86_tls_error_none))
|
|
{
|
|
reloc_howto_type *from, *to;
|
|
- const char *name;
|
|
|
|
from = elf_i386_rtype_to_howto (from_type);
|
|
to = elf_i386_rtype_to_howto (to_type);
|
|
|
|
- if (h)
|
|
- name = h->root.root.string;
|
|
- else
|
|
- {
|
|
- struct elf_x86_link_hash_table *htab;
|
|
-
|
|
- htab = elf_x86_hash_table (info, I386_ELF_DATA);
|
|
- if (htab == NULL)
|
|
- name = "*unknown*";
|
|
- else
|
|
- {
|
|
- Elf_Internal_Sym *isym;
|
|
-
|
|
- isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
|
|
- abfd, r_symndx);
|
|
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
|
|
- }
|
|
- }
|
|
+ _bfd_x86_elf_link_report_tls_transition_error
|
|
+ (info, abfd, sec, symtab_hdr, h, sym, rel, from->name,
|
|
+ to->name, tls_error);
|
|
|
|
- _bfd_error_handler
|
|
- /* xgettext:c-format */
|
|
- (_("%pB: TLS transition from %s to %s against `%s'"
|
|
- " at %#" PRIx64 " in section `%pA' failed"),
|
|
- abfd, from->name, to->name, name,
|
|
- (uint64_t) rel->r_offset, sec);
|
|
- bfd_set_error (bfd_error_bad_value);
|
|
return false;
|
|
}
|
|
|
|
@@ -1600,7 +1594,7 @@ elf_i386_scan_relocs (bfd *abfd,
|
|
if (! elf_i386_tls_transition (info, abfd, sec, contents,
|
|
symtab_hdr, sym_hashes,
|
|
&r_type, GOT_UNKNOWN,
|
|
- rel, rel_end, h, r_symndx, false))
|
|
+ rel, rel_end, h, isym, false))
|
|
goto error_return;
|
|
|
|
/* Check if _GLOBAL_OFFSET_TABLE_ is referenced. */
|
|
@@ -2875,7 +2869,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|
|
input_section, contents,
|
|
symtab_hdr, sym_hashes,
|
|
&r_type_tls, tls_type, rel,
|
|
- relend, h, r_symndx, true))
|
|
+ relend, h, sym, true))
|
|
return false;
|
|
|
|
expected_tls_le = htab->elf.target_os == is_solaris
|
|
@@ -3365,7 +3359,7 @@ elf_i386_relocate_section (bfd *output_bfd,
|
|
input_section, contents,
|
|
symtab_hdr, sym_hashes,
|
|
&r_type, GOT_UNKNOWN, rel,
|
|
- relend, h, r_symndx, true))
|
|
+ relend, h, sym, true))
|
|
return false;
|
|
|
|
if (r_type != R_386_TLS_LDM)
|
|
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
|
|
index 2ed120af780..f116e423f61 100644
|
|
--- a/bfd/elf64-x86-64.c
|
|
+++ b/bfd/elf64-x86-64.c
|
|
@@ -1120,7 +1120,7 @@ elf32_x86_64_elf_object_p (bfd *abfd)
|
|
/* Return TRUE if the TLS access code sequence support transition
|
|
from R_TYPE. */
|
|
|
|
-static bool
|
|
+static enum elf_x86_tls_error_type
|
|
elf_x86_64_check_tls_transition (bfd *abfd,
|
|
struct bfd_link_info *info,
|
|
asection *sec,
|
|
@@ -1147,7 +1147,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
case R_X86_64_TLSGD:
|
|
case R_X86_64_TLSLD:
|
|
if ((rel + 1) >= relend)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
if (r_type == R_X86_64_TLSGD)
|
|
{
|
|
@@ -1184,7 +1184,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
static const unsigned char leaq[] = { 0x66, 0x48, 0x8d, 0x3d };
|
|
|
|
if ((offset + 12) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
call = contents + offset + 4;
|
|
if (call[0] != 0x66
|
|
@@ -1208,20 +1208,20 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
|| call[14] != 0xd0
|
|
|| !((call[10] == 0x48 && call[12] == 0xd8)
|
|
|| (call[10] == 0x4c && call[12] == 0xf8)))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
largepic = true;
|
|
}
|
|
else if (ABI_64_P (abfd))
|
|
{
|
|
if (offset < 4
|
|
|| memcmp (contents + offset - 4, leaq, 4) != 0)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
else
|
|
{
|
|
if (offset < 3
|
|
|| memcmp (contents + offset - 3, leaq + 1, 3) != 0)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
indirect_call = call[2] == 0xff;
|
|
}
|
|
@@ -1250,10 +1250,10 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
static const unsigned char lea[] = { 0x48, 0x8d, 0x3d };
|
|
|
|
if (offset < 3 || (offset + 9) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
if (memcmp (contents + offset - 3, lea, 3) != 0)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
call = contents + offset + 4;
|
|
if (!(call[0] == 0xe8
|
|
@@ -1268,7 +1268,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
|| call[14] != 0xd0
|
|
|| !((call[10] == 0x48 && call[12] == 0xd8)
|
|
|| (call[10] == 0x4c && call[12] == 0xf8)))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
largepic = true;
|
|
}
|
|
indirect_call = call[0] == 0xff;
|
|
@@ -1276,22 +1276,30 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
|
|
r_symndx = htab->r_sym (rel[1].r_info);
|
|
if (r_symndx < symtab_hdr->sh_info)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
|
if (h == NULL
|
|
|| !((struct elf_x86_link_hash_entry *) h)->tls_get_addr)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
else
|
|
{
|
|
r_type = (ELF32_R_TYPE (rel[1].r_info)
|
|
& ~R_X86_64_converted_reloc_bit);
|
|
if (largepic)
|
|
- return r_type == R_X86_64_PLTOFF64;
|
|
+ return (r_type == R_X86_64_PLTOFF64
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
else if (indirect_call)
|
|
- return (r_type == R_X86_64_GOTPCRELX || r_type == R_X86_64_GOTPCREL);
|
|
+ return ((r_type == R_X86_64_GOTPCRELX
|
|
+ || r_type == R_X86_64_GOTPCREL)
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
else
|
|
- return (r_type == R_X86_64_PC32 || r_type == R_X86_64_PLT32);
|
|
+ return ((r_type == R_X86_64_PC32
|
|
+ || r_type == R_X86_64_PLT32)
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
}
|
|
|
|
case R_X86_64_CODE_4_GOTTPOFF:
|
|
@@ -1303,7 +1311,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
if (offset < 4
|
|
|| (offset + 4) > sec->size
|
|
|| contents[offset - 4] != 0xd5)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
goto check_gottpoff;
|
|
|
|
@@ -1315,14 +1323,16 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
if (offset < 6
|
|
|| (offset + 4) > sec->size
|
|
|| contents[offset - 6] != 0x62)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
val = bfd_get_8 (abfd, contents + offset - 2);
|
|
if (val != 0x01 && val != 0x03)
|
|
- return false;
|
|
+ return elf_x86_tls_error_add;
|
|
|
|
val = bfd_get_8 (abfd, contents + offset - 1);
|
|
- return (val & 0xc7) == 5;
|
|
+ return ((val & 0xc7) == 5
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
|
|
case R_X86_64_GOTTPOFF:
|
|
/* Check transition from IE access model:
|
|
@@ -1338,25 +1348,27 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
{
|
|
/* X32 may have 0x44 REX prefix or no REX prefix. */
|
|
if (ABI_64_P (abfd))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* X32 may not have any REX prefix. */
|
|
if (ABI_64_P (abfd))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
if (offset < 2 || (offset + 3) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
|
|
check_gottpoff:
|
|
val = bfd_get_8 (abfd, contents + offset - 2);
|
|
if (val != 0x8b && val != 0x03)
|
|
- return false;
|
|
+ return elf_x86_tls_error_add_mov;
|
|
|
|
val = bfd_get_8 (abfd, contents + offset - 1);
|
|
- return (val & 0xc7) == 5;
|
|
+ return ((val & 0xc7) == 5
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
|
|
case R_X86_64_CODE_4_GOTPC32_TLSDESC:
|
|
/* Check transition from GDesc access model:
|
|
@@ -1366,7 +1378,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
if (offset < 4
|
|
|| (offset + 4) > sec->size
|
|
|| contents[offset - 4] != 0xd5)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
goto check_tlsdesc;
|
|
|
|
@@ -1380,19 +1392,21 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
going to be rax. */
|
|
|
|
if (offset < 3 || (offset + 4) > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
val = bfd_get_8 (abfd, contents + offset - 3);
|
|
val &= 0xfb;
|
|
if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40))
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
check_tlsdesc:
|
|
if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
|
|
- return false;
|
|
+ return elf_x86_tls_error_lea;
|
|
|
|
val = bfd_get_8 (abfd, contents + offset - 1);
|
|
- return (val & 0xc7) == 0x05;
|
|
+ return ((val & 0xc7) == 0x05
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_yes);
|
|
|
|
case R_X86_64_TLSDESC_CALL:
|
|
/* Check transition from GDesc access model:
|
|
@@ -1411,14 +1425,16 @@ elf_x86_64_check_tls_transition (bfd *abfd,
|
|
{
|
|
prefix = 1;
|
|
if (offset + 3 > sec->size)
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
}
|
|
}
|
|
/* Make sure that it's a call *x@tlsdesc(%rax). */
|
|
- return call[prefix] == 0xff && call[1 + prefix] == 0x10;
|
|
+ return (call[prefix] == 0xff && call[1 + prefix] == 0x10
|
|
+ ? elf_x86_tls_error_none
|
|
+ : elf_x86_tls_error_indirect_call);
|
|
}
|
|
|
|
- return false;
|
|
+ return elf_x86_tls_error_yes;
|
|
|
|
default:
|
|
abort ();
|
|
@@ -1437,7 +1453,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
|
|
const Elf_Internal_Rela *rel,
|
|
const Elf_Internal_Rela *relend,
|
|
struct elf_link_hash_entry *h,
|
|
- unsigned long r_symndx,
|
|
+ Elf_Internal_Sym *sym,
|
|
bool from_relocate_section)
|
|
{
|
|
unsigned int from_type = *r_type;
|
|
@@ -1488,7 +1504,12 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
|
|
/* We checked the transition before when we were called from
|
|
elf_x86_64_scan_relocs. We only want to check the new
|
|
transition which hasn't been checked before. */
|
|
- check = new_to_type != to_type && from_type == to_type;
|
|
+ check = (new_to_type != to_type
|
|
+ && (from_type == to_type
|
|
+ || (from_type == R_X86_64_CODE_4_GOTTPOFF
|
|
+ && to_type == R_X86_64_GOTTPOFF)
|
|
+ || (from_type == R_X86_64_CODE_6_GOTTPOFF
|
|
+ && to_type == R_X86_64_GOTTPOFF)));
|
|
to_type = new_to_type;
|
|
}
|
|
|
|
@@ -1512,13 +1533,18 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
|
|
return true;
|
|
|
|
/* Check if the transition can be performed. */
|
|
+ enum elf_x86_tls_error_type tls_error;
|
|
if (check
|
|
- && ! elf_x86_64_check_tls_transition (abfd, info, sec, contents,
|
|
- symtab_hdr, sym_hashes,
|
|
- from_type, rel, relend))
|
|
+ && ((tls_error = elf_x86_64_check_tls_transition (abfd, info, sec,
|
|
+ contents,
|
|
+ symtab_hdr,
|
|
+ sym_hashes,
|
|
+ from_type, rel,
|
|
+ relend))
|
|
+ != elf_x86_tls_error_none))
|
|
+
|
|
{
|
|
reloc_howto_type *from, *to;
|
|
- const char *name;
|
|
|
|
from = elf_x86_64_rtype_to_howto (abfd, from_type);
|
|
to = elf_x86_64_rtype_to_howto (abfd, to_type);
|
|
@@ -1526,31 +1552,10 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
|
|
if (from == NULL || to == NULL)
|
|
return false;
|
|
|
|
- if (h)
|
|
- name = h->root.root.string;
|
|
- else
|
|
- {
|
|
- struct elf_x86_link_hash_table *htab;
|
|
-
|
|
- htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
|
|
- if (htab == NULL)
|
|
- name = "*unknown*";
|
|
- else
|
|
- {
|
|
- Elf_Internal_Sym *isym;
|
|
+ _bfd_x86_elf_link_report_tls_transition_error
|
|
+ (info, abfd, sec, symtab_hdr, h, sym, rel, from->name,
|
|
+ to->name, tls_error);
|
|
|
|
- isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
|
|
- abfd, r_symndx);
|
|
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
|
|
- }
|
|
- }
|
|
-
|
|
- _bfd_error_handler
|
|
- /* xgettext:c-format */
|
|
- (_("%pB: TLS transition from %s to %s against `%s' at %#" PRIx64
|
|
- " in section `%pA' failed"),
|
|
- abfd, from->name, to->name, name, (uint64_t) rel->r_offset, sec);
|
|
- bfd_set_error (bfd_error_bad_value);
|
|
return false;
|
|
}
|
|
|
|
@@ -2198,7 +2203,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
|
|
if (! elf_x86_64_tls_transition (info, abfd, sec, contents,
|
|
symtab_hdr, sym_hashes,
|
|
&r_type, GOT_UNKNOWN,
|
|
- rel, rel_end, h, r_symndx, false))
|
|
+ rel, rel_end, h, isym, false))
|
|
goto error_return;
|
|
|
|
/* Check if _GLOBAL_OFFSET_TABLE_ is referenced. */
|
|
@@ -3648,7 +3653,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
|
|
input_section, contents,
|
|
symtab_hdr, sym_hashes,
|
|
&r_type_tls, tls_type, rel,
|
|
- relend, h, r_symndx, true))
|
|
+ relend, h, sym, true))
|
|
return false;
|
|
|
|
if (r_type_tls == R_X86_64_TPOFF32)
|
|
@@ -4308,7 +4313,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
|
|
input_section, contents,
|
|
symtab_hdr, sym_hashes,
|
|
&r_type, GOT_UNKNOWN, rel,
|
|
- relend, h, r_symndx, true))
|
|
+ relend, h, sym, true))
|
|
return false;
|
|
|
|
if (r_type != R_X86_64_TLSLD)
|
|
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
|
|
index 508fd771da3..b17dad759c8 100644
|
|
--- a/bfd/elfxx-x86.c
|
|
+++ b/bfd/elfxx-x86.c
|
|
@@ -3202,6 +3202,91 @@ _bfd_x86_elf_link_report_relative_reloc
|
|
asect, abfd);
|
|
}
|
|
|
|
+/* Report TLS transition error. */
|
|
+
|
|
+void
|
|
+_bfd_x86_elf_link_report_tls_transition_error
|
|
+ (struct bfd_link_info *info, bfd *abfd, asection *asect,
|
|
+ Elf_Internal_Shdr *symtab_hdr, struct elf_link_hash_entry *h,
|
|
+ Elf_Internal_Sym *sym, const Elf_Internal_Rela *rel,
|
|
+ const char *from_reloc_name, const char *to_reloc_name,
|
|
+ enum elf_x86_tls_error_type tls_error)
|
|
+{
|
|
+ const char *name;
|
|
+
|
|
+ if (h)
|
|
+ name = h->root.root.string;
|
|
+ else
|
|
+ {
|
|
+ const struct elf_backend_data *bed
|
|
+ = get_elf_backend_data (abfd);
|
|
+ struct elf_x86_link_hash_table *htab
|
|
+ = elf_x86_hash_table (info, bed->target_id);
|
|
+ if (htab == NULL)
|
|
+ name = "*unknown*";
|
|
+ else
|
|
+ name = bfd_elf_sym_name (abfd, symtab_hdr, sym, NULL);
|
|
+ }
|
|
+
|
|
+ switch (tls_error)
|
|
+ {
|
|
+ case elf_x86_tls_error_yes:
|
|
+ info->callbacks->einfo
|
|
+ /* xgettext:c-format */
|
|
+ (_("%pB: TLS transition from %s to %s against `%s' at 0x%v in "
|
|
+ "section `%pA' failed"),
|
|
+ abfd, from_reloc_name, to_reloc_name, name, rel->r_offset,
|
|
+ asect);
|
|
+ break;
|
|
+
|
|
+ case elf_x86_tls_error_add:
|
|
+ info->callbacks->einfo
|
|
+ /* xgettext:c-format */
|
|
+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
|
|
+ "in ADD only"),
|
|
+ abfd, asect, rel->r_offset, from_reloc_name, name);
|
|
+ break;
|
|
+
|
|
+ case elf_x86_tls_error_add_mov:
|
|
+ info->callbacks->einfo
|
|
+ /* xgettext:c-format */
|
|
+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
|
|
+ "in ADD or MOV only"),
|
|
+ abfd, asect, rel->r_offset, from_reloc_name, name);
|
|
+ break;
|
|
+
|
|
+ case elf_x86_tls_error_add_sub_mov:
|
|
+ info->callbacks->einfo
|
|
+ /* xgettext:c-format */
|
|
+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
|
|
+ "in ADD, SUB or MOV only"),
|
|
+ abfd, asect, rel->r_offset, from_reloc_name, name);
|
|
+ break;
|
|
+
|
|
+ case elf_x86_tls_error_indirect_call:
|
|
+ info->callbacks->einfo
|
|
+ /* xgettext:c-format */
|
|
+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
|
|
+ "in indirect CALL only"),
|
|
+ abfd, asect, rel->r_offset, from_reloc_name, name);
|
|
+ break;
|
|
+
|
|
+ case elf_x86_tls_error_lea:
|
|
+ info->callbacks->einfo
|
|
+ /* xgettext:c-format */
|
|
+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
|
|
+ "in LEA only"),
|
|
+ abfd, asect, rel->r_offset, from_reloc_name, name);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ abort ();
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ bfd_set_error (bfd_error_bad_value);
|
|
+}
|
|
+
|
|
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
|
|
|
|
bool
|
|
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
|
|
index 110bcb9ad71..02e2efa6c56 100644
|
|
--- a/bfd/elfxx-x86.h
|
|
+++ b/bfd/elfxx-x86.h
|
|
@@ -767,6 +767,18 @@ struct elf_x86_plt
|
|
long count;
|
|
};
|
|
|
|
+enum elf_x86_tls_error_type
|
|
+{
|
|
+ elf_x86_tls_error_none,
|
|
+ elf_x86_tls_error_add,
|
|
+ elf_x86_tls_error_add_mov,
|
|
+ elf_x86_tls_error_add_sub_mov,
|
|
+ elf_x86_tls_error_indirect_call,
|
|
+ elf_x86_tls_error_lea,
|
|
+ elf_x86_tls_error_yes
|
|
+};
|
|
+
|
|
+
|
|
/* Set if a relocation is converted from a GOTPCREL relocation. */
|
|
#define R_X86_64_converted_reloc_bit (1 << 7)
|
|
|
|
@@ -908,6 +920,12 @@ extern void _bfd_x86_elf_link_fixup_ifunc_symbol
|
|
extern void _bfd_x86_elf_link_report_relative_reloc
|
|
(struct bfd_link_info *, asection *, struct elf_link_hash_entry *,
|
|
Elf_Internal_Sym *, const char *, const void *);
|
|
+extern void _bfd_x86_elf_link_report_tls_transition_error
|
|
+ (struct bfd_link_info *, bfd *, asection *, Elf_Internal_Shdr *,
|
|
+ struct elf_link_hash_entry *, Elf_Internal_Sym *,
|
|
+ const Elf_Internal_Rela *, const char *, const char *,
|
|
+ enum elf_x86_tls_error_type);
|
|
+
|
|
|
|
#define bfd_elf64_mkobject \
|
|
_bfd_x86_elf_mkobject
|
|
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
|
|
index 18d1c9198ca..a8db2c713f3 100644
|
|
--- a/ld/testsuite/ld-i386/i386.exp
|
|
+++ b/ld/testsuite/ld-i386/i386.exp
|
|
@@ -541,6 +541,8 @@ run_dump_test "tlsdesc2"
|
|
run_dump_test "report-reloc-1"
|
|
run_dump_test "pr27998a"
|
|
run_dump_test "pr27998b"
|
|
+run_dump_test "tlsgdesc1"
|
|
+run_dump_test "tlsgdesc2"
|
|
|
|
proc undefined_weak {cflags ldflags} {
|
|
set testname "Undefined weak symbol"
|
|
diff --git a/ld/testsuite/ld-i386/tlsgdesc1.d b/ld/testsuite/ld-i386/tlsgdesc1.d
|
|
new file mode 100644
|
|
index 00000000000..2a70e81c444
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-i386/tlsgdesc1.d
|
|
@@ -0,0 +1,4 @@
|
|
+#name: TLS GDesc->LE transition check (LEA)
|
|
+#as: --32
|
|
+#ld: -melf_i386
|
|
+#error: .*: relocation R_386_TLS_GOTDESC against `foo' must be used in LEA only
|
|
diff --git a/ld/testsuite/ld-i386/tlsgdesc1.s b/ld/testsuite/ld-i386/tlsgdesc1.s
|
|
new file mode 100644
|
|
index 00000000000..c30f7523462
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-i386/tlsgdesc1.s
|
|
@@ -0,0 +1,11 @@
|
|
+ .text
|
|
+ .globl _start
|
|
+_start:
|
|
+ movl foo@tlsdesc(%ebx), %eax
|
|
+ call *foo@tlscall(%eax)
|
|
+ .section .tdata,"awT",@progbits
|
|
+ .align 4
|
|
+ .type foo, @object
|
|
+ .size foo, 4
|
|
+foo:
|
|
+ .long 100
|
|
diff --git a/ld/testsuite/ld-i386/tlsgdesc2.d b/ld/testsuite/ld-i386/tlsgdesc2.d
|
|
new file mode 100644
|
|
index 00000000000..2e6a66d372c
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-i386/tlsgdesc2.d
|
|
@@ -0,0 +1,4 @@
|
|
+#name: TLS GDesc->LE transition check (indirect CALL)
|
|
+#as: --32
|
|
+#ld: -melf_i386
|
|
+#error: .*: relocation R_386_TLS_DESC_CALL against `foo' must be used in indirect CALL only
|
|
diff --git a/ld/testsuite/ld-i386/tlsgdesc2.s b/ld/testsuite/ld-i386/tlsgdesc2.s
|
|
new file mode 100644
|
|
index 00000000000..7d9d556e2ab
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-i386/tlsgdesc2.s
|
|
@@ -0,0 +1,11 @@
|
|
+ .text
|
|
+ .globl _start
|
|
+_start:
|
|
+ leal foo@tlsdesc(%ebx), %eax
|
|
+ jmp *foo@tlscall(%eax)
|
|
+ .section .tdata,"awT",@progbits
|
|
+ .align 4
|
|
+ .type foo, @object
|
|
+ .size foo, 4
|
|
+foo:
|
|
+ .long 100
|
|
diff --git a/ld/testsuite/ld-i386/tlsie2.d b/ld/testsuite/ld-i386/tlsie2.d
|
|
index ebb85fde7e7..9f9e63029d6 100644
|
|
--- a/ld/testsuite/ld-i386/tlsie2.d
|
|
+++ b/ld/testsuite/ld-i386/tlsie2.d
|
|
@@ -1,4 +1,4 @@
|
|
#name: TLS IE->LE transition check (R_386_TLS_GOTIE with %eax)
|
|
#as: --32
|
|
#ld: -melf_i386
|
|
-#error: .*TLS transition from R_386_TLS_GOTIE to R_386_TLS_LE_32 against `foo'.*failed.*
|
|
+#error: .*: relocation R_386_TLS_GOTIE against `foo' must be used in ADD, SUB or MOV only
|
|
diff --git a/ld/testsuite/ld-i386/tlsie3.d b/ld/testsuite/ld-i386/tlsie3.d
|
|
index d993f303c25..506f1a02605 100644
|
|
--- a/ld/testsuite/ld-i386/tlsie3.d
|
|
+++ b/ld/testsuite/ld-i386/tlsie3.d
|
|
@@ -1,4 +1,4 @@
|
|
#name: TLS IE->LE transition check (R_386_TLS_GOTIE)
|
|
#as: --32
|
|
#ld: -melf_i386
|
|
-#error: .*TLS transition from R_386_TLS_GOTIE to R_386_TLS_LE_32 against `foo'.*failed.*
|
|
+#error: .*: relocation R_386_TLS_GOTIE against `foo' must be used in ADD, SUB or MOV only
|
|
diff --git a/ld/testsuite/ld-i386/tlsie4.d b/ld/testsuite/ld-i386/tlsie4.d
|
|
index 3ca8fddf5dd..a516d002660 100644
|
|
--- a/ld/testsuite/ld-i386/tlsie4.d
|
|
+++ b/ld/testsuite/ld-i386/tlsie4.d
|
|
@@ -1,4 +1,4 @@
|
|
#name: TLS IE->LE transition check (R_386_TLS_IE with %eax)
|
|
#as: --32
|
|
#ld: -melf_i386
|
|
-#error: .*TLS transition from R_386_TLS_IE to R_386_TLS_LE_32 against `foo'.*failed.*
|
|
+#error: .*: relocation R_386_TLS_IE against `foo' must be used in ADD or MOV only
|
|
diff --git a/ld/testsuite/ld-i386/tlsie5.d b/ld/testsuite/ld-i386/tlsie5.d
|
|
index 3febeb159a9..d3447182e19 100644
|
|
--- a/ld/testsuite/ld-i386/tlsie5.d
|
|
+++ b/ld/testsuite/ld-i386/tlsie5.d
|
|
@@ -1,4 +1,4 @@
|
|
#name: TLS IE->LE transition check (R_386_TLS_IE)
|
|
#as: --32
|
|
#ld: -melf_i386
|
|
-#error: .*TLS transition from R_386_TLS_IE to R_386_TLS_LE_32 against `foo'.*failed.*
|
|
+#error: .*: relocation R_386_TLS_IE against `foo' must be used in ADD or MOV only
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsdesc3.d b/ld/testsuite/ld-x86-64/tlsdesc3.d
|
|
new file mode 100644
|
|
index 00000000000..bbf22ebeafe
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-x86-64/tlsdesc3.d
|
|
@@ -0,0 +1,4 @@
|
|
+#name: TLS GDesc->LE transition check (LEA)
|
|
+#as: --64
|
|
+#ld: -melf_x86_64
|
|
+#error: .*: relocation R_X86_64_GOTPC32_TLSDESC against `foo' must be used in LEA only
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsdesc3.s b/ld/testsuite/ld-x86-64/tlsdesc3.s
|
|
new file mode 100644
|
|
index 00000000000..45310654ffc
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-x86-64/tlsdesc3.s
|
|
@@ -0,0 +1,13 @@
|
|
+ .text
|
|
+ .globl _start
|
|
+ .type _start,@function
|
|
+_start:
|
|
+ movq foo@tlsdesc(%rip), %rax
|
|
+ call *foo@tlscall(%rax)
|
|
+ .globl foo
|
|
+ .section .tdata,"awT",@progbits
|
|
+ .align 8
|
|
+ .type foo, @object
|
|
+ .size foo, 8
|
|
+foo:
|
|
+ .quad 100
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsdesc4.d b/ld/testsuite/ld-x86-64/tlsdesc4.d
|
|
new file mode 100644
|
|
index 00000000000..b50115c7178
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-x86-64/tlsdesc4.d
|
|
@@ -0,0 +1,4 @@
|
|
+#name: TLS GDesc->LE transition check (indirect CALL)
|
|
+#as: --64
|
|
+#ld: -melf_x86_64
|
|
+#error: .*: relocation R_X86_64_TLSDESC_CALL against `foo' must be used in indirect CALL only
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsdesc4.s b/ld/testsuite/ld-x86-64/tlsdesc4.s
|
|
new file mode 100644
|
|
index 00000000000..b3d6c12d4fc
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-x86-64/tlsdesc4.s
|
|
@@ -0,0 +1,13 @@
|
|
+ .text
|
|
+ .globl _start
|
|
+ .type _start,@function
|
|
+_start:
|
|
+ leaq foo@tlsdesc(%rip), %rax
|
|
+ jmp *foo@tlscall(%rax)
|
|
+ .globl foo
|
|
+ .section .tdata,"awT",@progbits
|
|
+ .align 8
|
|
+ .type foo, @object
|
|
+ .size foo, 8
|
|
+foo:
|
|
+ .quad 100
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsie2.d b/ld/testsuite/ld-x86-64/tlsie2.d
|
|
index 97dcc288a3d..bf8a8198b5b 100644
|
|
--- a/ld/testsuite/ld-x86-64/tlsie2.d
|
|
+++ b/ld/testsuite/ld-x86-64/tlsie2.d
|
|
@@ -1,4 +1,4 @@
|
|
#name: TLS IE->LE transition check
|
|
#as: --64
|
|
#ld: -melf_x86_64
|
|
-#error: .*TLS transition from R_X86_64_GOTTPOFF to R_X86_64_TPOFF32 against `foo'.*failed.*
|
|
+#error: .*: relocation R_X86_64_GOTTPOFF against `foo' must be used in ADD or MOV only
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsie3.d b/ld/testsuite/ld-x86-64/tlsie3.d
|
|
index 8c982a69838..49d8464fbaf 100644
|
|
--- a/ld/testsuite/ld-x86-64/tlsie3.d
|
|
+++ b/ld/testsuite/ld-x86-64/tlsie3.d
|
|
@@ -1,4 +1,4 @@
|
|
#name: TLS IE->LE transition check (%r12)
|
|
#as: --64
|
|
#ld: -melf_x86_64
|
|
-#error: .*TLS transition from R_X86_64_GOTTPOFF to R_X86_64_TPOFF32 against `foo'.*failed.*
|
|
+#error: .*: relocation R_X86_64_GOTTPOFF against `foo' must be used in ADD or MOV only
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsie5.d b/ld/testsuite/ld-x86-64/tlsie5.d
|
|
new file mode 100644
|
|
index 00000000000..29de1cebf8e
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-x86-64/tlsie5.d
|
|
@@ -0,0 +1,4 @@
|
|
+#name: TLS IE->LE transition check (APX)
|
|
+#as: --64
|
|
+#ld: -melf_x86_64
|
|
+#error: .*: relocation R_X86_64_CODE_6_GOTTPOFF against `foo' must be used in ADD only
|
|
diff --git a/ld/testsuite/ld-x86-64/tlsie5.s b/ld/testsuite/ld-x86-64/tlsie5.s
|
|
new file mode 100644
|
|
index 00000000000..c39e46fd97b
|
|
--- /dev/null
|
|
+++ b/ld/testsuite/ld-x86-64/tlsie5.s
|
|
@@ -0,0 +1,12 @@
|
|
+ .text
|
|
+ .globl _start
|
|
+_start:
|
|
+ xorq %rax, foo@GOTTPOFF(%rip), %rax
|
|
+ movq (%rax), %rax
|
|
+ .globl foo
|
|
+ .section .tdata,"awT",@progbits
|
|
+ .align 4
|
|
+ .type foo, @object
|
|
+ .size foo, 4
|
|
+foo:
|
|
+ .long 100
|
|
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
|
|
index 2a40f0b095b..811813466f8 100644
|
|
--- a/ld/testsuite/ld-x86-64/x86-64.exp
|
|
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
|
|
@@ -741,6 +741,9 @@ run_dump_test "pr27016b"
|
|
run_dump_test "report-reloc-1"
|
|
run_dump_test "report-reloc-1-x32"
|
|
run_dump_test "pr29820"
|
|
+run_dump_test "tlsie5"
|
|
+run_dump_test "tlsdesc3"
|
|
+run_dump_test "tlsdesc4"
|
|
|
|
proc undefined_weak {cflags ldflags} {
|
|
set testname "Undefined weak symbol"
|
|
--
|
|
2.49.0
|
|
|