From da97efbe94bde94411f8d48f6f45c25c543c2f5a Mon Sep 17 00:00:00 2001
From: Igor Zamyatin <igor.zamyatin@intel.com>
Date: Fri, 14 Nov 2014 18:03:26 +0300
Subject: [PATCH] Add bndplt option

---
 bfd/ChangeLog                        |  6 ++++++
 bfd/elf64-x86-64.c                   | 13 +++++++------
 include/ChangeLog                    |  4 ++++
 include/bfdlink.h                    |  3 +++
 ld/ChangeLog                         | 17 +++++++++++++++++
 ld/emulparams/elf_x86_64.sh          |  5 ++++-
 ld/emultempl/elf32.em                | 15 +++++++++++++++
 ld/ld.texinfo                        |  3 +++
 ld/testsuite/ld-x86-64/bnd-ifunc-1.d |  2 +-
 ld/testsuite/ld-x86-64/bnd-ifunc-2.d |  2 +-
 ld/testsuite/ld-x86-64/bnd-plt-1.d   | 18 +++++++++---------
 ld/testsuite/ld-x86-64/mpx.exp       | 15 +++++++++++++++
 ld/testsuite/ld-x86-64/mpx3.dd       | 35 +++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-x86-64/mpx3a.s       | 17 +++++++++++++++++
 ld/testsuite/ld-x86-64/mpx3b.s       | 12 ++++++++++++
 ld/testsuite/ld-x86-64/mpx4.dd       | 24 ++++++++++++++++++++++++
 ld/testsuite/ld-x86-64/mpx4a.s       |  7 +++++++
 ld/testsuite/ld-x86-64/mpx4b.s       |  6 ++++++
 18 files changed, 186 insertions(+), 18 deletions(-)
 create mode 100644 ld/testsuite/ld-x86-64/mpx3.dd
 create mode 100644 ld/testsuite/ld-x86-64/mpx3a.s
 create mode 100644 ld/testsuite/ld-x86-64/mpx3b.s
 create mode 100644 ld/testsuite/ld-x86-64/mpx4.dd
 create mode 100644 ld/testsuite/ld-x86-64/mpx4a.s
 create mode 100644 ld/testsuite/ld-x86-64/mpx4b.s

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e29390c..0d63fdd 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2014-11-14  Igor Zamyatin  <igor.zamyatin@intel.com>
+
+	* elf64-x86-64.c (elf_x86_64_check_relocs): MPX PLT is now supported
+	for R_X86_64_PC32, R_X86_64_PLT32, R_X86_64_32 and R_X86_64_64 when
+	bndplt option is specified.
+
 2014-11-13  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* coffcode.h (coff_slurp_line_table): Add cast to unsigned int.
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index f2b13e7..20f45a9 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1629,11 +1629,16 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	    case R_X86_64_PC32_BND:
 	    case R_X86_64_PLT32_BND:
+	    case R_X86_64_PC32:
+	    case R_X86_64_PLT32:
+	    case R_X86_64_32:
+	    case R_X86_64_64:
 	      /* MPX PLT is supported only if elf_x86_64_arch_bed
 		 is used in 64-bit mode.  */
 	      if (ABI_64_P (abfd)
-		  && (get_elf_x86_64_backend_data (abfd)
-		      == &elf_x86_64_arch_bed))
+		      && info->bndplt
+		      && (get_elf_x86_64_backend_data (abfd)
+			  == &elf_x86_64_arch_bed))
 		{
 		  elf_x86_64_hash_entry (h)->has_bnd_reloc = TRUE;
 
@@ -1675,11 +1680,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 		}
 
 	    case R_X86_64_32S:
-	    case R_X86_64_32:
-	    case R_X86_64_64:
-	    case R_X86_64_PC32:
 	    case R_X86_64_PC64:
-	    case R_X86_64_PLT32:
 	    case R_X86_64_GOTPCREL:
 	    case R_X86_64_GOTPCREL64:
 	      if (htab->elf.dynobj == NULL)
