This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Add R_X86_64_[REX_]GOTPCRELX support to gas and ld


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=56ceb5b5405af23eddd12e12d8ba849010120324

commit 56ceb5b5405af23eddd12e12d8ba849010120324
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Oct 22 04:49:20 2015 -0700

    Add R_X86_64_[REX_]GOTPCRELX support to gas and ld
    
    This patch adds support for the R_X86_64_GOTPCRELX and
    R_X86_64_REX_GOTPCRELX relocations proposed in
    
    https://groups.google.com/forum/#!topic/x86-64-abi/n9AWHogmVY0
    
    to gas and ld.  It updates gas to generate R_X86_64_GOTPCRELX,
    R_X86_64_REX_GOTPCRELX if there is a REX prefix, relocation for memory
    operand, foo@GOTPCREL(%rip).  With the locally defined symbol, foo, we
    convert
    
      mov foo@GOTPCREL(%rip), %reg
    
    to
    
       lea foo(%rip), %reg
    
    and convert
    
       call/jmp *foo@GOTPCREL(%rip)
    to
    
       nop call foo/jmp foo nop
    
    When PIC is false, convert
    
       test %reg, foo@GOTPCREL(%rip)
    to
    
    test $foo, %reg
    
    and convert
    
       binop foo@GOTPCREL(%rip), %reg
    
    to
    
       binop $foo, %reg
    
    where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions.
    
    bfd/
    
    	* elf64-x86-64.c: Include opcode/i386.h.
    	(x86_64_elf_howto_table): Add R_X86_64_GOTPCRELX and
    	R_X86_64_REX_GOTPCRELX.
    	(R_X86_64_standard): Replace R_X86_64_PLT32_BND with
    	R_X86_64_REX_GOTPCRELX.
    	(x86_64_reloc_map): Add BFD_RELOC_X86_64_GOTPCRELX and
    	BFD_RELOC_X86_64_REX_GOTPCRELX.
    	(need_convert_mov_to_lea): Renamed to ...
    	(need_convert_load): This.
    	(elf_x86_64_check_relocs): Handle R_X86_64_GOTPCRELX and
    	R_X86_64_REX_GOTPCRELX.  Replace need_convert_mov_to_lea with
    	need_convert_load.
    	(elf_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPCRELX and
    	R_X86_64_REX_GOTPCRELX.
    	(elf_x86_64_size_dynamic_sections): Likewise.
    	(elf_x86_64_relocate_section): Likewise.
    	(elf_x86_64_convert_mov_to_lea): Renamed to ...
    	(elf_x86_64_convert_load): This.  Replace need_convert_mov_to_lea
    	with need_convert_load.  Support R_X86_64_GOTPCRELX and
    	R_X86_64_REX_GOTPCRELX transformations.
    	* reloc.c (BFD_RELOC_X86_64_GOTPCRELX): New.
    	(BFD_RELOC_X86_64_REX_GOTPCRELX): Likewise.
    	* bfd-in2.h: Regenerated.
    	* libbfd.h: Likewise.
    
    gas/
    
    	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
    	BFD_RELOC_X86_64_GOTPCRELX and BFD_RELOC_X86_64_REX_GOTPCRELX.
    	(tc_gen_reloc): Likewise.
    	(i386_validate_fix): Generate BFD_RELOC_X86_64_GOTPCRELX or
    	BFD_RELOC_X86_64_REX_GOTPCRELX if fx_tcbit2 is set.
    	* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Also return
    	true for BFD_RELOC_X86_64_GOTPCRELX and
    	BFD_RELOC_X86_64_REX_GOTPCRELX.
    
    gas/testsuite/
    
    	* gas/i386/i386.exp: Run x86-64-gotpcrel.
    	* gas/i386/x86-64-gotpcrel.d: New file.
    	* gas/i386/x86-64-gotpcrel.s: Likewise.
    	* gas/i386/ilp32/x86-64-gotpcrel.d: Likewise.
    	* gas/i386/x86-64-localpic.d: Replace R_X86_64_GOTPCREL with
    	R_X86_64_REX_GOTPCRELX.
    	* gas/i386/ilp32/x86-64-localpic.d: Likewise.
    
    include/elf/
    
    	* x86-64.h (R_X86_64_GOTPCRELX): New.
    	(R_X86_64_REX_GOTPCRELX): Likewise.
    
    ld/testsuite/
    
    	* ld-ifunc/ifunc-5r-local-x86-64.d: Replace R_X86_64_GOTPCREL
    	with R_X86_64_REX_GOTPCRELX.
    	* ld-x86-64/plt-main1.rd: Likewise.
    	* ld-x86-64/plt-main3.rd: Likewise.
    	* ld-x86-64/plt-main4.rd: Likewise.
    	* ld-x86-64/gotpcrel1.dd: New file.
    	* ld-x86-64/gotpcrel1.out: Likewise.
    	* ld-x86-64/gotpcrel1a.S: Likewise.
    	* ld-x86-64/gotpcrel1b.c: Likewise.
    	* ld-x86-64/gotpcrel1c.c: Likewise.
    	* ld-x86-64/gotpcrel1d.S: Likewise.
    	* ld-x86-64/load1.s: Likewise.
    	* ld-x86-64/load1a.d: Likewise.
    	* ld-x86-64/load1b.d: Likewise.
    	* ld-x86-64/load1c.d: Likewise.
    	* ld-x86-64/load1d.d: Likewise.
    	* ld-x86-64/x86-64.exp: Run load1a, load1b, load1c and load1d
    	tests.  Run gotpcrel1 test.

Diff:
---
 bfd/ChangeLog                                  |  27 ++++
 bfd/bfd-in2.h                                  |   2 +
 bfd/elf64-x86-64.c                             | 194 +++++++++++++++++++++----
 bfd/libbfd.h                                   |   2 +
 bfd/reloc.c                                    |   4 +
 gas/ChangeLog                                  |  11 ++
 gas/config/tc-i386.c                           |  10 +-
 gas/config/tc-i386.h                           |  11 +-
 gas/testsuite/ChangeLog                        |  10 ++
 gas/testsuite/gas/i386/i386.exp                |   2 +
 gas/testsuite/gas/i386/ilp32/x86-64-gotpcrel.d |  27 ++++
 gas/testsuite/gas/i386/ilp32/x86-64-localpic.d |   6 +-
 gas/testsuite/gas/i386/x86-64-gotpcrel.d       |  25 ++++
 gas/testsuite/gas/i386/x86-64-gotpcrel.s       |  23 +++
 gas/testsuite/gas/i386/x86-64-localpic.d       |   6 +-
 include/elf/ChangeLog                          |   5 +
 include/elf/x86-64.h                           |  14 +-
 ld/testsuite/ChangeLog                         |  21 +++
 ld/testsuite/ld-ifunc/ifunc-5r-local-x86-64.d  |   2 +-
 ld/testsuite/ld-x86-64/gotpcrel1.dd            |  17 +++
 ld/testsuite/ld-x86-64/gotpcrel1.out           |   8 +
 ld/testsuite/ld-x86-64/gotpcrel1a.S            |  18 +++
 ld/testsuite/ld-x86-64/gotpcrel1b.c            |   7 +
 ld/testsuite/ld-x86-64/gotpcrel1c.c            |   7 +
 ld/testsuite/ld-x86-64/gotpcrel1d.S            |  26 ++++
 ld/testsuite/ld-x86-64/load1.s                 |  51 +++++++
 ld/testsuite/ld-x86-64/load1a.d                |  54 +++++++
 ld/testsuite/ld-x86-64/load1b.d                |  55 +++++++
 ld/testsuite/ld-x86-64/load1c.d                |  47 ++++++
 ld/testsuite/ld-x86-64/load1d.d                |  47 ++++++
 ld/testsuite/ld-x86-64/plt-main1.rd            |   2 +-
 ld/testsuite/ld-x86-64/plt-main3.rd            |   2 +-
 ld/testsuite/ld-x86-64/plt-main4.rd            |   2 +-
 ld/testsuite/ld-x86-64/x86-64.exp              |  28 ++++
 34 files changed, 723 insertions(+), 50 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index a2e3034..afc8029 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,32 @@
 2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* elf64-x86-64.c: Include opcode/i386.h.
+	(x86_64_elf_howto_table): Add R_X86_64_GOTPCRELX and
+	R_X86_64_REX_GOTPCRELX.
+	(R_X86_64_standard): Replace R_X86_64_PLT32_BND with
+	R_X86_64_REX_GOTPCRELX.
+	(x86_64_reloc_map): Add BFD_RELOC_X86_64_GOTPCRELX and
+	BFD_RELOC_X86_64_REX_GOTPCRELX.
+	(need_convert_mov_to_lea): Renamed to ...
+	(need_convert_load): This.
+	(elf_x86_64_check_relocs): Handle R_X86_64_GOTPCRELX and
+	R_X86_64_REX_GOTPCRELX.  Replace need_convert_mov_to_lea with
+	need_convert_load.
+	(elf_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPCRELX and
+	R_X86_64_REX_GOTPCRELX.
+	(elf_x86_64_size_dynamic_sections): Likewise.
+	(elf_x86_64_relocate_section): Likewise.
+	(elf_x86_64_convert_mov_to_lea): Renamed to ...
+	(elf_x86_64_convert_load): This.  Replace need_convert_mov_to_lea
+	with need_convert_load.  Support R_X86_64_GOTPCRELX and
+	R_X86_64_REX_GOTPCRELX transformations.
+	* reloc.c (BFD_RELOC_X86_64_GOTPCRELX): New.
+	(BFD_RELOC_X86_64_REX_GOTPCRELX): Likewise.
+	* bfd-in2.h: Regenerated.
+	* libbfd.h: Likewise.
+
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
 	* elf32-i386.c: Include opcode/i386.h.
 	(elf_howto_table): Add R_386_GOT32X.
 	(R_386_ext2): Replace R_386_IRELATIVE with R_386_GOT32X.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index ad246c8..9345e88 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3209,6 +3209,8 @@ instruction.  */
   BFD_RELOC_X86_64_IRELATIVE,
   BFD_RELOC_X86_64_PC32_BND,
   BFD_RELOC_X86_64_PLT32_BND,
+  BFD_RELOC_X86_64_GOTPCRELX,
+  BFD_RELOC_X86_64_REX_GOTPCRELX,
 
 /* ns32k relocations  */
   BFD_RELOC_NS32K_IMM_8,
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index dc5fd0d..f8bb0d5 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -31,6 +31,7 @@
 #include "dwarf2.h"
 #include "libiberty.h"
 
+#include "opcode/i386.h"
 #include "elf/x86-64.h"
 
 #ifdef CORE_HEADER
@@ -176,12 +177,18 @@ static reloc_howto_type x86_64_elf_howto_table[] =
   HOWTO(R_X86_64_PLT32_BND, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_PLT32_BND", FALSE, 0xffffffff, 0xffffffff,
 	TRUE),
+  HOWTO(R_X86_64_GOTPCRELX, 0, 2, 32, TRUE, 0, complain_overflow_signed,
+	bfd_elf_generic_reloc, "R_X86_64_GOTPCRELX", FALSE, 0xffffffff,
+	0xffffffff, TRUE),
+  HOWTO(R_X86_64_REX_GOTPCRELX, 0, 2, 32, TRUE, 0, complain_overflow_signed,
+	bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", FALSE, 0xffffffff,
+	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_PLT32_BND + 1)
+#define R_X86_64_standard (R_X86_64_REX_GOTPCRELX + 1)
 #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -253,8 +260,10 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
   { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
   { BFD_RELOC_X86_64_TLSDESC,	R_X86_64_TLSDESC, },
   { BFD_RELOC_X86_64_IRELATIVE,	R_X86_64_IRELATIVE, },
-  { BFD_RELOC_X86_64_PC32_BND,	R_X86_64_PC32_BND,},
-  { BFD_RELOC_X86_64_PLT32_BND,	R_X86_64_PLT32_BND,},
+  { BFD_RELOC_X86_64_PC32_BND,	R_X86_64_PC32_BND, },
+  { BFD_RELOC_X86_64_PLT32_BND,	R_X86_64_PLT32_BND, },
+  { BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, },
+  { BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, },
   { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
 };
@@ -1545,7 +1554,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
 /* Rename some of the generic section flags to better document how they
    are used here.  */
-#define need_convert_mov_to_lea sec_flg0
+#define need_convert_load sec_flg0
 
 /* Look through the relocs for a section during the first phase, and
    calculate needed space in the global offset table, procedure
@@ -1726,6 +1735,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    case R_X86_64_32S:
 	    case R_X86_64_PC64:
 	    case R_X86_64_GOTPCREL:
+	    case R_X86_64_GOTPCRELX:
+	    case R_X86_64_REX_GOTPCRELX:
 	    case R_X86_64_GOTPCREL64:
 	      if (htab->elf.dynobj == NULL)
 		htab->elf.dynobj = abfd;
@@ -1779,6 +1790,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
+	case R_X86_64_GOTPCRELX:
+	case R_X86_64_REX_GOTPCRELX:
 	case R_X86_64_TLSGD:
 	case R_X86_64_GOT64:
 	case R_X86_64_GOTPCREL64:
@@ -2151,9 +2164,11 @@ do_size:
 	    return FALSE;
 	}
 
-      if (r_type == R_X86_64_GOTPCREL
+      if ((r_type == R_X86_64_GOTPCREL
+	   || r_type == R_X86_64_GOTPCRELX
+	   || r_type == R_X86_64_REX_GOTPCRELX)
 	  && (h == NULL || h->type != STT_GNU_IFUNC))
-	sec->need_convert_mov_to_lea = 1;
+	sec->need_convert_load = 1;
     }
 
   return TRUE;
@@ -2279,6 +2294,8 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
 	case R_X86_64_GOTTPOFF:
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
+	case R_X86_64_GOTPCRELX:
+	case R_X86_64_REX_GOTPCRELX:
 	case R_X86_64_GOT64:
 	case R_X86_64_GOTPCREL64:
 	case R_X86_64_GOTPLT64:
@@ -2953,15 +2970,28 @@ elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h,
   return TRUE;
 }
 
-/* Convert
+/* With the local symbol, foo, we convert
    mov foo@GOTPCREL(%rip), %reg
    to
    lea foo(%rip), %reg
-   with the local symbol, foo.  */
+   and convert
+   call/jmp *foo@GOTPCREL(%rip)
+   to
+   nop call foo/jmp foo nop
+   When PIC is false, convert
+   test %reg, foo@GOTPCREL(%rip)
+   to
+   test $foo, %reg
+   and convert
+   binop foo@GOTPCREL(%rip), %reg
+   to
+   binop $foo, %reg
+   where binop is one of adc, add, and, cmp, or, sbb, sub, xor
+   instructions.  */
 
 static bfd_boolean
-elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
-			       struct bfd_link_info *link_info)
+elf_x86_64_convert_load (bfd *abfd, asection *sec,
+			 struct bfd_link_info *link_info)
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs;
@@ -2979,7 +3009,7 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
 
   /* Nothing to do if there is no need or no output.  */
   if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
-      || sec->need_convert_mov_to_lea == 0
+      || sec->need_convert_load == 0
       || bfd_is_abs_section (sec->output_section))
     return TRUE;
 
@@ -3017,22 +3047,45 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
       asection *tsec;
       char symtype;
       bfd_vma toff, roff;
+      bfd_signed_vma raddend;
       unsigned int opcode;
+      unsigned int modrm;
 
-      if (r_type != R_X86_64_GOTPCREL)
+      if (r_type != R_X86_64_GOTPCREL
+	  && r_type != R_X86_64_GOTPCRELX
+	  && r_type != R_X86_64_REX_GOTPCRELX)
 	continue;
 
       roff = irel->r_offset;
+      if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
+	continue;
 
-      if (roff < 2)
+      raddend = irel->r_addend;
+      /* Addend for 32-bit PC-relative relocation must be -4.  */
+      if (raddend != -4)
 	continue;
 
       opcode = bfd_get_8 (abfd, contents + roff - 2);
 
-      /* PR ld/18591: Don't convert R_X86_64_GOTPCREL relocation if it
-         isn't for mov instruction.  */
+      /* It is OK to convert mov to lea.  */
       if (opcode != 0x8b)
-	continue;
+	{
+	  /* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX
+	     for mov call, jmp or one of adc, add, and, cmp, or, sbb,
+	     sub, test, xor instructions.  */
+	  if (r_type != R_X86_64_GOTPCRELX
+	      && r_type != R_X86_64_REX_GOTPCRELX)
+	    continue;
+
+	  /* It is OK to convert indirect branch to direct branch.  */
+	  if (opcode != 0xff)
+	    {
+	      /* It is OK to convert adc, add, and, cmp, or, sbb, sub,
+		 test, xor only when PIC is false.   */
+	      if (bfd_link_pic (link_info))
+		continue;
+	    }
+	}
 
       /* Get the symbol referred to by the reloc.  */
       if (r_symndx < symtab_hdr->sh_info)
@@ -3044,8 +3097,8 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
 
 	  symtype = ELF_ST_TYPE (isym->st_info);
 
-	  /* STT_GNU_IFUNC must keep R_X86_64_GOTPCREL relocation and
-	     skip relocation against undefined symbols.  */
+	  /* STT_GNU_IFUNC must keep GOTPCREL relocations and skip
+	     relocation against undefined symbols.  */
 	  if (symtype == STT_GNU_IFUNC || isym->st_shndx == SHN_UNDEF)
 	    continue;
 
@@ -3071,9 +3124,9 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
 		 || h->root.type == bfd_link_hash_warning)
 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-	  /* STT_GNU_IFUNC must keep R_X86_64_GOTPCREL relocation.  We also
-	     avoid optimizing _DYNAMIC since ld.so may use its link-time
-	     address.  */
+	  /* STT_GNU_IFUNC must keep GOTPCREL relocations.  We also
+	     avoid optimizing GOTPCREL relocations againt _DYNAMIC
+	     since ld.so may use its link-time address.  */
 	  if ((h->root.type == bfd_link_hash_defined
 	       || h->root.type == bfd_link_hash_defweak)
 	      && h->type != STT_GNU_IFUNC
@@ -3107,17 +3160,17 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
 	     access is presumed to be an offset from "sym";  The
 	     location of interest is just "sym".  */
 	   if (symtype == STT_SECTION)
-	     toff += irel->r_addend;
+	     toff += raddend;
 
 	   toff = _bfd_merged_section_offset (abfd, &tsec,
 					      elf_section_data (tsec)->sec_info,
 					      toff);
 
 	   if (symtype != STT_SECTION)
-	     toff += irel->r_addend;
+	     toff += raddend;
 	}
       else
