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] PR ld/20515: i386: Issue an error on non-PIC call to IFUNC in PIC object


On i386, IFUNC function must be called via PLT.  Since PLT in PIC
object uses EBX register, R_386_PLT32 relocation must be used to
call IFUNC function even when IFUNC function is defined locally.
Linker should issue an error when R_386_PC32 relocation is used
to call IFUNC function.

Since PR ld/19784 tests doesn't use PLT relocation to local IFUNC
function, they are moved to the x86-64 test directory.

Tested on i386.  I will check it in.

H.J.
---
bfd/

	PR ld/14961
	PR ld/20515
	* elf32-i386.c (elf_i386_check_relocs): Issue an error when
	R_386_PC32 relocation is used to call IFUNC function in PIC
	object.

ld/

	PR ld/14961
	PR ld/20515
	* testsuite/ld-i386/i386.exp: Run pr20515.
	* testsuite/ld-i386/pr20515.d: New file.
	* testsuite/ld-i386/pr20515.s: Likewise.
	* testsuite/ld-ifunc/ifunc-14a.s: Use R_386_PLT32 to call IFUNC
	function.
	* testsuite/ld-ifunc/ifunc-14c.s: Likewise.
	* testsuite/ld-ifunc/ifunc-2-i386.s: Likewise.
	* testsuite/ld-ifunc/ifunc-2-local-i386.s: Likewise.
	* testsuite/ld-ifunc/ifunc.exp: Move PR ld/19784 tests to ...
	* testsuite/ld-x86-64/x86-64.exp: Here.
	* testsuite/ld-ifunc/pr19784a.c: Moved to ...
	* testsuite/ld-x86-64/pr19784a.c: Here.
	* testsuite/ld-ifunc/pr19784b.c: Moved to ...
	* testsuite/ld-x86-64/pr19784b.c: Here.
	* testsuite/ld-ifunc/pr19784c.c: Moved to ...
	* testsuite/ld-x86-64/pr19784c.c: Here.
---
 bfd/elf32-i386.c                           | 14 +++++++++++
 ld/testsuite/ld-i386/i386.exp              |  1 +
 ld/testsuite/ld-i386/pr20515.d             |  3 +++
 ld/testsuite/ld-i386/pr20515.s             | 12 +++++++++
 ld/testsuite/ld-ifunc/ifunc-14a.s          |  2 +-
 ld/testsuite/ld-ifunc/ifunc-14c.s          |  2 +-
 ld/testsuite/ld-ifunc/ifunc-2-i386.s       |  2 +-
 ld/testsuite/ld-ifunc/ifunc-2-local-i386.s |  2 +-
 ld/testsuite/ld-ifunc/ifunc.exp            | 40 ------------------------------
 ld/testsuite/ld-ifunc/pr19784a.c           |  6 -----
 ld/testsuite/ld-ifunc/pr19784b.c           | 11 --------
 ld/testsuite/ld-ifunc/pr19784c.c           | 11 --------
 ld/testsuite/ld-x86-64/pr19784a.c          |  6 +++++
 ld/testsuite/ld-x86-64/pr19784b.c          | 11 ++++++++
 ld/testsuite/ld-x86-64/pr19784c.c          | 11 ++++++++
 ld/testsuite/ld-x86-64/x86-64.exp          | 38 ++++++++++++++++++++++++++++
 16 files changed, 100 insertions(+), 72 deletions(-)
 create mode 100644 ld/testsuite/ld-i386/pr20515.d
 create mode 100644 ld/testsuite/ld-i386/pr20515.s
 delete mode 100644 ld/testsuite/ld-ifunc/pr19784a.c
 delete mode 100644 ld/testsuite/ld-ifunc/pr19784b.c
 delete mode 100644 ld/testsuite/ld-ifunc/pr19784c.c
 create mode 100644 ld/testsuite/ld-x86-64/pr19784a.c
 create mode 100644 ld/testsuite/ld-x86-64/pr19784b.c
 create mode 100644 ld/testsuite/ld-x86-64/pr19784c.c

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 4179572..17f86e8 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2178,6 +2178,20 @@ do_relocation:
 		     a function defined in a shared library.  */
 		  if ((sec->flags & SEC_CODE) == 0)
 		    h->pointer_equality_needed = 1;
