This is the mail archive of the binutils@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]

[PATCH] x86-64: Check relocations with -z nocopyreloc


On x86-64, when -z nocopyreloc is used to build executable, relocations
may overflow at run-time or may not be resolved without PIC.  This patch
checks these conditions and issues an error with suggestion for -fPIC.

bfd/

	PR ld/22001
	* elf64-x86-64.c (elf_x86_64_relocate_section): Check for
	R_X86_64_PC32 relocation run-time overflow and unresolvable
	R_X86_64_32S relocation with -z nocopyreloc.

ld/

	PR ld/22001
	* testsuite/ld-i386/i386.exp: Run -z nocopyreloc tests.
	* testsuite/ld-x86-64/x86-64.exp: Likewise.
	* ld/testsuite/ld-i386/pr22001-1a.c: New file.
	* ld/testsuite/ld-i386/pr22001-1b.c: Likewise.
	* ld/testsuite/ld-i386/pr22001-1c.S: Likewise.
	* ld/testsuite/ld-x86-64/pr22001-1a.c: Likewise.
	* ld/testsuite/ld-x86-64/pr22001-1a.err: Likewise.
	* ld/testsuite/ld-x86-64/pr22001-1b.c: Likewise.
	* ld/testsuite/ld-x86-64/pr22001-1b.err: Likewise.
	* ld/testsuite/ld-x86-64/pr22001-1c.c: Likewise.
---
 bfd/elf64-x86-64.c                    | 39 ++++++++++++++++-------
 ld/testsuite/ld-i386/i386.exp         | 55 ++++++++++++++++++++++++++++++++
 ld/testsuite/ld-i386/pr22001-1a.c     | 13 ++++++++
 ld/testsuite/ld-i386/pr22001-1b.c     | 14 ++++++++
 ld/testsuite/ld-i386/pr22001-1c.S     | 51 +++++++++++++++++++++++++++++
 ld/testsuite/ld-x86-64/pr22001-1a.c   | 13 ++++++++
 ld/testsuite/ld-x86-64/pr22001-1a.err |  2 ++
 ld/testsuite/ld-x86-64/pr22001-1b.c   | 13 ++++++++
 ld/testsuite/ld-x86-64/pr22001-1b.err |  2 ++
 ld/testsuite/ld-x86-64/pr22001-1c.c   | 12 +++++++
 ld/testsuite/ld-x86-64/x86-64.exp     | 60 +++++++++++++++++++++++++++++++++++
 11 files changed, 262 insertions(+), 12 deletions(-)
 create mode 100644 ld/testsuite/ld-i386/pr22001-1a.c
 create mode 100644 ld/testsuite/ld-i386/pr22001-1b.c
 create mode 100644 ld/testsuite/ld-i386/pr22001-1c.S
 create mode 100644 ld/testsuite/ld-x86-64/pr22001-1a.c
 create mode 100644 ld/testsuite/ld-x86-64/pr22001-1a.err
 create mode 100644 ld/testsuite/ld-x86-64/pr22001-1b.c
 create mode 100644 ld/testsuite/ld-x86-64/pr22001-1b.err
 create mode 100644 ld/testsuite/ld-x86-64/pr22001-1c.c

diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 84d63f404e..e30428d6d8 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -4942,13 +4942,17 @@ do_ifunc_pointer:
 	case R_X86_64_PC32:
 	case R_X86_64_PC32_BND:
 	  /* Don't complain about -fPIC if the symbol is undefined when
-	     building executable unless it is unresolved weak symbol.  */
+	     building executable unless it is unresolved weak symbol or
+	     -z nocopyreloc is used.  */
           if ((input_section->flags & SEC_ALLOC) != 0
 	      && (input_section->flags & SEC_READONLY) != 0
 	      && h != NULL
 	      && ((bfd_link_executable (info)
-		   && h->root.type == bfd_link_hash_undefweak
-		   && !resolved_to_zero)
+		   && ((h->root.type == bfd_link_hash_undefweak
+			&& !resolved_to_zero)
+		       || (info->nocopyreloc
+			   && h->def_dynamic
+			   && !(h->root.u.def.section->flags & SEC_CODE))))
 		  || bfd_link_dll (info)))
 	    {
 	      bfd_boolean fail = FALSE;
@@ -5717,15 +5721,26 @@ direct:
 	  && _bfd_elf_section_offset (output_bfd, info, input_section,
 				      rel->r_offset) != (bfd_vma) -1)
 	{
-	  _bfd_error_handler
-	    /* xgettext:c-format */
-	    (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
-	     input_bfd,
-	     input_section,
-	     rel->r_offset,
-	     howto->name,
-	     h->root.root.string);
-	  return FALSE;
+	  switch (r_type)
+	    {
+	    case R_X86_64_32S:
+	      if (info->nocopyreloc
+		  && !(h->root.u.def.section->flags & SEC_CODE))
+		return elf_x86_64_need_pic (info, input_bfd, input_section,
+					    h, NULL, NULL, howto);
+	      /* Fall through.  */
+
+	    default:
+	      _bfd_error_handler
+		/* xgettext:c-format */
+		(_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+		 input_bfd,
+		 input_section,
+		 rel->r_offset,
+		 howto->name,
+		 h->root.root.string);
+	      return FALSE;
+	    }
 	}
 
 do_relocation:
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 3c5de021b2..c91a8611f3 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -1245,6 +1245,17 @@ if { [isnative]
 if { [isnative]
      && [istarget "i?86-*-*"]
      && [which $CC] != 0 } {
+    run_cc_link_tests [list \
+	[list \
+	    "Build pr22001-1.so" \
+	    "-shared" \
+	    "" \
+	    { pr22001-1a.c } \
+	    {} \
+	    "pr22001-1.so" \
+	] \
+    ]
+
     run_ld_link_exec_tests [list \
 	[list \
 	    "Run weakundef1 without PIE" \
@@ -1255,7 +1266,51 @@ if { [isnative]
 	    "pass.out" \
 	    "$NOPIE_CFLAGS" \
 	] \
+	[list \
+	    "Run pr22001-1" \
+	    "$NOPIE_LDFLAGS -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1b.c } \
+	    "pr22001-1" \
+	    "pass.out" \
+	    "$NOPIE_CFLAGS" \
+	] \
+	[list \
+	    "Run pr22001-1 (PIE 1)" \
+	    "$NOPIE_LDFLAGS -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1c.S } \
+	    "pr22001-1-pie-1" \
+	    "pass.out" \
+	] \
+	[list \
+	    "Run pr22001-1 (PIE 2)" \
+	    "-pie -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1c.S } \
+	    "pr22001-1-pie-2" \
+	    "pass.out" \
+	] \
+	[list \
+	    "Run pr22001-1 (PIC 1)" \
+	    "$NOPIE_LDFLAGS -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1b.c } \
+	    "pr22001-1-pic-1" \
+	    "pass.out" \
+	    "-fPIC" \
+	] \
+	[list \
+	    "Run pr22001-1 (PIC 2)" \
+	    "-pie -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1b.c } \
+	    "pr22001-1-pic-2" \
+	    "pass.out" \
+	    "-fPIC" \
+	] \
     ]
+
     if { [at_least_gcc_version 5 0] } {
 	run_ld_link_exec_tests [list \
 	    [list \
diff --git a/ld/testsuite/ld-i386/pr22001-1a.c b/ld/testsuite/ld-i386/pr22001-1a.c
new file mode 100644
index 0000000000..2b55ea8efb
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22001-1a.c
@@ -0,0 +1,13 @@
+int copy = 1;
+
+int
+get_copy ()
+{
+  return copy;
+}
+
+int *
+get_copy_p ()
+{
+  return ©
+}
diff --git a/ld/testsuite/ld-i386/pr22001-1b.c b/ld/testsuite/ld-i386/pr22001-1b.c
new file mode 100644
index 0000000000..8eadd42109
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22001-1b.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+extern int copy;
+extern int get_copy (void);
+extern int* get_copy_p (void);
+
+int
+main ()
+{
+  if (copy == get_copy () && &copy == get_copy_p ())
+    printf ("PASS\n");
+
+  return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr22001-1c.S b/ld/testsuite/ld-i386/pr22001-1c.S
new file mode 100644
index 0000000000..2c1041dba7
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22001-1c.S
@@ -0,0 +1,51 @@
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.LC0:
+	.string	"PASS"
+	.section	.text.startup,"ax",@progbits
+	.p2align 4,,15
+	.globl	main
+	.type	main, @function
+main:
+	leal	4(%esp), %ecx
+	andl	$-16, %esp
+	pushl	-4(%ecx)
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%esi
+	pushl	%ebx
+	pushl	%ecx
+	call	__x86.get_pc_thunk.bx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	subl	$12, %esp
+	call	get_copy@PLT
+	movl	copy@GOT(%ebx), %esi
+	cmpl	(%esi), %eax
+	je	.L7
+.L3:
+	leal	-12(%ebp), %esp
+	xorl	%eax, %eax
+	popl	%ecx
+	popl	%ebx
+	popl	%esi
+	popl	%ebp
+	leal	-4(%ecx), %esp
+	ret
+.L7:
+	call	get_copy_p@PLT
+	cmpl	%esi, %eax
+	jne	.L3
+	leal	.LC0@GOTOFF(%ebx), %eax
+	subl	$12, %esp
+	pushl	%eax
+	call	puts@PLT
+	addl	$16, %esp
+	jmp	.L3
+	.size	main, .-main
+	.section	.text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+	.globl	__x86.get_pc_thunk.bx
+	.hidden	__x86.get_pc_thunk.bx
+	.type	__x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+	movl	(%esp), %ebx
+	ret
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr22001-1a.c b/ld/testsuite/ld-x86-64/pr22001-1a.c
new file mode 100644
index 0000000000..2b55ea8efb
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22001-1a.c
@@ -0,0 +1,13 @@
+int copy = 1;
+
+int
+get_copy ()
+{
+  return copy;
+}
+
+int *
+get_copy_p ()
+{
+  return &copy;
+}
diff --git a/ld/testsuite/ld-x86-64/pr22001-1a.err b/ld/testsuite/ld-x86-64/pr22001-1a.err
new file mode 100644
index 0000000000..640aa072b8
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22001-1a.err
@@ -0,0 +1,2 @@
+.*relocation R_X86_64_PC32 against symbol `copy' can not be used when making a P(D|I)E object; recompile with -fPIC
+#...
diff --git a/ld/testsuite/ld-x86-64/pr22001-1b.c b/ld/testsuite/ld-x86-64/pr22001-1b.c
new file mode 100644
index 0000000000..a172236f4f
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22001-1b.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern int copy;
+extern int get_copy (void);
+
+int
+main ()
+{
+  if (copy == get_copy ())
+    printf ("PASS\n");
+
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/pr22001-1b.err b/ld/testsuite/ld-x86-64/pr22001-1b.err
new file mode 100644
index 0000000000..9617e73f58
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22001-1b.err
@@ -0,0 +1,2 @@
+.*relocation R_X86_64_32S against symbol `copy' can not be used when making a P(D|I)E object; recompile with -fPIC
+#...
diff --git a/ld/testsuite/ld-x86-64/pr22001-1c.c b/ld/testsuite/ld-x86-64/pr22001-1c.c
new file mode 100644
index 0000000000..8fd925c8f7
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22001-1c.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+extern int copy;
+extern int* get_copy_p (void);
+
+int main()
+{
+  if (&copy == get_copy_p ())
+    printf ("PASS\n");
+
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 0b795df60b..6dc3665712 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1040,6 +1040,30 @@ if { [isnative] && [which $CC] != 0 } {
 	    {{readelf {-n} property-7.r}} \
 	    "property-7b.o" \
 	] \
+	[list \
+	    "Build pr22001-1.so" \
+	    "-shared" \
+	    "-fPIC" \
+	    { pr22001-1a.c } \
+	    {} \
+	    "pr22001-1.so" \
+	] \
+	[list \
+	    "Build pr22001-1a" \
+	    "$NOPIE_LDFLAGS -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "$NOPIE_CFLAGS" \
+	    { pr22001-1b.c } \
+	    {{error_output "pr22001-1a.err"}} \
+	    "pr22001-1a" \
+	] \
+	[list \
+	    "Build pr22001-1b" \
+	    "$NOPIE_LDFLAGS -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "$NOPIE_CFLAGS" \
+	    { pr22001-1c.c } \
+	    {{error_output "pr22001-1b.err"}} \
+	    "pr22001-1b" \
+	] \
     ]
 
     run_ld_link_exec_tests [list \
@@ -1216,6 +1240,42 @@ if { [isnative] && [which $CC] != 0 } {
 	    {property-x86-2.S property-x86-1.S pass.c property-stack.S} \
 	    "property-5-static" "pass.out" \
 	] \
+	[list \
+	    "Run pr22001-1a (PIC 1)" \
+	    "$NOPIE_LDFLAGS -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1b.c } \
+	    "pr22001-1a-pic-1" \
+	    "pass.out" \
+	    "-fPIC" \
+	] \
+	[list \
+	    "Run pr22001-1a (PIC 2)" \
+	    "-pie -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1b.c } \
+	    "pr22001-1a-pic-2" \
+	    "pass.out" \
+	    "-fPIC" \
+	] \
+	[list \
+	    "Run pr22001-1b (PIC 1)" \
+	    "$NOPIE_LDFLAGS -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1c.c } \
+	    "pr22001-1b-pic-1" \
+	    "pass.out" \
+	    "-fPIC" \
+	] \
+	[list \
+	    "Run pr22001-1b (PIC 2)" \
+	    "-pie -Wl,-z,nocopyreloc,--no-as-needed tmpdir/pr22001-1.so" \
+	    "" \
+	    { pr22001-1c.c } \
+	    "pr22001-1b-pic-2" \
+	    "pass.out" \
+	    "-fPIC" \
+	] \
     ]
 
     # Run-time tests which require working ifunc attribute support.
-- 
2.13.5


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