-	toff += irel->r_addend;
+	toff += raddend;
 
       /* Don't convert if R_X86_64_PC32 relocation overflows.  */
       if (tsec->output_section == sec->output_section)
@@ -3148,8 +3201,8 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
 		}
 	    }
 
-	  /* Don't convert R_X86_64_GOTPCREL if TSEC isn't placed after
-	     SEC.  */
+	  /* Don't convert GOTPCREL relocations if TSEC isn't placed
+	     after SEC.  */
 	  if (asect == NULL)
 	    continue;
 
@@ -3160,8 +3213,82 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
 	    continue;
 	}
 
-      bfd_put_8 (abfd, 0x8d, contents + roff - 2);
-      irel->r_info = htab->r_info (r_symndx, R_X86_64_PC32);
+      if (opcode == 0xff)
+	{
+	  /* We have "call/jmp *foo@GOTPCREL(%rip)".  */
+	  unsigned int nop;
+	  bfd_vma nop_offset;
+
+	  /* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to
+	     R_X86_64_PC32.  */
+	  modrm = bfd_get_8 (abfd, contents + roff - 1);
+	  if (modrm == 0x25)
+	    {
+	      unsigned int disp;
+	      /* Convert to "jmp foo nop".  */
+	      modrm = 0xe9;
+	      nop = NOP_OPCODE;
+	      nop_offset = irel->r_offset + 3;
+	      disp = bfd_get_32 (abfd, contents + irel->r_offset);
+	      irel->r_offset -= 1;
+	      bfd_put_32 (abfd, disp, contents + irel->r_offset);
+	    }
+	  else
+	    {
+	      /* Convert to "nop call foo".  ADDR_PREFIX_OPCODE
+		 is a nop prefix.  */
+	      modrm = 0xe8;
+	      nop = ADDR_PREFIX_OPCODE;
+	      nop_offset = irel->r_offset - 2;
+	    }
+	  bfd_put_8 (abfd, nop, contents + nop_offset);
+	  bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
+	  r_type = R_X86_64_PC32;
+	}
+      else
+	{
+	  if (opcode == 0x8b)
+	    {
+	      /* Convert "mov foo@GOTPCREL(%rip), %reg" to
+		 "lea foo(%rip), %reg".  */
+	      opcode = 0x8d;
+	      r_type = R_X86_64_PC32;
+	    }
+	  else
+	    {
+	      modrm = bfd_get_8 (abfd, contents + roff - 1);
+	      if (opcode == 0x85)
+		{
+		  /* Convert "test %reg, foo@GOTPCREL(%rip)" to
+		     "test $foo, %reg".  */
+		  modrm = 0xc0 | (modrm & 0x38) >> 3;
+		  opcode = 0xf7;
+		}
+	      else
+		{
+		  /* Convert "binop foo@GOTPCREL(%rip), %reg" to
+		     "binop $foo, %reg".  */
+		  modrm = 0xc0 | (modrm & 0x38) >> 3 | (opcode & 0x3c);
+		  opcode = 0x81;
+		}
+	      bfd_put_8 (abfd, modrm, contents + roff - 1);
+
+	      if (r_type == R_X86_64_REX_GOTPCRELX)
+		{
+		  /* Move the R bit to the B bit in REX byte.  */
+		  unsigned int rex = bfd_get_8 (abfd, contents + roff - 3);
+		  rex = (rex & ~REX_R) | (rex & REX_R) >> 2;
+		  bfd_put_8 (abfd, rex, contents + roff - 3);
+		}
+	      /* No addend for R_X86_64_32S relocation.  */
+	      irel->r_addend = 0;
+	      r_type = R_X86_64_32S;
+	    }
+
+	  bfd_put_8 (abfd, opcode, contents + roff - 2);
+	}
+
+      irel->r_info = htab->r_info (r_symndx, r_type);
       changed_contents = TRUE;
       changed_relocs = TRUE;
 