diff --git a/include/ChangeLog b/include/ChangeLog
index 0204432..5a0b1f4 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2014-11-14  Igor Zamyatin  <igor.zamyatin@intel.com>
+
+	* bfdlink.h (struct bfd_link_info): New field bndplt.
+
 2014-10-30  Andrew Pinski  <apinski@cavium.com>
 
 	* elf/mips.h (AFL_EXT_OCTEON3): Define.
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 125683d..f3181ba 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -417,6 +417,9 @@ struct bfd_link_info
   /* TRUE if the linker script contained an explicit PHDRS command.  */
   unsigned int user_phdrs: 1;
 
+  /* TRUE if BND prefix in PLT entries is always generated.  */
+  unsigned int bndplt: 1;
+
   /* Char that may appear as the first char of a symbol, but should be
      skipped (like symbol_leading_char) when looking up symbols in
      wrap_hash.  Used by PowerPC Linux for 'dot' symbols.  */
diff --git a/ld/ChangeLog b/ld/ChangeLog
index ec4be3f..715216c 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,20 @@
+2014-11-14  Igor Zamyatin  <igor.zamyatin@intel.com>
+
+	* emulparams/elf_x86_64.sh: Set BNDPLT for x86_64.
+	* emultempl/elf32.em: Handle bndplt option and add description for it.
+	* ld.texinfo: Add description for bndplt.
+	* testsuite/ld-x86-64/bnd-ifunc-1.d: Add bndplt option.
+	* testsuite/ld-x86-64/bnd-ifunc-2.d: Ditto.
+	* testsuite/ld-x86-64/bnd-plt-1.d: Ditto. Update dissassembly
+	sections.
+	* testsuite/ld-x86-64/mpx.exp: Handle mpx3 and mpx4 tests.
+	* testsuite/ld-x86-64/mpx3.dd: New file.
+	* testsuite/ld-x86-64/mpx3a.s: New file.
+	* testsuite/ld-x86-64/mpx3b.s: New file.
+	* testsuite/ld-x86-64/mpx4.dd: New file.
+	* testsuite/ld-x86-64/mpx4a.s: New file.
+	* testsuite/ld-x86-64/mpx4b.s: New file.
+
 2014-10-08  Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
 
 	* avrtiny.sc: Apply avr.sc fixes.
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index d8cb6bf..1e83a74 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -31,7 +31,10 @@ fi
 case "$target" in
   x86_64*-linux*|i[3-7]86-*-linux-*)
     case "$EMULATION_NAME" in
-      *64*) LIBPATH_SUFFIX=64 ;;
+      *64*)
+        LIBPATH_SUFFIX=64
+        BNDPLT=yes
+        ;;
     esac
     ;;
   *-*-solaris2*)
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 67c437d..137446f 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -2277,6 +2277,14 @@ fragment <<EOF
 	  link_info.execstack = FALSE;
 	}
 EOF
+
+if test x"$BNDPLT" = xyes; then
+fragment <<EOF
+      else if (strcmp (optarg, "bndplt") == 0)
+	link_info.bndplt = TRUE;
+EOF
+fi
+
 if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
 fragment <<EOF
       else if (strcmp (optarg, "global") == 0)
@@ -2456,6 +2464,13 @@ fragment <<EOF
 EOF
 fi
 
+if test x"$BNDPLT" = xyes; then
+fragment <<EOF
+  fprintf (file, _("\
+  -z bndplt                   Always generate BND prefix in PLT entries\n"));
+EOF
+fi
+
 if test -n "$PARSE_AND_LIST_OPTIONS" ; then
 fragment <<EOF
  $PARSE_AND_LIST_OPTIONS
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 3001bf1..bb386e4 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1133,6 +1133,9 @@ Specify a stack size for in an ELF @code{PT_GNU_STACK} segment.
 Specifying zero will override any default non-zero sized
 @code{PT_GNU_STACK} segment creation.
 