+		  else if (h->type == STT_GNU_IFUNC
+			   && bfd_link_pic (info))
+		    {
+		    if (isym == NULL)
+		      name = h->root.root.string;
+		    else
+		      name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+					       NULL);
+		    (*_bfd_error_handler)
+		      (_("%B: unsupported non-PIC call to IFUNC `%s'"),
+		       abfd, name);
+		      bfd_set_error (bfd_error_bad_value);
+		      goto error_return;
+		    }
 		}
 	      else
 		{
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 2ba0f05..aedec41 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -413,6 +413,7 @@ run_dump_test "pr20253-4a"
 run_dump_test "pr20253-4b"
 run_dump_test "pr20253-4c"
 run_dump_test "pr20253-5"
+run_dump_test "pr20515"
 
 if { !([istarget "i?86-*-linux*"]
        || [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/pr20515.d b/ld/testsuite/ld-i386/pr20515.d
new file mode 100644
index 0000000..f3f5fec
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20515.d
@@ -0,0 +1,3 @@
+#as: --32
+#ld: -m elf_i386 -shared
+#error: unsupported non-PIC call to IFUNC `foo'
diff --git a/ld/testsuite/ld-i386/pr20515.s b/ld/testsuite/ld-i386/pr20515.s
new file mode 100644
index 0000000..eb86cbc
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20515.s
@@ -0,0 +1,12 @@
+	.text
+	.globl bar
+	.type	bar, @function
+bar:
+	jmp	foo
+	.size	bar, .-bar
+	.hidden	foo
+	.type foo, %gnu_indirect_function
+	.globl foo
+foo:
+	ret
+	.size	foo, .-foo
diff --git a/ld/testsuite/ld-ifunc/ifunc-14a.s b/ld/testsuite/ld-ifunc/ifunc-14a.s
index 9f20604..87bc0ef 100644
--- a/ld/testsuite/ld-ifunc/ifunc-14a.s
+++ b/ld/testsuite/ld-ifunc/ifunc-14a.s
@@ -2,6 +2,6 @@
 	.globl bar
 	.type	bar, @function
 bar:
-	jmp	foo
+	jmp	foo@PLT
 	.size	bar, .-bar
 	.hidden	foo
diff --git a/ld/testsuite/ld-ifunc/ifunc-14c.s b/ld/testsuite/ld-ifunc/ifunc-14c.s
index 3cde56e..1a714cb 100644
--- a/ld/testsuite/ld-ifunc/ifunc-14c.s
+++ b/ld/testsuite/ld-ifunc/ifunc-14c.s
@@ -2,6 +2,6 @@
 	.globl xxx
 	.type	xxx, @function
 xxx:
-	jmp	foo
+	jmp	foo@PLT
 	.size	xxx, .-xxx
 	.hidden	foo
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-i386.s b/ld/testsuite/ld-ifunc/ifunc-2-i386.s
index 32d8812..e84d6b7 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-i386.s
+++ b/ld/testsuite/ld-ifunc/ifunc-2-i386.s
@@ -15,7 +15,7 @@ bar:
 .L6:
 	popl	%ebx
 	addl	$_GLOBAL_OFFSET_TABLE_+[.-.L6], %ebx
-	call	__GI_foo
+	call	__GI_foo@PLT
 	leal	__GI_foo@GOTOFF(%ebx), %eax
 	ret
 	.size	bar, .-bar
diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s b/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s
index 4e0b6ae..a69e060 100644
--- a/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s
+++ b/ld/testsuite/ld-ifunc/ifunc-2-local-i386.s
@@ -12,7 +12,7 @@ bar:
 .L6:
 	popl	%ebx
 	addl	$_GLOBAL_OFFSET_TABLE_+[.-.L6], %ebx
-	call	__GI_foo
+	call	__GI_foo@PLT
 	leal	__GI_foo@GOTOFF(%ebx), %eax
 	ret
 	.size	bar, .-bar
diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp
index c3c9379..504007a 100644
--- a/ld/testsuite/ld-ifunc/ifunc.exp
+++ b/ld/testsuite/ld-ifunc/ifunc.exp
@@ -505,30 +505,6 @@ run_cc_link_tests [list \
 	{} \
 	"libpr18841c.so" \
     ] \
-    [list \
-	"Build libpr19784a.so" \
-	"-shared -Wl,-Bsymbolic-functions" \
-	"-fPIC -O2 -g" \
-	{ pr19784b.c pr19784c.c } \
-	{} \
-	"libpr19784a.so" \
-    ] \
-    [list \
-	"Build libpr19784b.so" \
-	"-shared -Wl,-Bsymbolic-functions" \
-	"-fPIC -O2 -g" \
-	{ pr19784c.c pr19784b.c } \
-	{} \
-	"libpr19784b.so" \
-    ] \
-    [list \
-	"Build pr19784a.o" \
-	"" \
-	"" \
-	{ pr19784a.c } \
-	"" \
-	"" \
-    ] \
 ]
 
 run_ld_link_exec_tests [list \
@@ -556,20 +532,4 @@ run_ld_link_exec_tests [list \
 	"pr18841c" \
 	"pr18841.out" \
     ] \
-    [list \
-	"Run pr19784a" \
-	"tmpdir/pr19784a.o tmpdir/libpr19784a.so" \
-	"" \
-	{ dummy.c } \
-	"pr19784a" \
-	"pass.out" \
-    ] \
-    [list \
-	"Run pr19784b" \
-	"--as-needed tmpdir/pr19784a.o tmpdir/libpr19784b.so" \
-	"" \
-	{ dummy.c } \
-	"pr19784b" \
-	"pass.out" \
-    ] \
 ]
diff --git a/ld/testsuite/ld-ifunc/pr19784a.c b/ld/testsuite/ld-ifunc/pr19784a.c
deleted file mode 100644
index c922cb9..0000000
--- a/ld/testsuite/ld-ifunc/pr19784a.c
+++ /dev/null
@@ -1,6 +0,0 @@
-void bar(void);
-int main(void)
-{
-  bar();
-  return 0;
-}
diff --git a/ld/testsuite/ld-ifunc/pr19784b.c b/ld/testsuite/ld-ifunc/pr19784b.c
deleted file mode 100644
index 8ea7ce2..0000000
--- a/ld/testsuite/ld-ifunc/pr19784b.c
+++ /dev/null
@@ -1,11 +0,0 @@
-int foo (int x) __attribute__ ((ifunc ("resolve_foo")));
-
-static int foo_impl(int x)
-{
-  return x;
-}
-
-void *resolve_foo (void)
-{
-  return (void *) foo_impl;
-}
diff --git a/ld/testsuite/ld-ifunc/pr19784c.c b/ld/testsuite/ld-ifunc/pr19784c.c
deleted file mode 100644
index 117dfec..0000000
--- a/ld/testsuite/ld-ifunc/pr19784c.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <stdio.h>
-
-extern void abort (void);
-extern int foo (int) __attribute__ ((visibility("hidden")));
-
-int bar()
-{
-  if (foo (5) != 5)
-    abort ();
-  printf("PASS\n");
-}
diff --git a/ld/testsuite/ld-x86-64/pr19784a.c b/ld/testsuite/ld-x86-64/pr19784a.c
new file mode 100644
index 0000000..c922cb9
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr19784a.c
@@ -0,0 +1,6 @@
+void bar(void);
+int main(void)
+{
+  bar();
+  return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/pr19784b.c b/ld/testsuite/ld-x86-64/pr19784b.c
new file mode 100644
index 0000000..8ea7ce2
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr19784b.c
@@ -0,0 +1,11 @@
+int foo (int x) __attribute__ ((ifunc ("resolve_foo")));
+
+static int foo_impl(int x)
+{
+  return x;
+}
+
+void *resolve_foo (void)
+{
+  return (void *) foo_impl;
+}
diff --git a/ld/testsuite/ld-x86-64/pr19784c.c b/ld/testsuite/ld-x86-64/pr19784c.c
new file mode 100644
index 0000000..117dfec
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr19784c.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+extern void abort (void);
+extern int foo (int) __attribute__ ((visibility("hidden")));
+
+int bar()
+{
+  if (foo (5) != 5)
+    abort ();
+  printf("PASS\n");
+}
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 5fa4c9f..01b6a49 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -822,6 +822,28 @@ if { [isnative] && [which $CC] != 0 } {
 	    {{objdump {-dw} pr19319.dd}} \
 	    "pr19319" \
 	] \
+	[list \
+	    "Build libpr19784a.so" \
+	    "-shared -Wl,-Bsymbolic-functions" \
+	    "-fPIC -O2 -g" \
+	    { pr19784b.c pr19784c.c } \
+	    {} \
+	    "libpr19784a.so" \
+	] \
+	[list \
+	    "Build libpr19784b.so" \
+	    "-shared -Wl,-Bsymbolic-functions" \
+	    "-fPIC -O2 -g" \
+	    { pr19784c.c pr19784b.c } \
+	    {} \
+	    "libpr19784b.so" \
+	] \
+	[list \
+	   "Build pr19784a.o" \
+	   "" \
+	   "" \
+	   { pr19784a.c } \
+	] \
     ]
 
     run_ld_link_exec_tests [list \
@@ -892,6 +914,22 @@ if { [isnative] && [which $CC] != 0 } {
 	    "gotpcrel1" \
 	    "gotpcrel1.out" \
 	] \
+	[list \
+	    "Run pr19784a" \
+	    "tmpdir/pr19784a.o tmpdir/libpr19784a.so" \
+	    "" \
+	    { dummy.s } \
+	    "pr19784a" \
+	    "pass.out" \
+	] \
+	[list \
+	    "Run pr19784b" \
+	    "--as-needed tmpdir/pr19784a.o tmpdir/libpr19784b.so" \
+	    "" \
+	    { dummy.s } \
+	    "pr19784b" \
+	    "pass.out" \
+	] \
     ]
 
     if { [istarget "x86_64-*-linux*"] \
-- 
2.7.4


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