@@ -3264,7 +3391,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
 	{
 	  struct elf_dyn_relocs *p;
 
-	  if (!elf_x86_64_convert_mov_to_lea (ibfd, s, info))
+	  if (!elf_x86_64_convert_load (ibfd, s, info))
 	    return FALSE;
 
 	  for (p = (struct elf_dyn_relocs *)
@@ -3985,6 +4112,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 	      goto do_relocation;
 
 	    case R_X86_64_GOTPCREL:
+	    case R_X86_64_GOTPCRELX:
+	    case R_X86_64_REX_GOTPCRELX:
 	    case R_X86_64_GOTPCREL64:
 	      base_got = htab->elf.sgot;
 	      off = h->got.offset;
@@ -4053,6 +4182,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 	  /* Relocation is to the entry for this symbol in the global
 	     offset table.  */
 	case R_X86_64_GOTPCREL:
+	case R_X86_64_GOTPCRELX:
+	case R_X86_64_REX_GOTPCRELX:
 	case R_X86_64_GOTPCREL64:
 	  /* Use global offset table entry as symbol value.  */
 	case R_X86_64_GOTPLT64:
@@ -4158,7 +4289,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 
 	  relocation = base_got->output_section->vma
 		       + base_got->output_offset + off;
-	  if (r_type != R_X86_64_GOTPCREL && r_type != R_X86_64_GOTPCREL64)
+	  if (r_type != R_X86_64_GOTPCREL
+	      && r_type != R_X86_64_GOTPCRELX
+	      && r_type != R_X86_64_REX_GOTPCRELX
+	      && r_type != R_X86_64_GOTPCREL64)
 	    relocation -= htab->elf.sgotplt->output_section->vma
 			  - htab->elf.sgotplt->output_offset;
 
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 3bf1400..57300e9 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1322,6 +1322,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_X86_64_IRELATIVE",
   "BFD_RELOC_X86_64_PC32_BND",
   "BFD_RELOC_X86_64_PLT32_BND",
+  "BFD_RELOC_X86_64_GOTPCRELX",
+  "BFD_RELOC_X86_64_REX_GOTPCRELX",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index c6e2807..aa3d24f 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2739,6 +2739,10 @@ ENUMX
   BFD_RELOC_X86_64_PC32_BND
 ENUMX
   BFD_RELOC_X86_64_PLT32_BND
+ENUMX
+  BFD_RELOC_X86_64_GOTPCRELX
+ENUMX
+  BFD_RELOC_X86_64_REX_GOTPCRELX
 ENUMDOC
   x86-64/elf relocations
 
diff --git a/gas/ChangeLog b/gas/ChangeLog
index d2d0da4..f9d87ba 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,6 +1,17 @@
 2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
+	BFD_RELOC_X86_64_GOTPCRELX and BFD_RELOC_X86_64_REX_GOTPCRELX.
+	(tc_gen_reloc): Likewise.
+	(i386_validate_fix): Generate BFD_RELOC_X86_64_GOTPCRELX or
+	BFD_RELOC_X86_64_REX_GOTPCRELX if fx_tcbit2 is set.
+	* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Also return
+	true for BFD_RELOC_X86_64_GOTPCRELX and
+	BFD_RELOC_X86_64_REX_GOTPCRELX.
+
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
 	BFD_RELOC_386_GOT32X.
 	(tc_gen_reloc): Likewise.
 	(match_template): Force 0x8b encoding for "mov foo@GOT, %eax".
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index dd1a41b..d74e870 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -2942,6 +2942,8 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
       || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX
+      || fixP->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX
       || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
       || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
       || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
@@ -10363,7 +10365,9 @@ i386_validate_fix (fixS *fixp)
 		abort ();
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 	      if (fixp->fx_tcbit2)
-		fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
+		fixp->fx_r_type = (fixp->fx_tcbit
+				   ? BFD_RELOC_X86_64_REX_GOTPCRELX
+				   : BFD_RELOC_X86_64_GOTPCRELX);
 	      else
 #endif
 		fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
@@ -10419,6 +10423,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
     case BFD_RELOC_X86_64_PLT32:
     case BFD_RELOC_X86_64_GOT32:
     case BFD_RELOC_X86_64_GOTPCREL:
+    case BFD_RELOC_X86_64_GOTPCRELX:
+    case BFD_RELOC_X86_64_REX_GOTPCRELX:
     case BFD_RELOC_386_PLT32:
     case BFD_RELOC_386_GOT32:
     case BFD_RELOC_386_GOT32X:
@@ -10573,6 +10579,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 	  case BFD_RELOC_X86_64_PLT32:
 	  case BFD_RELOC_X86_64_GOT32:
 	  case BFD_RELOC_X86_64_GOTPCREL:
+	  case BFD_RELOC_X86_64_GOTPCRELX:
+	  case BFD_RELOC_X86_64_REX_GOTPCRELX:
 	  case BFD_RELOC_X86_64_TLSGD:
 	  case BFD_RELOC_X86_64_TLSLD:
 	  case BFD_RELOC_X86_64_GOTTPOFF:
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 40483a1..2c43044 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -170,11 +170,12 @@ extern int tc_i386_fix_adjustable (struct fix *);
    the .o file.  GOTOFF and GOT32 do not need to be checked here because
    they are not pcrel.  .*/
 
-#define TC_FORCE_RELOCATION_LOCAL(FIX)			\
-  (!(FIX)->fx_pcrel					\
-   || (FIX)->fx_r_type == BFD_RELOC_386_PLT32		\
-   || (FIX)->fx_r_type == BFD_RELOC_386_GOTPC		\
-   || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL	\
+#define TC_FORCE_RELOCATION_LOCAL(FIX)				\
+  (!(FIX)->fx_pcrel						\
+   || (FIX)->fx_r_type == BFD_RELOC_386_PLT32			\
+   || (FIX)->fx_r_type == BFD_RELOC_386_GOTPC			\
+   || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX		\
+   || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX	\
    || TC_FORCE_RELOCATION (FIX))
 
 extern int i386_parse_name (char *, expressionS *, char *);
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index d149faa..07ec4c8 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,5 +1,15 @@
 2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* gas/i386/i386.exp: Run x86-64-gotpcrel.
+	* gas/i386/x86-64-gotpcrel.d: New file.
+	* gas/i386/x86-64-gotpcrel.s: Likewise.
+	* gas/i386/ilp32/x86-64-gotpcrel.d: Likewise.
+	* gas/i386/x86-64-localpic.d: Replace R_X86_64_GOTPCREL with
+	R_X86_64_REX_GOTPCRELX.
+	* gas/i386/ilp32/x86-64-localpic.d: Likewise.
+
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
 	* gas/i386/got.d: New file.
 	* gas/i386/got.s: Likewise.
 	* gas/i386/i386.exp: Run got.
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 8c374f2..1739ba9 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -780,6 +780,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
 	run_dump_test "x86-64-jump"
 	run_dump_test "x86-64-branch-2"
 	run_list_test "x86-64-branch-3" "-al -mintel64"
+
+	run_dump_test "x86-64-gotpcrel"
     }
 
     set ASFLAGS "$old_ASFLAGS"
diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-gotpcrel.d b/gas/testsuite/gas/i386/ilp32/x86-64-gotpcrel.d
new file mode 100644
index 0000000..e5a3b1c
--- /dev/null
+++ b/gas/testsuite/gas/i386/ilp32/x86-64-gotpcrel.d
@@ -0,0 +1,27 @@
+#source: ../x86-64-gotpcrel.s
+#objdump: -dwr
+#name: x86-64 (ILP32) gotpcrel
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	48 c7 c0 00 00 00 00 	mov    \$0x0,%rax	3: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 04 25 00 00 00 00 	mov    0x0,%rax	b: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 05 00 00 00 00 	mov    0x0\(%rip\),%rax        # 16 <_start\+0x16>	12: R_X86_64_REX_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	48 8b 81 00 00 00 00 	mov    0x0\(%rcx\),%rax	19: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 15 00 00 00 00    	callq  \*0x0\(%rip\)        # 23 <_start\+0x23>	1f: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff 90 00 00 00 00    	callq  \*0x0\(%rax\)	25: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 25 00 00 00 00    	jmpq   \*0x0\(%rip\)        # 2f <_start\+0x2f>	2b: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff a1 00 00 00 00    	jmpq   \*0x0\(%rcx\)	31: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 c7 c0 00 00 00 00 	mov    \$0x0,%rax	38: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 04 25 00 00 00 00 	mov    0x0,%rax	40: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 05 00 00 00 00 	mov    0x0\(%rip\),%rax        # 4b <_start\+0x4b>	47: R_X86_64_REX_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	48 8b 81 00 00 00 00 	mov    0x0\(%rcx\),%rax	4e: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 15 00 00 00 00    	callq  \*0x0\(%rip\)        # 58 <_start\+0x58>	54: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff 90 00 00 00 00    	callq  \*0x0\(%rax\)	5a: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 25 00 00 00 00    	jmpq   \*0x0\(%rip\)        # 64 <_start\+0x64>	60: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff a1 00 00 00 00    	jmpq   \*0x0\(%rcx\)	66: R_X86_64_GOTPCREL	foo
+#pass
diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
index 9efd341..0ca69c7 100644
--- a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
+++ b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
@@ -1,10 +1,10 @@
 #source: ../x86-64-localpic.s
-#readelf: -rs
+#readelf: -rsW
 #name: x86-64 (ILP32) local PIC
 
 Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 1 entries:
- Offset     Info    Type            Sym.Value  Sym. Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ R_X86_64_GOTPCREL +[0-9a-f]+ +foo - 4
+ +Offset +Info +Type +Sym. Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
 #...
  +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
 #pass
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.d b/gas/testsuite/gas/i386/x86-64-gotpcrel.d
new file mode 100644
index 0000000..6ca3fc7
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.d
@@ -0,0 +1,25 @@
+#objdump: -dwr
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	48 c7 c0 00 00 00 00 	mov    \$0x0,%rax	3: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 04 25 00 00 00 00 	mov    0x0,%rax	b: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 05 00 00 00 00 	mov    0x0\(%rip\),%rax        # 16 <_start\+0x16>	12: R_X86_64_REX_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	48 8b 81 00 00 00 00 	mov    0x0\(%rcx\),%rax	19: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 15 00 00 00 00    	callq  \*0x0\(%rip\)        # 23 <_start\+0x23>	1f: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff 90 00 00 00 00    	callq  \*0x0\(%rax\)	25: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 25 00 00 00 00    	jmpq   \*0x0\(%rip\)        # 2f <_start\+0x2f>	2b: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff a1 00 00 00 00    	jmpq   \*0x0\(%rcx\)	31: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 c7 c0 00 00 00 00 	mov    \$0x0,%rax	38: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 04 25 00 00 00 00 	mov    0x0,%rax	40: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	48 8b 05 00 00 00 00 	mov    0x0\(%rip\),%rax        # 4b <_start\+0x4b>	47: R_X86_64_REX_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	48 8b 81 00 00 00 00 	mov    0x0\(%rcx\),%rax	4e: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 15 00 00 00 00    	callq  \*0x0\(%rip\)        # 58 <_start\+0x58>	54: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff 90 00 00 00 00    	callq  \*0x0\(%rax\)	5a: R_X86_64_GOTPCREL	foo
+[ 	]*[a-f0-9]+:	ff 25 00 00 00 00    	jmpq   \*0x0\(%rip\)        # 64 <_start\+0x64>	60: R_X86_64_GOTPCRELX	foo-0x4
+[ 	]*[a-f0-9]+:	ff a1 00 00 00 00    	jmpq   \*0x0\(%rcx\)	66: R_X86_64_GOTPCREL	foo
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.s b/gas/testsuite/gas/i386/x86-64-gotpcrel.s
new file mode 100644
index 0000000..981b14f
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.s
@@ -0,0 +1,23 @@
+	.text
+_start:
+	movq	$foo@GOTPCREL, %rax
+	movq	foo@GOTPCREL, %rax
+	movq	foo@GOTPCREL(%rip), %rax
+	movq	foo@GOTPCREL(%rcx), %rax
+
+	call	*foo@GOTPCREL(%rip)
+	call	*foo@GOTPCREL(%rax)
+	jmp	*foo@GOTPCREL(%rip)
+	jmp	*foo@GOTPCREL(%rcx)
+
+	.intel_syntax noprefix
+
+	mov	rax, offset foo@gotpcrel
+	mov	rax, QWORD PTR [foo@GOTPCREL]
+	mov	rax, QWORD PTR [rip + foo@GOTPCREL]
+	mov	rax, QWORD PTR [rcx + foo@GOTPCREL]
+
+	call	QWORD PTR [rip + foo@GOTPCREL]
+	call	QWORD PTR [rax + foo@GOTPCREL]
+	jmp	QWORD PTR [rip + foo@GOTPCREL]
+	jmp	QWORD PTR [rcx + foo@GOTPCREL]
diff --git a/gas/testsuite/gas/i386/x86-64-localpic.d b/gas/testsuite/gas/i386/x86-64-localpic.d
index f400adb..0a07149 100644
--- a/gas/testsuite/gas/i386/x86-64-localpic.d
+++ b/gas/testsuite/gas/i386/x86-64-localpic.d
@@ -1,9 +1,9 @@
-#readelf: -rs
+#readelf: -rsW
 #name: x86-64 local PIC
 
 Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 1 entries:
-  Offset          Info           Type           Sym. Value    Sym. Name \+ Addend
-[0-9a-f]+ +[0-9a-f]+ R_X86_64_GOTPCREL +[0-9a-f]+ +foo - 4
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
 #...
  +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
 #pass
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index 8dc601c..08b6701 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,5 +1,10 @@
 2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* x86-64.h (R_X86_64_GOTPCRELX): New.
+	(R_X86_64_REX_GOTPCRELX): Likewise.
+
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
 	* i386.h (R_386_GOT32X): New relocation.
 
 2015-10-07  Cupertino Miranda  <cmiranda@synopsys.com>
diff --git a/include/elf/x86-64.h b/include/elf/x86-64.h
index f18ec66..7b98f65 100644
--- a/include/elf/x86-64.h
+++ b/include/elf/x86-64.h
@@ -72,10 +72,16 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
      RELOC_NUMBER (R_X86_64_TLSDESC, 36)      /* 2x64-bit TLS descriptor.  */
      RELOC_NUMBER (R_X86_64_IRELATIVE, 37)    /* Adjust indirectly by program base */
      RELOC_NUMBER (R_X86_64_RELATIVE64, 38)   /* 64bit adjust by program base */
-     RELOC_NUMBER (R_X86_64_PC32_BND, 39)      /* PC relative 32 bit
-						  signed with BND prefix  */
-     RELOC_NUMBER (R_X86_64_PLT32_BND, 40)     /* 32 bit PLT address with
-						  BND prefix */
+     RELOC_NUMBER (R_X86_64_PC32_BND, 39)     /* PC relative 32 bit
+						 signed with BND prefix  */
+     RELOC_NUMBER (R_X86_64_PLT32_BND, 40)    /* 32 bit PLT address with
+						 BND prefix */
+     /* Load from 32 bit signed pc relative offset to GOT entry without
+	REX prefix, relaxable.  */
+     RELOC_NUMBER (R_X86_64_GOTPCRELX, 41)
+     /* Load from 32 bit signed pc relative offset to GOT entry with
+	REX prefix, relaxable.  */
+     RELOC_NUMBER (R_X86_64_REX_GOTPCRELX, 42)
      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)
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index becfd53..b8d04f5 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,5 +1,26 @@
 2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* ld-ifunc/ifunc-5r-local-x86-64.d: Replace R_X86_64_GOTPCREL
+	with R_X86_64_REX_GOTPCRELX.
+	* ld-x86-64/plt-main1.rd: Likewise.
+	* ld-x86-64/plt-main3.rd: Likewise.
+	* ld-x86-64/plt-main4.rd: Likewise.
+	* ld-x86-64/gotpcrel1.dd: New file.
+	* ld-x86-64/gotpcrel1.out: Likewise.
+	* ld-x86-64/gotpcrel1a.S: Likewise.
+	* ld-x86-64/gotpcrel1b.c: Likewise.
+	* ld-x86-64/gotpcrel1c.c: Likewise.
+	* ld-x86-64/gotpcrel1d.S: Likewise.
+	* ld-x86-64/load1.s: Likewise.
+	* ld-x86-64/load1a.d: Likewise.
+	* ld-x86-64/load1b.d: Likewise.
+	* ld-x86-64/load1c.d: Likewise.
+	* ld-x86-64/load1d.d: Likewise.
+	* ld-x86-64/x86-64.exp: Run load1a, load1b, load1c and load1d
+	tests.  Run gotpcrel1 test.
+
+2015-10-22  H.J. Lu  <hongjiu.lu@intel.com>
+
 	* ld-i386/branch1.d: New file.
 	* ld-i386/branch1.s: Likewise.
 	* ld-i386/call1.d: Likewise.
diff --git a/ld/testsuite/ld-ifunc/ifunc-5r-local-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-5r-local-x86-64.d
index e9ad214c..18021e7 100644
--- a/ld/testsuite/ld-ifunc/ifunc-5r-local-x86-64.d
+++ b/ld/testsuite/ld-ifunc/ifunc-5r-local-x86-64.d
@@ -7,4 +7,4 @@
 Relocation section '.rela.text' at .*
 [ ]+Offset[ ]+Info[ ]+Type[ ]+.*
 [0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_PLT32[ ]+foo\(\)[ ]+foo - 4
-[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_GOTPCREL[ ]+foo\(\)[ ]+foo - 4
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_REX_GOTPCRELX[ ]+foo\(\)[ ]+foo - 4
diff --git a/ld/testsuite/ld-x86-64/gotpcrel1.dd b/ld/testsuite/ld-x86-64/gotpcrel1.dd
new file mode 100644
index 0000000..187a1a5
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/gotpcrel1.dd
@@ -0,0 +1,17 @@
+#...
+[a-f0-9]+ <main>:
+[ 	]*[a-f0-9]+:	48 83 ec 08          	sub    \$0x8,%rsp
+[ 	]*[a-f0-9]+:	[ a-f0-9]+    	addr32 callq [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	[ a-f0-9]+    	callq  \*0x[a-f0-9]+\(%rip\)        # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
+[ 	]*[a-f0-9]+:	[ a-f0-9]+    	callq  \*0x[a-f0-9]+\(%rip\)        # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
+[ 	]*[a-f0-9]+:	[ a-f0-9]+	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	ff d0                	callq  \*%rax
+[ 	]*[a-f0-9]+:	[ a-f0-9]+	mov    0x[a-f0-9]+\(%rip\),%rcx        # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
+[ 	]*[a-f0-9]+:	ff d1                	callq  \*%rcx
+[ 	]*[a-f0-9]+:	[ a-f0-9]+	mov    0x[a-f0-9]+\(%rip\),%rdx        # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
+[ 	]*[a-f0-9]+:	ff d2                	callq  \*%rdx
+[ 	]*[a-f0-9]+:	31 ff                	xor    %edi,%edi
+[ 	]*[a-f0-9]+:	48 83 c4 08          	add    \$0x8,%rsp
+[ 	]*[a-f0-9]+:	[ a-f0-9]+       	jmpq   [a-f0-9]+ <myexit>
+[ 	]*[a-f0-9]+:	90                   	nop
+#pass
diff --git a/ld/testsuite/ld-x86-64/gotpcrel1.out b/ld/testsuite/ld-x86-64/gotpcrel1.out
new file mode 100644
index 0000000..4d35632
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/gotpcrel1.out
@@ -0,0 +1,8 @@
+foo
+bar
+plt
+plt
+foo
+bar
+plt
+plt
diff --git a/ld/testsuite/ld-x86-64/gotpcrel1a.S b/ld/testsuite/ld-x86-64/gotpcrel1a.S
new file mode 100644
index 0000000..58dfbb1
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/gotpcrel1a.S
@@ -0,0 +1,18 @@
+	.text
+	.globl	main
+	.type	main, @function
+main:
+	subq	$8, %rsp
+	call   *foo@GOTPCREL(%rip)
+	call   *bar@GOTPCREL(%rip)
+	call   *plt@GOTPCREL(%rip)
+	movq   foo@GOTPCREL(%rip), %rax
+	call   *%rax
+	movq   bar@GOTPCREL(%rip), %rcx
+	call   *%rcx
+	movq   plt@GOTPCREL(%rip), %rdx
+	call   *%rdx
+	xorl	%edi, %edi
+	addq	$8, %rsp
+	jmp	*myexit@GOTPCREL(%rip)
+	.size	main, .-main
diff --git a/ld/testsuite/ld-x86-64/gotpcrel1b.c b/ld/testsuite/ld-x86-64/gotpcrel1b.c
new file mode 100644
index 0000000..cf0c78e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/gotpcrel1b.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+foo (void)
+{
+  printf ("%s\n", __FUNCTION__);
+}
diff --git a/ld/testsuite/ld-x86-64/gotpcrel1c.c b/ld/testsuite/ld-x86-64/gotpcrel1c.c
new file mode 100644
index 0000000..05f5fc2
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/gotpcrel1c.c
@@ -0,0 +1,7 @@
+#include <stdlib.h>
+
+void
+myexit (int status)
+{
+  exit (status);
+}
diff --git a/ld/testsuite/ld-x86-64/gotpcrel1d.S b/ld/testsuite/ld-x86-64/gotpcrel1d.S
new file mode 100644
index 0000000..4b01499
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/gotpcrel1d.S
@@ -0,0 +1,26 @@
+	.text
+	.globl	bar
+	.type	bar, @function
+bar:
+	leaq	__FUNCTION__.2215(%rip), %rdi
+	jmp   *puts@GOTPCREL(%rip)
+	.size	bar, .-bar
+	.globl	plt
+	.type	plt, @function
+plt:
+	leaq	__FUNCTION__.2219(%rip), %rdi
+	subq	$8, %rsp
+	call   *puts@GOTPCREL(%rip)
+	leaq	__FUNCTION__.2219(%rip), %rdi
+	addq	$8, %rsp
+	jmp	*puts@GOTPCREL(%rip)
+	.size	plt, .-plt
+	.section	.rodata
+	.type	__FUNCTION__.2219, @object
+	.size	__FUNCTION__.2219, 4
+__FUNCTION__.2219:
+	.string	"plt"
+	.type	__FUNCTION__.2215, @object
+	.size	__FUNCTION__.2215, 4
+__FUNCTION__.2215:
+	.string	"bar"
diff --git a/ld/testsuite/ld-x86-64/load1.s b/ld/testsuite/ld-x86-64/load1.s
new file mode 100644
index 0000000..f35b48f
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/load1.s
@@ -0,0 +1,51 @@
+	.data
+	.type	bar, @object
+bar:
+	.byte	1
+	.size	bar, .-bar
+	.globl	foo
+	.type	foo, @object
+foo:
+	.byte	1
+	.size	foo, .-foo
+	.text
+	.globl	_start
+	.type	_start, @function
+_start:
+	adcl	bar@GOTPCREL(%rip), %eax
+	addl	bar@GOTPCREL(%rip), %ebx
+	andl	bar@GOTPCREL(%rip), %ecx
+	cmpl	bar@GOTPCREL(%rip), %edx
+	orl	bar@GOTPCREL(%rip), %esi
+	sbbl	bar@GOTPCREL(%rip), %edi
+	subl	bar@GOTPCREL(%rip), %ebp
+	xorl	bar@GOTPCREL(%rip), %r8d
+	testl	%r15d, bar@GOTPCREL(%rip)
+	adcq	bar@GOTPCREL(%rip), %rax
+	addq	bar@GOTPCREL(%rip), %rbx
+	andq	bar@GOTPCREL(%rip), %rcx
+	cmpq	bar@GOTPCREL(%rip), %rdx
+	orq	bar@GOTPCREL(%rip), %rdi
+	sbbq	bar@GOTPCREL(%rip), %rsi
+	subq	bar@GOTPCREL(%rip), %rbp
+	xorq	bar@GOTPCREL(%rip), %r8
+	testq	%r15, bar@GOTPCREL(%rip)
+	adcl	foo@GOTPCREL(%rip), %eax
+	addl	foo@GOTPCREL(%rip), %ebx
+	andl	foo@GOTPCREL(%rip), %ecx
+	cmpl	foo@GOTPCREL(%rip), %edx
+	orl	foo@GOTPCREL(%rip), %esi
+	sbbl	foo@GOTPCREL(%rip), %edi
+	subl	foo@GOTPCREL(%rip), %ebp
+	xorl	foo@GOTPCREL(%rip), %r8d
+	testl	%r15d, foo@GOTPCREL(%rip)
+	adcq	foo@GOTPCREL(%rip), %rax
+	addq	foo@GOTPCREL(%rip), %rbx
+	andq	foo@GOTPCREL(%rip), %rcx
+	cmpq	foo@GOTPCREL(%rip), %rdx
+	orq	foo@GOTPCREL(%rip), %rdi
+	sbbq	foo@GOTPCREL(%rip), %rsi
+	subq	foo@GOTPCREL(%rip), %rbp
+	xorq	foo@GOTPCREL(%rip), %r8
+	testq	%r15, foo@GOTPCREL(%rip)
+	.size	_start, .-_start
diff --git a/ld/testsuite/ld-x86-64/load1a.d b/ld/testsuite/ld-x86-64/load1a.d
new file mode 100644
index 0000000..e03efbd
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/load1a.d
@@ -0,0 +1,54 @@
+#source: load1.s
+#as: --64
+#ld: -melf_x86_64
+#objdump: -dw --sym
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+6001b8 l     O .data	0+1 bar
+#...
+0+6001b9 g     O .data	0+1 foo
+#...
+
+Disassembly of section .text:
+
+0+4000b0 <_start>:
+[ 	]*[a-f0-9]+:	81 d0 b8 01 60 00    	adc    \$0x6001b8,%eax
+[ 	]*[a-f0-9]+:	81 c3 b8 01 60 00    	add    \$0x6001b8,%ebx
+[ 	]*[a-f0-9]+:	81 e1 b8 01 60 00    	and    \$0x6001b8,%ecx
+[ 	]*[a-f0-9]+:	81 fa b8 01 60 00    	cmp    \$0x6001b8,%edx
+[ 	]*[a-f0-9]+:	81 ce b8 01 60 00    	or     \$0x6001b8,%esi
+[ 	]*[a-f0-9]+:	81 df b8 01 60 00    	sbb    \$0x6001b8,%edi
+[ 	]*[a-f0-9]+:	81 ed b8 01 60 00    	sub    \$0x6001b8,%ebp
+[ 	]*[a-f0-9]+:	41 81 f0 b8 01 60 00 	xor    \$0x6001b8,%r8d
+[ 	]*[a-f0-9]+:	41 f7 c7 b8 01 60 00 	test   \$0x6001b8,%r15d
+[ 	]*[a-f0-9]+:	48 81 d0 b8 01 60 00 	adc    \$0x6001b8,%rax
+[ 	]*[a-f0-9]+:	48 81 c3 b8 01 60 00 	add    \$0x6001b8,%rbx
+[ 	]*[a-f0-9]+:	48 81 e1 b8 01 60 00 	and    \$0x6001b8,%rcx
+[ 	]*[a-f0-9]+:	48 81 fa b8 01 60 00 	cmp    \$0x6001b8,%rdx
+[ 	]*[a-f0-9]+:	48 81 cf b8 01 60 00 	or     \$0x6001b8,%rdi
+[ 	]*[a-f0-9]+:	48 81 de b8 01 60 00 	sbb    \$0x6001b8,%rsi
+[ 	]*[a-f0-9]+:	48 81 ed b8 01 60 00 	sub    \$0x6001b8,%rbp
+[ 	]*[a-f0-9]+:	49 81 f0 b8 01 60 00 	xor    \$0x6001b8,%r8
+[ 	]*[a-f0-9]+:	49 f7 c7 b8 01 60 00 	test   \$0x6001b8,%r15
+[ 	]*[a-f0-9]+:	81 d0 b9 01 60 00    	adc    \$0x6001b9,%eax
+[ 	]*[a-f0-9]+:	81 c3 b9 01 60 00    	add    \$0x6001b9,%ebx
+[ 	]*[a-f0-9]+:	81 e1 b9 01 60 00    	and    \$0x6001b9,%ecx
+[ 	]*[a-f0-9]+:	81 fa b9 01 60 00    	cmp    \$0x6001b9,%edx
+[ 	]*[a-f0-9]+:	81 ce b9 01 60 00    	or     \$0x6001b9,%esi
+[ 	]*[a-f0-9]+:	81 df b9 01 60 00    	sbb    \$0x6001b9,%edi
+[ 	]*[a-f0-9]+:	81 ed b9 01 60 00    	sub    \$0x6001b9,%ebp
+[ 	]*[a-f0-9]+:	41 81 f0 b9 01 60 00 	xor    \$0x6001b9,%r8d
+[ 	]*[a-f0-9]+:	41 f7 c7 b9 01 60 00 	test   \$0x6001b9,%r15d
+[ 	]*[a-f0-9]+:	48 81 d0 b9 01 60 00 	adc    \$0x6001b9,%rax
+[ 	]*[a-f0-9]+:	48 81 c3 b9 01 60 00 	add    \$0x6001b9,%rbx
+[ 	]*[a-f0-9]+:	48 81 e1 b9 01 60 00 	and    \$0x6001b9,%rcx
+[ 	]*[a-f0-9]+:	48 81 fa b9 01 60 00 	cmp    \$0x6001b9,%rdx
+[ 	]*[a-f0-9]+:	48 81 cf b9 01 60 00 	or     \$0x6001b9,%rdi
+[ 	]*[a-f0-9]+:	48 81 de b9 01 60 00 	sbb    \$0x6001b9,%rsi
+[ 	]*[a-f0-9]+:	48 81 ed b9 01 60 00 	sub    \$0x6001b9,%rbp
+[ 	]*[a-f0-9]+:	49 81 f0 b9 01 60 00 	xor    \$0x6001b9,%r8
+[ 	]*[a-f0-9]+:	49 f7 c7 b9 01 60 00 	test   \$0x6001b9,%r15
+#pass
diff --git a/ld/testsuite/ld-x86-64/load1b.d b/ld/testsuite/ld-x86-64/load1b.d
new file mode 100644
index 0000000..5adc89d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/load1b.d
@@ -0,0 +1,55 @@
+#source: load1.s
+#as: --x32
+#ld: -melf32_x86_64
+#objdump: -dw --sym
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+60017c l     O .data	0+1 bar
+#...
+0+60017d g     O .data	0+1 foo
+#...
+
+
+Disassembly of section .text:
+
+0+400074 <_start>:
+[ 	]*[a-f0-9]+:	81 d0 7c 01 60 00    	adc    \$0x60017c,%eax
+[ 	]*[a-f0-9]+:	81 c3 7c 01 60 00    	add    \$0x60017c,%ebx
+[ 	]*[a-f0-9]+:	81 e1 7c 01 60 00    	and    \$0x60017c,%ecx
+[ 	]*[a-f0-9]+:	81 fa 7c 01 60 00    	cmp    \$0x60017c,%edx
+[ 	]*[a-f0-9]+:	81 ce 7c 01 60 00    	or     \$0x60017c,%esi
+[ 	]*[a-f0-9]+:	81 df 7c 01 60 00    	sbb    \$0x60017c,%edi
+[ 	]*[a-f0-9]+:	81 ed 7c 01 60 00    	sub    \$0x60017c,%ebp
+[ 	]*[a-f0-9]+:	41 81 f0 7c 01 60 00 	xor    \$0x60017c,%r8d
+[ 	]*[a-f0-9]+:	41 f7 c7 7c 01 60 00 	test   \$0x60017c,%r15d
+[ 	]*[a-f0-9]+:	48 81 d0 7c 01 60 00 	adc    \$0x60017c,%rax
+[ 	]*[a-f0-9]+:	48 81 c3 7c 01 60 00 	add    \$0x60017c,%rbx
+[ 	]*[a-f0-9]+:	48 81 e1 7c 01 60 00 	and    \$0x60017c,%rcx
+[ 	]*[a-f0-9]+:	48 81 fa 7c 01 60 00 	cmp    \$0x60017c,%rdx
+[ 	]*[a-f0-9]+:	48 81 cf 7c 01 60 00 	or     \$0x60017c,%rdi
+[ 	]*[a-f0-9]+:	48 81 de 7c 01 60 00 	sbb    \$0x60017c,%rsi
+[ 	]*[a-f0-9]+:	48 81 ed 7c 01 60 00 	sub    \$0x60017c,%rbp
+[ 	]*[a-f0-9]+:	49 81 f0 7c 01 60 00 	xor    \$0x60017c,%r8
+[ 	]*[a-f0-9]+:	49 f7 c7 7c 01 60 00 	test   \$0x60017c,%r15
+[ 	]*[a-f0-9]+:	81 d0 7d 01 60 00    	adc    \$0x60017d,%eax
+[ 	]*[a-f0-9]+:	81 c3 7d 01 60 00    	add    \$0x60017d,%ebx
+[ 	]*[a-f0-9]+:	81 e1 7d 01 60 00    	and    \$0x60017d,%ecx
+[ 	]*[a-f0-9]+:	81 fa 7d 01 60 00    	cmp    \$0x60017d,%edx
+[ 	]*[a-f0-9]+:	81 ce 7d 01 60 00    	or     \$0x60017d,%esi
+[ 	]*[a-f0-9]+:	81 df 7d 01 60 00    	sbb    \$0x60017d,%edi
+[ 	]*[a-f0-9]+:	81 ed 7d 01 60 00    	sub    \$0x60017d,%ebp
+[ 	]*[a-f0-9]+:	41 81 f0 7d 01 60 00 	xor    \$0x60017d,%r8d
+[ 	]*[a-f0-9]+:	41 f7 c7 7d 01 60 00 	test   \$0x60017d,%r15d
+[ 	]*[a-f0-9]+:	48 81 d0 7d 01 60 00 	adc    \$0x60017d,%rax
+[ 	]*[a-f0-9]+:	48 81 c3 7d 01 60 00 	add    \$0x60017d,%rbx
+[ 	]*[a-f0-9]+:	48 81 e1 7d 01 60 00 	and    \$0x60017d,%rcx
+[ 	]*[a-f0-9]+:	48 81 fa 7d 01 60 00 	cmp    \$0x60017d,%rdx
+[ 	]*[a-f0-9]+:	48 81 cf 7d 01 60 00 	or     \$0x60017d,%rdi
+[ 	]*[a-f0-9]+:	48 81 de 7d 01 60 00 	sbb    \$0x60017d,%rsi
+[ 	]*[a-f0-9]+:	48 81 ed 7d 01 60 00 	sub    \$0x60017d,%rbp
+[ 	]*[a-f0-9]+:	49 81 f0 7d 01 60 00 	xor    \$0x60017d,%r8
+[ 	]*[a-f0-9]+:	49 f7 c7 7d 01 60 00 	test   \$0x60017d,%r15
+#pass
diff --git a/ld/testsuite/ld-x86-64/load1c.d b/ld/testsuite/ld-x86-64/load1c.d
new file mode 100644
index 0000000..2e0eb07
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/load1c.d
@@ -0,0 +1,47 @@
+#source: load1.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[ 	]*[a-f0-9]+:	13 05 ca 01 20 00    	adc    0x2001ca\(%rip\),%eax        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	03 1d c4 01 20 00    	add    0x2001c4\(%rip\),%ebx        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	23 0d be 01 20 00    	and    0x2001be\(%rip\),%ecx        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	3b 15 b8 01 20 00    	cmp    0x2001b8\(%rip\),%edx        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	0b 35 b2 01 20 00    	or     0x2001b2\(%rip\),%esi        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	1b 3d ac 01 20 00    	sbb    0x2001ac\(%rip\),%edi        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	2b 2d a6 01 20 00    	sub    0x2001a6\(%rip\),%ebp        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	44 33 05 9f 01 20 00 	xor    0x20019f\(%rip\),%r8d        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	44 85 3d 98 01 20 00 	test   %r15d,0x200198\(%rip\)        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	48 13 05 91 01 20 00 	adc    0x200191\(%rip\),%rax        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	48 03 1d 8a 01 20 00 	add    0x20018a\(%rip\),%rbx        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	48 23 0d 83 01 20 00 	and    0x200183\(%rip\),%rcx        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	48 3b 15 7c 01 20 00 	cmp    0x20017c\(%rip\),%rdx        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	48 0b 3d 75 01 20 00 	or     0x200175\(%rip\),%rdi        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	48 1b 35 6e 01 20 00 	sbb    0x20016e\(%rip\),%rsi        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	48 2b 2d 67 01 20 00 	sub    0x200167\(%rip\),%rbp        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	4c 33 05 60 01 20 00 	xor    0x200160\(%rip\),%r8        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	4c 85 3d 59 01 20 00 	test   %r15,0x200159\(%rip\)        # 2003e0 <_DYNAMIC\+0xe0>
+[ 	]*[a-f0-9]+:	13 05 5b 01 20 00    	adc    0x20015b\(%rip\),%eax        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	03 1d 55 01 20 00    	add    0x200155\(%rip\),%ebx        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	23 0d 4f 01 20 00    	and    0x20014f\(%rip\),%ecx        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	3b 15 49 01 20 00    	cmp    0x200149\(%rip\),%edx        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	0b 35 43 01 20 00    	or     0x200143\(%rip\),%esi        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	1b 3d 3d 01 20 00    	sbb    0x20013d\(%rip\),%edi        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	2b 2d 37 01 20 00    	sub    0x200137\(%rip\),%ebp        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	44 33 05 30 01 20 00 	xor    0x200130\(%rip\),%r8d        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	44 85 3d 29 01 20 00 	test   %r15d,0x200129\(%rip\)        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	48 13 05 22 01 20 00 	adc    0x200122\(%rip\),%rax        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	48 03 1d 1b 01 20 00 	add    0x20011b\(%rip\),%rbx        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	48 23 0d 14 01 20 00 	and    0x200114\(%rip\),%rcx        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	48 3b 15 0d 01 20 00 	cmp    0x20010d\(%rip\),%rdx        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	48 0b 3d 06 01 20 00 	or     0x200106\(%rip\),%rdi        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	48 1b 35 ff 00 20 00 	sbb    0x2000ff\(%rip\),%rsi        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	48 2b 2d f8 00 20 00 	sub    0x2000f8\(%rip\),%rbp        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	4c 33 05 f1 00 20 00 	xor    0x2000f1\(%rip\),%r8        # 2003e8 <_DYNAMIC\+0xe8>
+[ 	]*[a-f0-9]+:	4c 85 3d ea 00 20 00 	test   %r15,0x2000ea\(%rip\)        # 2003e8 <_DYNAMIC\+0xe8>
+#pass
diff --git a/ld/testsuite/ld-x86-64/load1d.d b/ld/testsuite/ld-x86-64/load1d.d
new file mode 100644
index 0000000..68292ac
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/load1d.d
@@ -0,0 +1,47 @@
+#source: load1.s
+#as: --x32
+#ld: -shared -melf32_x86_64
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+[a-f0-9]+ <_start>:
+[ 	]*[a-f0-9]+:	13 05 5e 01 20 00    	adc    0x20015e\(%rip\),%eax        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	03 1d 58 01 20 00    	add    0x200158\(%rip\),%ebx        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	23 0d 52 01 20 00    	and    0x200152\(%rip\),%ecx        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	3b 15 4c 01 20 00    	cmp    0x20014c\(%rip\),%edx        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	0b 35 46 01 20 00    	or     0x200146\(%rip\),%esi        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	1b 3d 40 01 20 00    	sbb    0x200140\(%rip\),%edi        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	2b 2d 3a 01 20 00    	sub    0x20013a\(%rip\),%ebp        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	44 33 05 33 01 20 00 	xor    0x200133\(%rip\),%r8d        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	44 85 3d 2c 01 20 00 	test   %r15d,0x20012c\(%rip\)        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	48 13 05 25 01 20 00 	adc    0x200125\(%rip\),%rax        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	48 03 1d 1e 01 20 00 	add    0x20011e\(%rip\),%rbx        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	48 23 0d 17 01 20 00 	and    0x200117\(%rip\),%rcx        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	48 3b 15 10 01 20 00 	cmp    0x200110\(%rip\),%rdx        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	48 0b 3d 09 01 20 00 	or     0x200109\(%rip\),%rdi        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	48 1b 35 02 01 20 00 	sbb    0x200102\(%rip\),%rsi        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	48 2b 2d fb 00 20 00 	sub    0x2000fb\(%rip\),%rbp        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	4c 33 05 f4 00 20 00 	xor    0x2000f4\(%rip\),%r8        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	4c 85 3d ed 00 20 00 	test   %r15,0x2000ed\(%rip\)        # 2002d0 <_DYNAMIC\+0x70>
+[ 	]*[a-f0-9]+:	13 05 ef 00 20 00    	adc    0x2000ef\(%rip\),%eax        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	03 1d e9 00 20 00    	add    0x2000e9\(%rip\),%ebx        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	23 0d e3 00 20 00    	and    0x2000e3\(%rip\),%ecx        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	3b 15 dd 00 20 00    	cmp    0x2000dd\(%rip\),%edx        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	0b 35 d7 00 20 00    	or     0x2000d7\(%rip\),%esi        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	1b 3d d1 00 20 00    	sbb    0x2000d1\(%rip\),%edi        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	2b 2d cb 00 20 00    	sub    0x2000cb\(%rip\),%ebp        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	44 33 05 c4 00 20 00 	xor    0x2000c4\(%rip\),%r8d        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	44 85 3d bd 00 20 00 	test   %r15d,0x2000bd\(%rip\)        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	48 13 05 b6 00 20 00 	adc    0x2000b6\(%rip\),%rax        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	48 03 1d af 00 20 00 	add    0x2000af\(%rip\),%rbx        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	48 23 0d a8 00 20 00 	and    0x2000a8\(%rip\),%rcx        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	48 3b 15 a1 00 20 00 	cmp    0x2000a1\(%rip\),%rdx        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	48 0b 3d 9a 00 20 00 	or     0x20009a\(%rip\),%rdi        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	48 1b 35 93 00 20 00 	sbb    0x200093\(%rip\),%rsi        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	48 2b 2d 8c 00 20 00 	sub    0x20008c\(%rip\),%rbp        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	4c 33 05 85 00 20 00 	xor    0x200085\(%rip\),%r8        # 2002d8 <_DYNAMIC\+0x78>
+[ 	]*[a-f0-9]+:	4c 85 3d 7e 00 20 00 	test   %r15,0x20007e\(%rip\)        # 2002d8 <_DYNAMIC\+0x78>
+#pass
diff --git a/ld/testsuite/ld-x86-64/plt-main1.rd b/ld/testsuite/ld-x86-64/plt-main1.rd
index 421d911..36fa8ef 100644
--- a/ld/testsuite/ld-x86-64/plt-main1.rd
+++ b/ld/testsuite/ld-x86-64/plt-main1.rd
@@ -1,3 +1,3 @@
 #...
-[0-9a-f ]+R_X86_64_GOTPCREL +0+ +bar - 4
+[0-9a-f ]+R_X86_64_(REX_|)GOTPCRELX +0+ +bar - 4
 #pass
diff --git a/ld/testsuite/ld-x86-64/plt-main3.rd b/ld/testsuite/ld-x86-64/plt-main3.rd
index f3d294e..0a0d402 100644
--- a/ld/testsuite/ld-x86-64/plt-main3.rd
+++ b/ld/testsuite/ld-x86-64/plt-main3.rd
@@ -1,5 +1,5 @@
 #...
-[0-9a-f ]+R_X86_64_GOTPCREL +0+ +bar - 4
+[0-9a-f ]+R_X86_64_(REX_GOTPCRELX|GOTPCREL) +0+ +bar - 4
 #...
 [0-9a-f ]+R_X86_64_PLT32 +0+ +bar - 4
 #pass
diff --git a/ld/testsuite/ld-x86-64/plt-main4.rd b/ld/testsuite/ld-x86-64/plt-main4.rd
index 7f33f3a..d391fc0 100644
--- a/ld/testsuite/ld-x86-64/plt-main4.rd
+++ b/ld/testsuite/ld-x86-64/plt-main4.rd
@@ -1,5 +1,5 @@
 #...
-[0-9a-f ]+R_X86_64_GOTPCREL +0+ +foo - 4
+[0-9a-f ]+R_X86_64_(REX_|)GOTPCRELX +0+ +foo - 4
 #...
 [0-9a-f ]+R_X86_64_PLT32 +0+ +foo - 4
 #pass
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 69728c2..7b8990b 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -321,6 +321,10 @@ run_dump_test "mov1a"
 run_dump_test "mov1b"
 run_dump_test "mov1c"
 run_dump_test "mov1d"
+run_dump_test "load1a"
+run_dump_test "load1b"
+run_dump_test "load1c"
+run_dump_test "load1d"
 run_dump_test "pr17935-1"
 run_dump_test "pr17935-2"
 run_dump_test "pr18160"
@@ -511,6 +515,22 @@ if { [isnative] && [which $CC] != 0 } {
 	    "" \
 	    "pr19031.so" \
 	] \
+	[list \
+	    "Build gotpcrel1d.so" \
+	    "-shared" \
+	    "" \
+	    { gotpcrel1d.S } \
+	    "" \
+	    "gotpcrel1d.so" \
+	] \
+	[list \
+	    "Build gotpcrel1" \
+	    "tmpdir/gotpcrel1d.so" \
+	    "" \
+	    { gotpcrel1a.S gotpcrel1b.c gotpcrel1c.c } \
+	    {{objdump {-dw} gotpcrel1.dd}} \
+	    "gotpcrel1" \
+	] \
     ]
 
     run_ld_link_exec_tests [] [list \
@@ -573,6 +593,14 @@ if { [isnative] && [which $CC] != 0 } {
 	    "pr19031" \
 	    "pr19031.out" \
 	] \
+	[list \
+	    "Run gotpcrel1" \
+	    "tmpdir/gotpcrel1d.so" \
+	    "" \
+	    { gotpcrel1a.S gotpcrel1b.c gotpcrel1c.c } \
+	    "gotpcrel1" \
+	    "gotpcrel1.out" \
+	] \
     ]
 
     if { [istarget "x86_64-*-linux*"] \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]