+@item bndplt
+Always generate BND prefix in PLT entries. Supported for Linux/x86_64.
+
 @end table
 
 Other keywords are ignored for Solaris compatibility.
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-1.d b/ld/testsuite/ld-x86-64/bnd-ifunc-1.d
index cdcb4f6..11313ab 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-1.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-1.d
@@ -1,5 +1,5 @@
 #as: --64 -madd-bnd-prefix
-#ld: -shared -melf_x86_64
+#ld: -shared -melf_x86_64 -z bndplt
 #objdump: -dw
 
 #...
diff --git a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
index 43e3356..6be8290 100644
--- a/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
+++ b/ld/testsuite/ld-x86-64/bnd-ifunc-2.d
@@ -1,5 +1,5 @@
 #as: --64 -madd-bnd-prefix
-#ld: -shared -melf_x86_64
+#ld: -shared -melf_x86_64 -z bndplt
 #objdump: -dw
 
 #...
diff --git a/ld/testsuite/ld-x86-64/bnd-plt-1.d b/ld/testsuite/ld-x86-64/bnd-plt-1.d
index 3cfe9e6..d76a7a7 100644
--- a/ld/testsuite/ld-x86-64/bnd-plt-1.d
+++ b/ld/testsuite/ld-x86-64/bnd-plt-1.d
@@ -1,6 +1,6 @@
 #source: bnd-branch-1.s
 #as: --64
-#ld: -shared -melf_x86_64
+#ld: -shared -melf_x86_64 -z bndplt
 #objdump: -dw
 
 .*: +file format .*
