]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 9 Jun 2023 20:50:22 +0000 (13:50 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 28 Dec 2023 16:47:17 +0000 (08:47 -0800)
For

add name@gottpoff(%rip), %reg
mov name@gottpoff(%rip), %reg

add

 # define R_X86_64_CODE_4_GOTTPOFF 44

and for

lea name@tlsdesc(%rip), %reg

add

 # define R_X86_64_CODE_4_GOTPC32_TLSDESC 45

if the instruction starts at 4 bytes before the relocation offset.
They are similar to R_X86_64_GOTTPOFF and R_X86_64_GOTPC32_TLSDESC,
respectively.  Linker can covert GOTTPOFF to

add $name@tpoff, %reg
mov $name@tpoff, %reg

and GOTPC32_TLSDESC to

mov $name@tpoff, %reg
mov name@gottpoff(%rip), %reg

if the instruction is encoded with the REX2 prefix when possible.

bfd/

* elf64-x86-64.c (x86_64_elf_howto_table): Add
R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC.
(R_X86_64_standard): Updated.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTTPOFF
and BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
(elf_x86_64_check_tls_transition): Handle R_X86_64_CODE_4_GOTTPOFF
and R_X86_64_CODE_4_GOTPC32_TLSDESC.
(elf_x86_64_tls_transition): Likewise.
(elf_x86_64_scan_relocs): Likewise.
(elf_x86_64_relocate_section): Likewise.
* reloc.c (bfd_reloc_code_real): Add
BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.

gas/

* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
(md_assemble): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF.
(output_insn): Don't add empty REX prefix with REX2 prefix.
(output_disp): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
(md_apply_fix): Likewise.
(i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTTPOFF or
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC if ixp->fx_tcbit3 is set.
(tc_gen_reloc): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
* testsuite/gas/i386/x86-64-gottpoff.d: New file.
* testsuite/gas/i386/x86-64-gottpoff.s: Likewise.
* testsuite/gas/i386/x86-64-tlsdesc.d: Likewise.
* testsuite/gas/i386/x86-64-tlsdesc.s: Likewise.

include/

* elf/x86-64.h (elf_x86_64_reloc_type): Add
R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC

ld/

* testsuite/ld-x86-64/tlsbindesc.d: Updated.
* testsuite/ld-x86-64/tlsbindesc.rd: Likewise.
* testsuite/ld-x86-64/tlsbindesc.s: Add R_X86_64_CODE_4_GOTTPOFF
and R_X86_64_CODE_4_GOTPC32_TLSDESC tests.

14 files changed:
bfd/bfd-in2.h
bfd/elf64-x86-64.c
bfd/libbfd.h
bfd/reloc.c
gas/config/tc-i386.c
gas/testsuite/gas/i386/x86-64-gottpoff.d [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-gottpoff.s [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-tlsdesc.d [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-tlsdesc.s [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64.exp
include/elf/x86-64.h
ld/testsuite/ld-x86-64/tlsbindesc.dd
ld/testsuite/ld-x86-64/tlsbindesc.rd
ld/testsuite/ld-x86-64/tlsbindesc.s

index 96709da917095b1d9002639ffdec8413cebb392c..550704ae89fb6d23f1114b192c146e05abc6ed04 100644 (file)
@@ -3892,6 +3892,8 @@ enum bfd_reloc_code_real
   BFD_RELOC_X86_64_GOTPCRELX,
   BFD_RELOC_X86_64_REX_GOTPCRELX,
   BFD_RELOC_X86_64_CODE_4_GOTPCRELX,
+  BFD_RELOC_X86_64_CODE_4_GOTTPOFF,
+  BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC,
 
   /* ns32k relocations.  */
   BFD_RELOC_NS32K_IMM_8,
index a2d1b6f14b7080f4b17d61ecd4d5acfaa1ee0cd3..3406bc86ec1e151250399182dd4a47695edfc534 100644 (file)
@@ -173,12 +173,18 @@ static reloc_howto_type x86_64_elf_howto_table[] =
   HOWTO(R_X86_64_CODE_4_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed,
        bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTPCRELX", false, 0, 0xffffffff,
        true),
+  HOWTO(R_X86_64_CODE_4_GOTTPOFF, 0, 4, 32, true, 0, complain_overflow_signed,
+       bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTTPOFF", false, 0, 0xffffffff,
+       true),
+  HOWTO(R_X86_64_CODE_4_GOTPC32_TLSDESC, 0, 4, 32, true, 0,
+       complain_overflow_bitfield, bfd_elf_generic_reloc,
+       "R_X86_64_CODE_4_GOTPC32_TLSDESC", false, 0, 0xffffffff, true),
 
   /* We have a gap in the reloc numbers here.
      R_X86_64_standard counts the number up to this point, and
      R_X86_64_vt_offset is the value to subtract from a reloc type of
      R_X86_64_GNU_VT* to form an index into this table.  */
-#define R_X86_64_standard (R_X86_64_CODE_4_GOTPCRELX + 1)
+#define R_X86_64_standard (R_X86_64_CODE_4_GOTPC32_TLSDESC + 1)
 #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -248,6 +254,8 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
   { BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, },
   { BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, },
   { BFD_RELOC_X86_64_CODE_4_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX, },
+  { BFD_RELOC_X86_64_CODE_4_GOTTPOFF, R_X86_64_CODE_4_GOTTPOFF, },
+  { BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC, R_X86_64_CODE_4_GOTPC32_TLSDESC, },
   { BFD_RELOC_VTABLE_INHERIT,  R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,    R_X86_64_GNU_VTENTRY, },
 };
@@ -1262,6 +1270,19 @@ elf_x86_64_check_tls_transition (bfd *abfd,
            return (r_type == R_X86_64_PC32 || r_type == R_X86_64_PLT32);
        }
 
+    case R_X86_64_CODE_4_GOTTPOFF:
+      /* Check transition from IE access model:
+               mov foo@gottpoff(%rip), %reg
+               add foo@gottpoff(%rip), %reg
+               where reg is one of r16 to r31.  */
+
+      if (offset < 4
+         || (offset + 4) > sec->size
+         || contents[offset - 4] != 0xd5)
+       return false;
+
+      goto check_gottpoff;
+
     case R_X86_64_GOTTPOFF:
       /* Check transition from IE access model:
                mov foo@gottpoff(%rip), %reg
@@ -1288,6 +1309,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
            return false;
        }
 
+ check_gottpoff:
       val = bfd_get_8 (abfd, contents + offset - 2);
       if (val != 0x8b && val != 0x03)
        return false;
@@ -1295,6 +1317,18 @@ elf_x86_64_check_tls_transition (bfd *abfd,
       val = bfd_get_8 (abfd, contents + offset - 1);
       return (val & 0xc7) == 5;
 
+    case R_X86_64_CODE_4_GOTPC32_TLSDESC:
+      /* Check transition from GDesc access model:
+               lea x@tlsdesc(%rip), %reg
+        where reg is one of r16 to r31.  */
+
+      if (offset < 4
+         || (offset + 4) > sec->size
+         || contents[offset - 4] != 0xd5)
+       return false;
+
+      goto check_tlsdesc;
+
     case R_X86_64_GOTPC32_TLSDESC:
       /* Check transition from GDesc access model:
                leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
@@ -1312,6 +1346,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
       if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40))
        return false;
 
+ check_tlsdesc:
       if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
        return false;
 
@@ -1378,8 +1413,10 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
     {
     case R_X86_64_TLSGD:
     case R_X86_64_GOTPC32_TLSDESC:
+    case R_X86_64_CODE_4_GOTPC32_TLSDESC:
     case R_X86_64_TLSDESC_CALL:
     case R_X86_64_GOTTPOFF:
+    case R_X86_64_CODE_4_GOTTPOFF:
       if (bfd_link_executable (info))
        {
          if (h == NULL)
@@ -1399,6 +1436,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
          if (to_type == R_X86_64_TLSGD
              || to_type == R_X86_64_GOTPC32_TLSDESC
+             || to_type == R_X86_64_CODE_4_GOTPC32_TLSDESC
              || to_type == R_X86_64_TLSDESC_CALL)
            {
              if (tls_type == GOT_TLS_IE)
@@ -1424,7 +1462,9 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
     }
 
   /* Return TRUE if there is no transition.  */
-  if (from_type == to_type)
+  if (from_type == to_type
+      || (from_type == R_X86_64_CODE_4_GOTTPOFF
+         && to_type == R_X86_64_GOTTPOFF))
     return true;
 
   /* Check if the transition can be performed.  */
@@ -2132,6 +2172,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
          break;
 
        case R_X86_64_GOTTPOFF:
+       case R_X86_64_CODE_4_GOTTPOFF:
          if (!bfd_link_executable (info))
            info->flags |= DF_STATIC_TLS;
          /* Fall through */
@@ -2146,6 +2187,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_GOTPCREL64:
        case R_X86_64_GOTPLT64:
        case R_X86_64_GOTPC32_TLSDESC:
+       case R_X86_64_CODE_4_GOTPC32_TLSDESC:
        case R_X86_64_TLSDESC_CALL:
          /* This symbol requires a global offset table entry.  */
          {
@@ -2167,9 +2209,11 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
                tls_type = GOT_TLS_GD;
                break;
              case R_X86_64_GOTTPOFF:
+             case R_X86_64_CODE_4_GOTTPOFF:
                tls_type = GOT_TLS_IE;
                break;
              case R_X86_64_GOTPC32_TLSDESC:
+             case R_X86_64_CODE_4_GOTPC32_TLSDESC:
              case R_X86_64_TLSDESC_CALL:
                tls_type = GOT_TLS_GDESC;
                break;
@@ -3518,8 +3562,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 
        case R_X86_64_TLSGD:
        case R_X86_64_GOTPC32_TLSDESC:
+       case R_X86_64_CODE_4_GOTPC32_TLSDESC:
        case R_X86_64_TLSDESC_CALL:
        case R_X86_64_GOTTPOFF:
+       case R_X86_64_CODE_4_GOTTPOFF:
          tls_type = GOT_UNKNOWN;
          if (h == NULL && local_got_offsets)
            tls_type = elf_x86_local_got_tls_type (input_bfd) [r_symndx];
@@ -3660,6 +3706,37 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                              contents + roff);
                  continue;
                }
+             else if (r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC)
+               {
+                 /* GDesc -> LE transition.
+                    It's originally something like:
+                    lea x@tlsdesc(%rip), %reg
+
+                    Change it to:
+                    mov $x@tpoff, %reg
+                    where reg is one of r16 to r31.  */
+
+                 unsigned int val, rex2;
+                 unsigned int rex2_mask = REX_R | REX_R << 4;
+
+                 if (roff < 4)
+                   goto corrupt_input;
+                 rex2 = bfd_get_8 (input_bfd, contents + roff - 3);
+                 val = bfd_get_8 (input_bfd, contents + roff - 1);
+                 /* Move the R bits to the B bits in REX2 payload
+                    byte.  */
+                 bfd_put_8 (output_bfd,
+                            ((rex2 & ~rex2_mask)
+                             | (rex2 & rex2_mask) >> 2),
+                            contents + roff - 3);
+                 bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
+                 bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
+                            contents + roff - 1);
+                 bfd_put_32 (output_bfd,
+                             elf_x86_64_tpoff (info, relocation),
+                             contents + roff);
+                 continue;
+               }
              else if (r_type == R_X86_64_TLSDESC_CALL)
                {
                  /* GDesc -> LE transition.
@@ -3799,6 +3876,46 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                              contents + roff);
                  continue;
                }
+             else if (r_type == R_X86_64_CODE_4_GOTTPOFF)
+               {
+                 /* IE->LE transition:
+                    Originally it can be one of:
+                    mov foo@gottpoff(%rip), %reg
+                    add foo@gottpoff(%rip), %reg
+                    We change it into:
+                    mov $foo@tpoff, %reg
+                    add $foo@tpoff, %reg
+                    where reg is one of r16 to r31.  */
+
+                 unsigned int rex2, type, reg;
+                 unsigned int rex2_mask = REX_R | REX_R << 4;
+
+                 if (roff < 4)
+                   goto corrupt_input;
+
+                 rex2 = bfd_get_8 (input_bfd, contents + roff - 3);
+                 type = bfd_get_8 (input_bfd, contents + roff - 2);
+                 reg = bfd_get_8 (input_bfd, contents + roff - 1);
+                 reg >>= 3;
+                 /* Move the R bits to the B bits in REX2 payload
+                    byte.  */
+                 if (type == 0x8b)
+                   type = 0xc7;
+                 else
+                   type = 0x81;
+                 bfd_put_8 (output_bfd,
+                            ((rex2 & ~rex2_mask)
+                             | (rex2 & rex2_mask) >> 2),
+                            contents + roff - 3);
+                 bfd_put_8 (output_bfd, type,
+                            contents + roff - 2);
+                 bfd_put_8 (output_bfd, 0xc0 | reg,
+                            contents + roff - 1);
+                 bfd_put_32 (output_bfd,
+                             elf_x86_64_tpoff (info, relocation),
+                             contents + roff);
+                 continue;
+               }
              else
                BFD_ASSERT (false);
            }
@@ -3905,6 +4022,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
          if (r_type_tls == r_type)
            {
              if (r_type == R_X86_64_GOTPC32_TLSDESC
+                 || r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC
                  || r_type == R_X86_64_TLSDESC_CALL)
                relocation = htab->elf.sgotplt->output_section->vma
                  + htab->elf.sgotplt->output_offset
@@ -4000,7 +4118,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                  wrel++;
                  continue;
                }
-             else if (r_type == R_X86_64_GOTPC32_TLSDESC)
+             else if (r_type == R_X86_64_GOTPC32_TLSDESC
+                      || r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC)
                {
                  /* GDesc -> IE transition.
                     It's originally something like:
index 8873fafdde9dc8b64447d50ae3f5109357585a43..196e7e55ea644b6def33032998e9c494db6dd838 100644 (file)
@@ -1461,6 +1461,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_X86_64_GOTPCRELX",
   "BFD_RELOC_X86_64_REX_GOTPCRELX",
   "BFD_RELOC_X86_64_CODE_4_GOTPCRELX",
+  "BFD_RELOC_X86_64_CODE_4_GOTTPOFF",
+  "BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
index 56d852d084f896338c7c0d9bdbeb042115695b52..30852b1422fd6afb91614a564ee35401b5b8cad0 100644 (file)
@@ -2477,6 +2477,10 @@ ENUMX
   BFD_RELOC_X86_64_REX_GOTPCRELX
 ENUMX
   BFD_RELOC_X86_64_CODE_4_GOTPCRELX
+ENUMX
+  BFD_RELOC_X86_64_CODE_4_GOTTPOFF
+ENUMX
+  BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC
 ENUMDOC
   x86-64/elf relocations.
 
index 8d76446010b38957881b2e872abfb89e278f4b91..694c494edec6e5ed011a6980f4fcf69db3d7a39e 100644 (file)
@@ -3601,10 +3601,12 @@ tc_i386_fix_adjustable (fixS *fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
       || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
+      || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTTPOFF
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
+      || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC
       || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
@@ -5632,6 +5634,7 @@ md_assemble (char *line)
          case BFD_RELOC_386_TLS_GOTIE:
          case BFD_RELOC_386_TLS_LE_32:
          case BFD_RELOC_X86_64_GOTTPOFF:
+         case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
          case BFD_RELOC_X86_64_TLSLD:
            as_bad (_("TLS relocation cannot be used with `%s'"), insn_name (&i.tm));
            return;
@@ -10477,6 +10480,7 @@ output_insn (const struct last_insn *last_insn)
             is also needed for lea with R_X86_64_GOTPC32_TLSDESC
             relocation for GDesc -> IE/LE optimization.  */
          if (x86_elf_abi == X86_64_X32_ABI
+             && !is_apx_rex2_encoding ()
              && i.operands == 2
              && (i.reloc[0] == BFD_RELOC_X86_64_GOTTPOFF
                  || i.reloc[0] == BFD_RELOC_X86_64_GOTPC32_TLSDESC)
@@ -10842,7 +10846,9 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
                    case BFD_RELOC_X86_64_TLSGD:
                    case BFD_RELOC_X86_64_TLSLD:
                    case BFD_RELOC_X86_64_GOTTPOFF:
+                   case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
                    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+                   case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
                    case BFD_RELOC_X86_64_TLSDESC_CALL:
                      i.has_gotpc_tls_reloc = true;
                    default:
@@ -14356,7 +14362,9 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       case BFD_RELOC_X86_64_TLSGD:
       case BFD_RELOC_X86_64_TLSLD:
       case BFD_RELOC_X86_64_GOTTPOFF:
+      case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
       case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+      case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
        value = 0; /* Fully resolved at runtime.  No addend.  */
        /* Fallthrough */
       case BFD_RELOC_386_TLS_LE:
@@ -15929,6 +15937,14 @@ i386_validate_fix (fixS *fixp)
     return IS_ELF && fixp->fx_addsy
           && (!S_IS_DEFINED (fixp->fx_addsy)
               || S_IS_EXTERNAL (fixp->fx_addsy));
+
+  if (fixp->fx_tcbit3)
+    {
+      if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF)
+       fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTTPOFF;
+      else if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC)
+       fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC;
+    }
 #endif
 
   if (fixp->fx_subsy)
@@ -16073,6 +16089,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
     case BFD_RELOC_X86_64_DTPOFF32:
     case BFD_RELOC_X86_64_DTPOFF64:
     case BFD_RELOC_X86_64_GOTTPOFF:
+    case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
     case BFD_RELOC_X86_64_TPOFF32:
     case BFD_RELOC_X86_64_TPOFF64:
     case BFD_RELOC_X86_64_GOTOFF64:
@@ -16083,6 +16100,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
     case BFD_RELOC_X86_64_GOTPLT64:
     case BFD_RELOC_X86_64_PLTOFF64:
     case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+    case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
     case BFD_RELOC_X86_64_TLSDESC_CALL:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
@@ -16215,7 +16233,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
          case BFD_RELOC_X86_64_TLSGD:
          case BFD_RELOC_X86_64_TLSLD:
          case BFD_RELOC_X86_64_GOTTPOFF:
+         case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
          case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+         case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
          case BFD_RELOC_X86_64_TLSDESC_CALL:
            rel->addend = fixp->fx_offset - fixp->fx_size;
            break;
diff --git a/gas/testsuite/gas/i386/x86-64-gottpoff.d b/gas/testsuite/gas/i386/x86-64-gottpoff.d
new file mode 100644 (file)
index 0000000..d42abcc
--- /dev/null
@@ -0,0 +1,19 @@
+#as:
+#objdump: -dwr
+#name: x86-64 gottpoff
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+:   48 03 05 00 00 00 00    add    0x0\(%rip\),%rax        # 7 <_start\+0x7>        3: R_X86_64_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   48 8b 05 00 00 00 00    mov    0x0\(%rip\),%rax        # e <_start\+0xe>        a: R_X86_64_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   d5 48 03 05 00 00 00 00         add    0x0\(%rip\),%r16        # 16 <_start\+0x16>      12: R_X86_64_CODE_4_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   d5 48 8b 25 00 00 00 00         mov    0x0\(%rip\),%r20        # 1e <_start\+0x1e>      1a: R_X86_64_CODE_4_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   48 03 05 00 00 00 00    add    0x0\(%rip\),%rax        # 25 <_start\+0x25>      21: R_X86_64_GOTTPOFF   foo-0x4
+ +[a-f0-9]+:   48 8b 05 00 00 00 00    mov    0x0\(%rip\),%rax        # 2c <_start\+0x2c>      28: R_X86_64_GOTTPOFF   foo-0x4
+ +[a-f0-9]+:   d5 48 03 05 00 00 00 00         add    0x0\(%rip\),%r16        # 34 <_start\+0x34>      30: R_X86_64_CODE_4_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   d5 48 8b 25 00 00 00 00         mov    0x0\(%rip\),%r20        # 3c <_start\+0x3c>      38: R_X86_64_CODE_4_GOTTPOFF    foo-0x4
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-gottpoff.s b/gas/testsuite/gas/i386/x86-64-gottpoff.s
new file mode 100644 (file)
index 0000000..6f8f9d1
--- /dev/null
@@ -0,0 +1,15 @@
+       .text
+_start:
+       addq    foo@GOTTPOFF(%rip), %rax
+       movq    foo@GOTTPOFF(%rip), %rax
+
+       addq    foo@GOTTPOFF(%rip), %r16
+       movq    foo@GOTTPOFF(%rip), %r20
+
+       .intel_syntax noprefix
+
+       addq    rax, QWORD PTR [rip + foo@GOTTPOFF]
+       movq    rax, QWORD PTR [rip + foo@GOTTPOFF]
+
+       addq    r16, QWORD PTR [rip + foo@GOTTPOFF]
+       movq    r20, QWORD PTR [rip + foo@GOTTPOFF]
diff --git a/gas/testsuite/gas/i386/x86-64-tlsdesc.d b/gas/testsuite/gas/i386/x86-64-tlsdesc.d
new file mode 100644 (file)
index 0000000..50c04e1
--- /dev/null
@@ -0,0 +1,17 @@
+#as:
+#objdump: -dwr
+#name: x86-64 tlsdesc
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+:   48 8d 05 00 00 00 00    lea    0x0\(%rip\),%rax        # 7 <_start\+0x7>        3: R_X86_64_GOTPC32_TLSDESC     foo-0x4
+ +[a-f0-9]+:   d5 48 8d 05 00 00 00 00         lea    0x0\(%rip\),%r16        # f <_start\+0xf>        b: R_X86_64_CODE_4_GOTPC32_TLSDESC      foo-0x4
+ +[a-f0-9]+:   d5 48 8d 25 00 00 00 00         lea    0x0\(%rip\),%r20        # 17 <_start\+0x17>      13: R_X86_64_CODE_4_GOTPC32_TLSDESC     foo-0x4
+ +[a-f0-9]+:   48 8d 05 00 00 00 00    lea    0x0\(%rip\),%rax        # 1e <_start\+0x1e>      1a: R_X86_64_GOTPC32_TLSDESC    foo-0x4
+ +[a-f0-9]+:   d5 48 8d 05 00 00 00 00         lea    0x0\(%rip\),%r16        # 26 <_start\+0x26>      22: R_X86_64_CODE_4_GOTPC32_TLSDESC     foo-0x4
+ +[a-f0-9]+:   d5 48 8d 25 00 00 00 00         lea    0x0\(%rip\),%r20        # 2e <_start\+0x2e>      2a: R_X86_64_CODE_4_GOTPC32_TLSDESC     foo-0x4
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-tlsdesc.s b/gas/testsuite/gas/i386/x86-64-tlsdesc.s
new file mode 100644 (file)
index 0000000..91f8d23
--- /dev/null
@@ -0,0 +1,13 @@
+       .text
+_start:
+       leaq    foo@TLSDESC(%rip), %rax
+
+       leaq    foo@TLSDESC(%rip), %r16
+       leaq    foo@TLSDESC(%rip), %r20
+
+       .intel_syntax noprefix
+
+       leaq    rax, QWORD PTR [rip + foo@TLSDESC]
+
+       leaq    r16, QWORD PTR [rip + foo@TLSDESC]
+       leaq    r20, QWORD PTR [rip + foo@TLSDESC]
index fa6a1c3c9458c54a7ed2bbaea972a41fb3f19321..cd28846ca8f79695e7706c471956e920a3fb646b 100644 (file)
@@ -665,6 +665,9 @@ if [is_elf_format] then {
     run_dump_test "x86-64-gotpcrel-no-relax"
     run_dump_test "x86-64-gotpcrel-2"
 
+    run_dump_test "x86-64-gottpoff"
+    run_dump_test "x86-64-tlsdesc"
+
     run_dump_test "x86-64-no-got"
 
     run_dump_test "x86-64-addend"
index 30d1722cb73151e5abe0455b9ee69f758b4c2c04..bbcf190532e358d0b503abceac72cf8d3b001aeb 100644 (file)
@@ -86,6 +86,12 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
        instruction starts at 4 bytes before the relocation offset,
        relaxable.  */
      RELOC_NUMBER (R_X86_64_CODE_4_GOTPCRELX, 43)
+     /* PC relative offset to IE GOT entry if the instruction starts at
+       4 bytes before the relocation offset.  */
+     RELOC_NUMBER (R_X86_64_CODE_4_GOTTPOFF, 44)
+     /* 32 bit signed pc relative offset to TLS descriptor in the GOT if
+       instruction starts at 4 bytes before the relocation offset.  */
+     RELOC_NUMBER (R_X86_64_CODE_4_GOTPC32_TLSDESC, 45)
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)
index 5bdb659555f681277d974d3fb6e47cebb7bb6fc3..4587cc751b40c15e746a1aaf6ff5ea5428bf8766 100644 (file)
@@ -165,6 +165,55 @@ Disassembly of section .text:
  +[0-9a-f]+:   90[     ]+nop *
  +[0-9a-f]+:   c9[     ]+leave *
  +[0-9a-f]+:   c3[     ]+ret *
+#  IE against global var
+ +[0-9a-f]+:   d5 48 03 05 ([0-9a-f]{2} ){3}[  ]+add    0x[0-9a-f]+\(%rip\),%r16 +# [0-9a-f]+ <sG2>
+#                              -> R_X86_64_TPOFF64     sG2
+ +[0-9a-f]+:   00 *
+#  IE -> LE against global var defined in exec
+ +[0-9a-f]+:   d5 18 81 c1 60 ff ff[   ]+add    \$0xf+60,%r17
+#                                                      sg1
+ +[0-9a-f]+:   ff *
+#  IE -> LE against local var
+ +[0-9a-f]+:   d5 18 81 c2 80 ff ff[   ]+add    \$0xf+80,%r18
+#                                                      sl1
+ +[0-9a-f]+:   ff *
+#  IE -> LE against hidden var
+ +[0-9a-f]+:   d5 18 81 c3 a0 ff ff[   ]+add    \$0xf+a0,%r19
+#                                                      sh1
+ +[0-9a-f]+:   ff *
+#  Direct access through %fs
+#  IE against global var
+ +[0-9a-f]+:   d5 48 8b 25 ([0-9a-f]{2} ){3}[  ]+mov    0x[0-9a-f]+\(%rip\),%r20 +# [0-9a-f]+ <sG5>
+#                              -> R_X86_64_TPOFF64     sG5
+ +[0-9a-f]+:   00 *
+#  IE->LE against local var
+ +[0-9a-f]+:   d5 18 c7 c5 90 ff ff[   ]+mov    \$0xf+90,%r21
+#                                                      sl5
+ +[0-9a-f]+:   ff *
+#  IE->LE against hidden var
+ +[0-9a-f]+:   d5 18 c7 c6 b0 ff ff[   ]+mov    \$0xf+b0,%r22
+ +[0-9a-f]+:   ff *
+#  GD -> IE because variable is not defined in executable
+ +[0-9a-f]+:   d5 48 8b 05 ([0-9a-f]{2} ){3}[  ]+mov    0x[0-9a-f]+\(%rip\),%r16 +# [0-9a-f]+ <sG1>
+#                              -> R_X86_64_TPOFF64     sG1
+ +[0-9a-f]+:   00 *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through IE too
+ +[0-9a-f]+:   d5 48 8b 0d ([0-9a-f]{2} ){3}[  ]+mov    0x[0-9a-f]+\(%rip\),%r17 +# [0-9a-f]+ <sG2>
+#                              -> R_X86_64_TPOFF64     sG2
+ +[0-9a-f]+:   00 *
+#  GD -> LE with global variable defined in executable
+ +[0-9a-f]+:   d5 18 c7 c2 60 ff ff[   ]+mov    \$0xf+60,%r18
+#                                                      sg1
+ +[0-9a-f]+:   ff *
+#  GD -> LE with local variable defined in executable
+ +[0-9a-f]+:   d5 18 c7 c3 80 ff ff[   ]+mov    \$0xf+80,%r19
+#                                                      sl1
+ +[0-9a-f]+:   ff *
+#  GD -> LE with hidden variable defined in executable
+ +[0-9a-f]+:   d5 18 c7 c4 a0 ff ff[   ]+mov    \$0xf+a0,%r20
+#                                                      sh1
+ +[0-9a-f]+:   ff *
 
 [0-9a-f]+ <_start>:
  +[0-9a-f]+:   55[     ]+push   %rbp
index 682c4a066a2bec86998ac05a7317ca60fbea15f9..daaea7a53716e0db7b5dffd3bc1f10767d6c420f 100644 (file)
@@ -15,12 +15,12 @@ Section Headers:
  +\[[ 0-9]+\] .dynsym +.*
  +\[[ 0-9]+\] .dynstr +.*
  +\[[ 0-9]+\] .rela.dyn +.*
- +\[[ 0-9]+\] .text +PROGBITS +0+401000 0+1000 0+1fd 00 +AX +0 +0 +4096
- +\[[ 0-9]+\] .tdata +PROGBITS +0+6011fd 0+11fd 0+60 00 WAT +0 +0 +1
- +\[[ 0-9]+\] .tbss +NOBITS +0+60125d 0+125d 0+40 00 WAT +0 +0 +1
- +\[[ 0-9]+\] .dynamic +DYNAMIC +0+601260 0+1260 0+100 10 +WA +4 +0 +8
- +\[[ 0-9]+\] .got +PROGBITS +0+601360 0+1360 0+20 08 +WA +0 +0 +8
- +\[[ 0-9]+\] .got.plt +PROGBITS +0+601380 0+1380 0+18 08 +WA +0 +0 +8
+ +\[[ 0-9]+\] .text +PROGBITS +0+401000 0+1000 0+25d 00 +AX +0 +0 +4096
+ +\[[ 0-9]+\] .tdata +PROGBITS +0+60125d 0+125d 0+60 00 WAT +0 +0 +1
+ +\[[ 0-9]+\] .tbss +NOBITS +0+6012bd 0+12bd 0+40 00 WAT +0 +0 +1
+ +\[[ 0-9]+\] .dynamic +DYNAMIC +0+6012c0 0+12c0 0+100 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] .got +PROGBITS +0+6013c0 0+13c0 0+20 08 +WA +0 +0 +8
+ +\[[ 0-9]+\] .got.plt +PROGBITS +0+6013e0 0+13e0 0+18 08 +WA +0 +0 +8
  +\[[ 0-9]+\] .symtab +.*
  +\[[ 0-9]+\] .strtab +.*
  +\[[ 0-9]+\] .shstrtab +.*
@@ -28,7 +28,7 @@ Key to Flags:
 #...
 
 Elf file type is EXEC \(Executable file\)
-Entry point 0x401105
+Entry point 0x401165
 There are [0-9]+ program headers, starting at offset [0-9]+
 
 Program Headers:
@@ -36,10 +36,10 @@ Program Headers:
  +PHDR.*
  +INTERP.*
 .*Requesting program interpreter.*
- +LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11fd 0x0+11fd R E 0x200000
- +LOAD +0x0+11fd 0x0+6011fd 0x0+6011fd 0x0+19b 0x0+19b RW +0x200000
- +DYNAMIC +0x0+1260 0x0+601260 0x0+601260 0x0+100 0x0+100 RW +0x8
- +TLS +0x0+11fd 0x0+6011fd 0x0+6011fd 0x0+60 0x0+a0 R +0x1
+ +LOAD +0x0+ 0x0+400000 0x0+400000 0x0+125d 0x0+125d R E 0x200000
+ +LOAD +0x0+125d 0x0+60125d 0x0+60125d 0x0+19b 0x0+19b RW +0x200000
+ +DYNAMIC +0x0+12c0 0x0+6012c0 0x0+6012c0 0x0+100 0x0+100 RW +0x8
+ +TLS +0x0+125d 0x0+60125d 0x0+60125d 0x0+60 0x0+a0 R +0x1
 
  Section to Segment mapping:
  +Segment Sections...
@@ -52,10 +52,10 @@ Program Headers:
 
 Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
-0+601360 +0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
-0+601368 +0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
-0+601370 +0+300000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
-0+601378 +0+400000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
+0+6013c0 +0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+0+6013c8 +0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
+0+6013d0 +0+300000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+0+6013d8 +0+400000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
 
 Symbol table '\.dynsym' contains [0-9]+ entries:
  +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
@@ -88,8 +88,8 @@ Symbol table '\.symtab' contains [0-9]+ entries:
  +[0-9]+: 0+9c +0 +TLS +LOCAL +DEFAULT +8 bl8
 .* FILE +LOCAL +DEFAULT +ABS 
  +[0-9]+: 0+a0 +0 +TLS +LOCAL +DEFAULT +7 _TLS_MODULE_BASE_
- +[0-9]+: 0+601260 +0 +OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
- +[0-9]+: 0+601380 +0 +OBJECT +LOCAL +DEFAULT +11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+6012c0 +0 +OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
+ +[0-9]+: 0+6013e0 +0 +OBJECT +LOCAL +DEFAULT +11 _GLOBAL_OFFSET_TABLE_
  +[0-9]+: 0+1c +0 +TLS +GLOBAL +DEFAULT +7 sg8
  +[0-9]+: 0+7c +0 +TLS +GLOBAL +DEFAULT +8 bg8
  +[0-9]+: 0+74 +0 +TLS +GLOBAL +DEFAULT +8 bg6
@@ -104,7 +104,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
  +[0-9]+: 0+58 +0 +TLS +GLOBAL +HIDDEN +7 sh7
  +[0-9]+: 0+5c +0 +TLS +GLOBAL +HIDDEN +7 sh8
  +[0-9]+: 0+ +0 +TLS +GLOBAL +DEFAULT +7 sg1
- +[0-9]+: 0+401105 +0 +FUNC +GLOBAL +DEFAULT +6 _start
+ +[0-9]+: 0+401165 +0 +FUNC +GLOBAL +DEFAULT +6 _start
  +[0-9]+: 0+4c +0 +TLS +GLOBAL +HIDDEN +7 sh4
  +[0-9]+: 0+78 +0 +TLS +GLOBAL +DEFAULT +8 bg7
  +[0-9]+: 0+50 +0 +TLS +GLOBAL +HIDDEN +7 sh5
index cbebf02171d7dec1e0ad61df90e21971727184df..b80e5f192c0d3556a5e1e37c66fef3b061b11cbc 100644 (file)
@@ -126,3 +126,42 @@ fn2:
 
        leave
        ret
+
+       /* IE against global var  */
+       addq    sG2@gottpoff(%rip), %r16
+
+       /* IE -> LE against global var defined in exec */
+       addq    sg1@gottpoff(%rip), %r17
+
+       /* IE -> LE against local var */
+       addq    sl1@gottpoff(%rip), %r18
+
+       /* IE -> LE against hidden var */
+       addq    sh1@gottpoff(%rip), %r19
+
+       /* Direct access through %fs  */
+
+       /* IE against global var  */
+       movq    sG5@gottpoff(%rip), %r20
+
+       /* IE->LE against local var  */
+       movq    sl5@gottpoff(%rip), %r21
+
+       /* IE->LE against hidden var  */
+       movq    sh5@gottpoff(%rip), %r22
+
+       /* GD -> IE because variable is not defined in executable */
+       leaq    sG1@tlsdesc(%rip), %r16
+
+       /* GD -> IE because variable is not defined in executable where
+          the variable is referenced through IE too */
+       leaq    sG2@tlsdesc(%rip), %r17
+
+       /* GD -> LE with global variable defined in executable */
+       leaq    sg1@tlsdesc(%rip), %r18
+
+       /* GD -> LE with local variable defined in executable */
+       leaq    sl1@tlsdesc(%rip), %r19
+
+       /* GD -> LE with hidden variable defined in executable */
+       leaq    sh1@tlsdesc(%rip), %r20