@@ -13,8 +13,8 @@ Disassembly of section .plt:
 [      ]*[a-f0-9]+:	f2 ff 25 83 01 20 00 	bnd jmpq \*0x200183\(%rip\)        # 200440 <_GLOBAL_OFFSET_TABLE_\+0x10>
 [      ]*[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
 [      ]*[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
-[      ]*[a-f0-9]+:	e9 e6 ff ff ff       	jmpq   2b0 <foo2@plt-0x50>
-[      ]*[a-f0-9]+:	66 0f 1f 44 00 00    	nopw   0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 2b0 <foo2@plt-0x50>
+[      ]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 [      ]*[a-f0-9]+:	68 01 00 00 00       	pushq  \$0x1
 [      ]*[a-f0-9]+:	f2 e9 d5 ff ff ff    	bnd jmpq 2b0 <foo2@plt-0x50>
 [      ]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
@@ -22,14 +22,14 @@ Disassembly of section .plt:
 [      ]*[a-f0-9]+:	f2 e9 c5 ff ff ff    	bnd jmpq 2b0 <foo2@plt-0x50>
 [      ]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 [      ]*[a-f0-9]+:	68 03 00 00 00       	pushq  \$0x3
-[      ]*[a-f0-9]+:	e9 b6 ff ff ff       	jmpq   2b0 <foo2@plt-0x50>
-[      ]*[a-f0-9]+:	66 0f 1f 44 00 00    	nopw   0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:	f2 e9 b5 ff ff ff    	bnd jmpq 2b0 <foo2@plt-0x50>
+[      ]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
 
 Disassembly of section .plt.bnd:
 
 0+300 <foo2@plt>:
-[ 	]*[a-f0-9]+:	ff 25 42 01 20 00    	jmpq   \*0x200142\(%rip\)        # 200448 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ 	]*[a-f0-9]+:	66 90                	xchg   %ax,%ax
+[ 	]*[a-f0-9]+:	f2 ff 25 41 01 20 00 	bnd jmpq \*0x200141\(%rip\)        # 200448 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[ 	]*[a-f0-9]+:	90                   	nop
 
 0+308 <foo3@plt>:
 [ 	]*[a-f0-9]+:	f2 ff 25 41 01 20 00 	bnd jmpq \*0x200141\(%rip\)        # 200450 <_GLOBAL_OFFSET_TABLE_\+0x20>
@@ -40,8 +40,8 @@ Disassembly of section .plt.bnd:
 [ 	]*[a-f0-9]+:	90                   	nop
 
 0+318 <foo4@plt>:
-[ 	]*[a-f0-9]+:	ff 25 42 01 20 00    	jmpq   \*0x200142\(%rip\)        # 200460 <_GLOBAL_OFFSET_TABLE_\+0x30>
-[ 	]*[a-f0-9]+:	66 90                	xchg   %ax,%ax
+[ 	]*[a-f0-9]+:	f2 ff 25 41 01 20 00 	bnd jmpq \*0x200141\(%rip\)        # 200460 <_GLOBAL_OFFSET_TABLE_\+0x30>
+[ 	]*[a-f0-9]+:	90                   	nop
 
 Disassembly of section .text:
 
diff --git a/ld/testsuite/ld-x86-64/mpx.exp b/ld/testsuite/ld-x86-64/mpx.exp
index f2a50d4..a4e3254 100644
--- a/ld/testsuite/ld-x86-64/mpx.exp
+++ b/ld/testsuite/ld-x86-64/mpx.exp
@@ -59,6 +59,21 @@ set build_tests {
 
 run_cc_link_tests $build_tests
 
+run_ld_link_tests {
+    {"Build libcall.so"
+     "-shared -z bndplt" "" ""
+     {mpx3b.s} {} "libcall.so"}
+    {"Build mpx3"
+     "tmpdir/libcall.so -z bndplt" "" ""
+     {mpx3a.s} {{objdump -dw mpx3.dd}} "mpx3"}
+    {"Build libcall1.so"
+     "-shared -z bndplt" "" ""
+     {mpx4b.s} {} "libcall1.so"}
+    {"Build mpx4"
+     "tmpdir/libcall1.so -z bndplt" "" ""
+     {mpx4a.s} {{objdump -dw mpx4.dd}} "mpx4"}
+}
+
 set run_tests {
     {"Run mpx1"
      "tmpdir/mpx1a.o tmpdir/mpx1b.o tmpdir/mpx1c.o" ""
diff --git a/ld/testsuite/ld-x86-64/mpx3.dd b/ld/testsuite/ld-x86-64/mpx3.dd
new file mode 100644
index 0000000..2a8356d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/mpx3.dd
@@ -0,0 +1,35 @@
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+400290 <.plt>:
+[  	]*[a-f0-9]+:	ff 35 6a 01 20 00    	pushq  0x20016a\(%rip\)        # 600400 <_GLOBAL_OFFSET_TABLE_\+0x8>
+[  	]*[a-f0-9]+:	f2 ff 25 6b 01 20 00 	bnd jmpq \*0x20016b\(%rip\)        # 600408 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[  	]*[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
+[  	]*[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
+[  	]*[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 400290 <call1@plt-0x30>
+[  	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+[  	]*[a-f0-9]+:	68 01 00 00 00       	pushq  \$0x1
+[  	]*[a-f0-9]+:	f2 e9 d5 ff ff ff    	bnd jmpq 400290 <call1@plt-0x30>
+[  	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+
+Disassembly of section .plt.bnd:
+
+0+4002c0 <call1@plt>:
+[  	]*[a-f0-9]+:	f2 ff 25 49 01 20 00 	bnd jmpq \*0x200149\(%rip\)        # 600410 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[  	]*[a-f0-9]+:	90                   	nop
+
+0+4002c8 <call2@plt>:
+[  	]*[a-f0-9]+:	f2 ff 25 49 01 20 00 	bnd jmpq \*0x200149\(%rip\)        # 600418 <_GLOBAL_OFFSET_TABLE_\+0x20>
+[  	]*[a-f0-9]+:	90                   	nop
+
+Disassembly of section .text:
+
+0+4002d0 <_start>:
+[  	]*[a-f0-9]+:	bf c0 02 40 00       	mov    \$0x4002c0,%edi
+[  	]*[a-f0-9]+:	f2 ff d7             	bnd callq \*%rdi
+[  	]*[a-f0-9]+:	48 8b 3d 41 01 20 00 	mov    0x200141\(%rip\),%rdi        # 600420 <func>
+[  	]*[a-f0-9]+:	f2 ff d7             	bnd callq \*%rdi
+[  	]*[a-f0-9]+:	c3                   	retq   
+#pass
diff --git a/ld/testsuite/ld-x86-64/mpx3a.s b/ld/testsuite/ld-x86-64/mpx3a.s
new file mode 100644
index 0000000..dbb1361
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/mpx3a.s
@@ -0,0 +1,17 @@
+	.text
+	.globl	_start
+	.type	_start, @function
+_start:
+	movl	$call1, %edi
+	bnd call *%rdi
+	movq	func(%rip), %rdi
+	bnd call *%rdi
+	ret
+	.size	_start, .-_start
+	.globl	func
+	.data
+	.type	func, @object
+	.size	func, 8
+func:
+	.quad	call2
+
diff --git a/ld/testsuite/ld-x86-64/mpx3b.s b/ld/testsuite/ld-x86-64/mpx3b.s
new file mode 100644
index 0000000..171f1dd
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/mpx3b.s
@@ -0,0 +1,12 @@
+	.text
+	.globl	call1
+	.type	call1, @function
+call1:
+	ret
+	.size	call1, .-call1
+	.globl	call2
+	.type	call2, @function
+call2:
+	ret
+	.size	call2, .-call2
+
diff --git a/ld/testsuite/ld-x86-64/mpx4.dd b/ld/testsuite/ld-x86-64/mpx4.dd
new file mode 100644
index 0000000..0cf0f75
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/mpx4.dd
@@ -0,0 +1,24 @@
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+400260 <.plt>:
+[  	]*[a-f0-9]+:	ff 35 42 01 20 00    	pushq  0x200142\(%rip\)        # 6003a8 <_GLOBAL_OFFSET_TABLE_\+0x8>
+[  	]*[a-f0-9]+:	f2 ff 25 43 01 20 00 	bnd jmpq \*0x200143\(%rip\)        # 6003b0 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[  	]*[a-f0-9]+:	0f 1f 00             	nopl   \(%rax\)
+[  	]*[a-f0-9]+:	68 00 00 00 00       	pushq  \$0x0
+[  	]*[a-f0-9]+:	f2 e9 e5 ff ff ff    	bnd jmpq 400260 <call1@plt-0x20>
+[  	]*[a-f0-9]+:	0f 1f 44 00 00       	nopl   0x0\(%rax,%rax,1\)
+
+Disassembly of section .plt.bnd:
+
+0+400280 <call1@plt>:
+[  	]*[a-f0-9]+:	f2 ff 25 31 01 20 00 	bnd jmpq \*0x200131\(%rip\)        # 6003b8 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[  	]*[a-f0-9]+:	90                   	nop
+
+Disassembly of section .text:
+
+0+400288 <_start>:
+[  	]*[a-f0-9]+:	bf 80 02 40 00       	mov    \$0x400280,%edi
+[  	]*[a-f0-9]+:	f2 ff d7             	bnd callq \*%rdi
diff --git a/ld/testsuite/ld-x86-64/mpx4a.s b/ld/testsuite/ld-x86-64/mpx4a.s
new file mode 100644
index 0000000..56f0fab
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/mpx4a.s
@@ -0,0 +1,7 @@
+.text
+    .globl     _start
+    .type      _start, @function
+_start:
+    movl      $call1, %edi
+    bnd call *%rdi
+
diff --git a/ld/testsuite/ld-x86-64/mpx4b.s b/ld/testsuite/ld-x86-64/mpx4b.s
new file mode 100644
index 0000000..a456de0
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/mpx4b.s
@@ -0,0 +1,6 @@
+.text
+    .globl     call1
+    .type      call1, @function
+call1:
+     ret
+
-- 
1.9.0

