[committed] x86: Properly check building shared library

Message ID 20180213223129.GA30801@gmail.com
State New
Headers show
Series
  • [committed] x86: Properly check building shared library
Related show

Commit Message

H.J. Lu Feb. 13, 2018, 10:31 p.m.
If a symbol is not defined in a regular file, and we are not generating
a shared library, then set the symbol to its location in the .plt.  This
is required to make function pointers compare as equal between the normal
executable and the shared library.

	* elfxx-x86.c (elf_x86_allocate_dynrelocs): Check bfd_link_dll,
	instead of bfd_link_pic, for building shared library.
---
 bfd/elfxx-x86.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.14.3

Comments

Alan Modra Feb. 14, 2018, 2:11 a.m. | #1
On Tue, Feb 13, 2018 at 02:31:43PM -0800, H.J. Lu wrote:
> If a symbol is not defined in a regular file, and we are not generating

> a shared library, then set the symbol to its location in the .plt.  This

> is required to make function pointers compare as equal between the normal

> executable and the shared library.


I'm curious as to why this is necessary, in case other targets need
the same treatment.  Normally a PIE is built from position independent
code, and thus addresses of functions are loaded from the GOT.  That
means there is no need to use any tricks to avoid dynamic text relocs.

-- 
Alan Modra
Australia Development Lab, IBM
H.J. Lu Feb. 14, 2018, 5:13 a.m. | #2
On Tue, Feb 13, 2018 at 6:11 PM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, Feb 13, 2018 at 02:31:43PM -0800, H.J. Lu wrote:

>> If a symbol is not defined in a regular file, and we are not generating

>> a shared library, then set the symbol to its location in the .plt.  This

>> is required to make function pointers compare as equal between the normal

>> executable and the shared library.

>

> I'm curious as to why this is necessary, in case other targets need

> the same treatment.  Normally a PIE is built from position independent

> code, and thus addresses of functions are loaded from the GOT.  That

> means there is no need to use any tricks to avoid dynamic text relocs.

>


This is true in most cases.  However, you can use PC-relative relocation
to compute function address without GOT.  Here is a patch for

https://sourceware.org/bugzilla/show_bug.cgi?id=22842

with testcases in assembly for i386 and x86-64.  I think you can create
similar testcases for other targets.

I will check it in tomorrow.

-- 
H.J.
From 6b902f979e0239b2d1cb41d220a0b842907c5bb4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Tue, 13 Feb 2018 12:26:50 -0800
Subject: [PATCH] x86-64: Use PLT address for PC-relative reloc

Since PLT in PDE and PC-relative PLT in PIE can be used as function
address, there is no need for dynamic PC-relative relocation against
a dynamic function definition in PIE.  Linker should resolve PC-relative
reference to its PLT address.

NB: i386 has non-PIC PLT and PIC PLT.  Only non-PIC PLT in PDE can
be used as function address.  PIC PLT in PIE can't be used as
function address.

bfd/

	PR ld/22842
	* elf32-i386.c (elf_i386_check_relocs): Pass FALSE for non
	PC-relative PLT to NEED_DYNAMIC_RELOCATION_P.
	* elf64-x86-64.c (elf_x86_64_check_relocs): Create PLT for
	R_X86_64_PC32 reloc against dynamic function in data section.
	Pass TRUE for PC-relative PLT to NEED_DYNAMIC_RELOCATION_P.
	(elf_x86_64_relocate_section): Use PLT for R_X86_64_PC32 reloc
	against dynamic function in data section.
	* elfxx-x86.c (elf_x86_allocate_dynrelocs): Use PLT in PIE as
	function address only if pcrel_plt is true.
	(_bfd_x86_elf_link_hash_table_create): Set pcrel_plt.
	* elfxx-x86.h (NEED_DYNAMIC_RELOCATION_P): Add PCREL_PLT for
	PC-relative PLT.  If PLT is PC-relative, don't generate dynamic
	PC-relative relocation against a function definition in data
	secton in PIE.  Remove the obsolete comments.
	(elf_x86_link_hash_table): Add pcrel_plt.

ld/

	PR ld/22842
	* testsuite/ld-i386/i386.exp: Run PR ld/22842 tests.
	* testsuite/ld-x86-64/x86-64.exp: Likewise.
	* testsuite/ld-i386/pr22842a.c: New file.
	* testsuite/ld-i386/pr22842b.S: Likewise.
	* testsuite/ld-x86-64/pr22842a.c: Likewise.
	* testsuite/ld-x86-64/pr22842a.rd: Likewise.
	* testsuite/ld-x86-64/pr22842b.S: Likewise.
	* testsuite/ld-x86-64/pr22842b.rd: Likewise.
---
 bfd/elf32-i386.c                   |  2 +-
 bfd/elf64-x86-64.c                 | 24 ++++++++++++++++--
 bfd/elfxx-x86.c                    | 22 ++++++++++++-----
 bfd/elfxx-x86.h                    | 50 +++++++++++++++++++++++---------------
 ld/testsuite/ld-i386/i386.exp      | 16 ++++++++++++
 ld/testsuite/ld-i386/pr22842a.c    | 20 +++++++++++++++
 ld/testsuite/ld-i386/pr22842b.S    | 41 +++++++++++++++++++++++++++++++
 ld/testsuite/ld-x86-64/pr22842a.c  | 20 +++++++++++++++
 ld/testsuite/ld-x86-64/pr22842a.rd |  4 +++
 ld/testsuite/ld-x86-64/pr22842b.S  | 20 +++++++++++++++
 ld/testsuite/ld-x86-64/pr22842b.rd |  4 +++
 ld/testsuite/ld-x86-64/x86-64.exp  | 25 +++++++++++++++++++
 12 files changed, 220 insertions(+), 28 deletions(-)
 create mode 100644 ld/testsuite/ld-i386/pr22842a.c
 create mode 100644 ld/testsuite/ld-i386/pr22842b.S
 create mode 100644 ld/testsuite/ld-x86-64/pr22842a.c
 create mode 100644 ld/testsuite/ld-x86-64/pr22842a.rd
 create mode 100644 ld/testsuite/ld-x86-64/pr22842b.S
 create mode 100644 ld/testsuite/ld-x86-64/pr22842b.rd

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index e74da3af62..1a4b53ae30 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1812,7 +1812,7 @@ do_relocation:
 
 	  size_reloc = FALSE;
 do_size:
-	  if (NEED_DYNAMIC_RELOCATION_P (info, h, sec, r_type,
+	  if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
 					 R_386_32))
 	    {
 	      struct elf_dyn_relocs *p;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 0e4bb2e4a5..00ed5d17a5 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2135,7 +2135,17 @@ pointer:
 		     as pointer, make sure that PLT is used if foo is
 		     a function defined in a shared library.  */
 		  if ((sec->flags & SEC_CODE) == 0)
-		    h->pointer_equality_needed = 1;
+		    {
+		      h->pointer_equality_needed = 1;
+		      if (bfd_link_pie (info)
+			  && h->type == STT_FUNC
+			  && !h->def_regular
+			  && h->def_dynamic)
+			{
+			  h->needs_plt = 1;
+			  h->plt.refcount = 1;
+			}
+		    }
 		}
 	      else if (r_type != R_X86_64_PC32_BND
 		       && r_type != R_X86_64_PC64)
@@ -2173,7 +2183,7 @@ pointer:
 
 	  size_reloc = FALSE;
 do_size:
-	  if (NEED_DYNAMIC_RELOCATION_P (info, h, sec, r_type,
+	  if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type,
 					 htab->pointer_r_type))
 	    {
 	      struct elf_dyn_relocs *p;
@@ -2968,6 +2978,7 @@ do_ifunc_pointer:
 	      break;
 	    }
 
+use_plt:
 	  if (h->plt.offset != (bfd_vma) -1)
 	    {
 	      if (htab->plt_second != NULL)
@@ -3046,6 +3057,15 @@ do_ifunc_pointer:
 		return elf_x86_64_need_pic (info, input_bfd, input_section,
 					    h, NULL, NULL, howto);
 	    }
+	  /* Since x86-64 has PC-relative PLT, we can use PLT in PIE
+	     as function address.  */
+	  else if (h != NULL
+		   && (input_section->flags & SEC_CODE) == 0
+		   && bfd_link_pie (info)
+		   && h->type == STT_FUNC
+		   && !h->def_regular
+		   && h->def_dynamic)
+	    goto use_plt;
 	  /* Fall through.  */
 
 	case R_X86_64_8:
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index bd36707fc0..05d283b4fe 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -179,6 +179,7 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	  asection *s = htab->elf.splt;
 	  asection *second_s = htab->plt_second;
 	  asection *got_s = htab->plt_got;
+	  bfd_boolean use_plt;
 
 	  /* If this is the first .plt entry, make room for the special
 	     first entry.  The .plt section is used by prelink to undo
@@ -196,12 +197,19 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	    }
 
 	  /* If this symbol is not defined in a regular file, and we are
-	     not generating a shared library, then set the symbol to this
-	     location in the .plt.  This is required to make function
-	     pointers compare as equal between the normal executable and
-	     the shared library.  */
-	  if (! bfd_link_dll (info)
-	      && !h->def_regular)
+	     generating PDE, then set the symbol to this location in the
+	     .plt.  This is required to make function pointers compare
+	     as equal between PDE and the shared library.
+
+	     NB: If PLT is PC-relative, we can use the .plt in PIE for
+	     function address. */
+	  if (h->def_regular)
+	    use_plt = FALSE;
+	  else if (htab->pcrel_plt)
+	    use_plt = ! bfd_link_dll (info);
+	  else
+	    use_plt = bfd_link_pde (info);
+	  if (use_plt)
 	    {
 	      if (use_plt_got)
 		{
@@ -771,6 +779,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
       ret->dt_reloc_sz = DT_RELASZ;
       ret->dt_reloc_ent = DT_RELAENT;
       ret->got_entry_size = 8;
+      ret->pcrel_plt = TRUE;
       ret->tls_get_addr = "__tls_get_addr";
     }
   if (ABI_64_P (abfd))
@@ -798,6 +807,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
 	  ret->dt_reloc_ent = DT_RELENT;
 	  ret->sizeof_reloc = sizeof (Elf32_External_Rel);
 	  ret->got_entry_size = 4;
+	  ret->pcrel_plt = FALSE;
 	  ret->pointer_r_type = R_386_32;
 	  ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER;
 	  ret->dynamic_interpreter_size
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 0162a90c6d..f84fe01630 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -76,14 +76,11 @@
    into the shared library.  However, if we are linking with -Bsymbolic,
    we do not need to copy a reloc against a global symbol which is
    defined in an object we are including in the link (i.e., DEF_REGULAR
-   is set).  At this point we have not seen all the input files, so it
-   is possible that DEF_REGULAR is not set now but will be set later (it
-   is never cleared).  In case of a weak definition, DEF_REGULAR may be
-   cleared later by a strong definition in a shared library.  We account
-   for that possibility below by storing information in the relocs_copied
-   field of the hash table entry.  A similar situation occurs when
-   creating shared libraries and symbol visibility changes render the
-   symbol local.
+   is set).
+
+   If PCREL_PLT is true, don't generate dynamic relocation in PIE for
+   PC-relative relocation against a dynamic function definition in data
+   section when PLT address can be used.
 
    If on the other hand, we are creating an executable, we may need to
    keep relocations for symbols satisfied by a dynamic library if we
@@ -91,23 +88,30 @@
 
    We also need to generate dynamic pointer relocation against
    STT_GNU_IFUNC symbol in the non-code section.  */
-#define NEED_DYNAMIC_RELOCATION_P(INFO, H, SEC, R_TYPE, POINTER_TYPE) \
+#define NEED_DYNAMIC_RELOCATION_P(INFO, PCREL_PLT, H, SEC, R_TYPE, \
+				  POINTER_TYPE) \
   ((bfd_link_pic (INFO) \
     && (! X86_PCREL_TYPE_P (R_TYPE) \
 	|| ((H) != NULL \
 	    && (! (bfd_link_pie (INFO) \
 		   || SYMBOLIC_BIND ((INFO), (H))) \
 		|| (H)->root.type == bfd_link_hash_defweak \
-		|| !(H)->def_regular)))) \
-		|| ((H) != NULL \
-		    && (H)->type == STT_GNU_IFUNC \
-		    && (R_TYPE) == POINTER_TYPE \
-		    && ((SEC)->flags & SEC_CODE) == 0) \
-		    || (ELIMINATE_COPY_RELOCS \
-			&& !bfd_link_pic (INFO) \
-			&& (H) != NULL \
-			&& ((H)->root.type == bfd_link_hash_defweak \
-			    || !(H)->def_regular)))
+		|| (!(bfd_link_pie (INFO) \
+		      && (PCREL_PLT) \
+		      && (H)->plt.refcount > 0 \
+		      && ((SEC)->flags & SEC_CODE) == 0 \
+		      && (H)->type == STT_FUNC \
+		      && (H)->def_dynamic) \
+		    && !(H)->def_regular))))) \
+   || ((H) != NULL \
+       && (H)->type == STT_GNU_IFUNC \
+       && (R_TYPE) == POINTER_TYPE \
+       && ((SEC)->flags & SEC_CODE) == 0) \
+   || (ELIMINATE_COPY_RELOCS \
+       && !bfd_link_pic (INFO) \
+       && (H) != NULL \
+       && ((H)->root.type == bfd_link_hash_defweak \
+	   || !(H)->def_regular)))
 
 /* TRUE if dynamic relocation should be generated.  Don't copy a
    pc-relative relocation into the output file if the symbol needs
@@ -482,6 +486,14 @@ struct elf_x86_link_hash_table
   /* TRUE if GOT is referenced.  */
   unsigned int got_referenced : 1;
 
+  /* TRUE if PLT is PC-relative.  PLT in PDE and PC-relative PLT in PIE
+     can be used as function address.
+
+     NB: i386 has non-PIC PLT and PIC PLT.  Only non-PIC PLT in PDE can
+     be used as function address.  PIC PLT in PIE can't be used as
+     function address.  */
+  unsigned int pcrel_plt : 1;
+
   bfd_vma (*r_info) (bfd_vma, bfd_vma);
   bfd_vma (*r_sym) (bfd_vma);
   bfd_boolean (*is_reloc_section) (const char *);
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index e4ec07d0e9..ba2cce87ec 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -1273,6 +1273,14 @@ if { [isnative]
 	    {} \
 	    "pr21997-1.so" \
 	] \
+	[list \
+	    "Build pr22842.so" \
+	    "-shared" \
+	    "-fPIC" \
+	    { pr22842a.c } \
+	    {} \
+	    "pr22842.so" \
+	] \
     ]
 
     run_ld_link_exec_tests [list \
@@ -1371,6 +1379,14 @@ if { [isnative]
 	    "pr21997-1-pie-2" \
 	    "pass.out" \
 	] \
+	[list \
+	    "Build pr22842" \
+	    "-pie -Wl,--no-as-needed tmpdir/pr22842.so" \
+	    "" \
+	    { pr22842b.S } \
+	    "pr22842" \
+	    "pass.out" \
+	] \
     ]
 
     if { [at_least_gcc_version 5 0] } {
diff --git a/ld/testsuite/ld-i386/pr22842a.c b/ld/testsuite/ld-i386/pr22842a.c
new file mode 100644
index 0000000000..52489bba2f
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22842a.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+test (void)
+{
+  static int count;
+  if (count)
+    printf("PASS\n");
+  count++;
+}
+
+void
+foo (void (*bar) (void))
+{
+  if (bar != test)
+    abort ();
+  bar ();
+  test ();
+}
diff --git a/ld/testsuite/ld-i386/pr22842b.S b/ld/testsuite/ld-i386/pr22842b.S
new file mode 100644
index 0000000000..d959a5f34c
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr22842b.S
@@ -0,0 +1,41 @@
+	.text
+	.globl	main
+	.type	main, @function
+main:
+	leal	4(%esp), %ecx
+	andl	$-16, %esp
+	pushl	-4(%ecx)
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%ecx
+	call	__x86.get_pc_thunk.bx
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	subl	$12, %esp
+	movl	bar@GOT(%ebx), %eax
+	addl	(%eax), %eax
+	pushl	%eax
+	call	foo@PLT
+	addl	$16, %esp
+	leal	-8(%ebp), %esp
+	xorl	%eax, %eax
+	popl	%ecx
+	popl	%ebx
+	popl	%ebp
+	leal	-4(%ecx), %esp
+	ret
+	.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
+
+	.data
+	.p2align 2
+bar:
+	.long	test - .
+
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr22842a.c b/ld/testsuite/ld-x86-64/pr22842a.c
new file mode 100644
index 0000000000..52489bba2f
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22842a.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+test (void)
+{
+  static int count;
+  if (count)
+    printf("PASS\n");
+  count++;
+}
+
+void
+foo (void (*bar) (void))
+{
+  if (bar != test)
+    abort ();
+  bar ();
+  test ();
+}
diff --git a/ld/testsuite/ld-x86-64/pr22842a.rd b/ld/testsuite/ld-x86-64/pr22842a.rd
new file mode 100644
index 0000000000..d78ea2f7cc
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22842a.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_X86_64_NONE.*
+#...
diff --git a/ld/testsuite/ld-x86-64/pr22842b.S b/ld/testsuite/ld-x86-64/pr22842b.S
new file mode 100644
index 0000000000..f0659cd901
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22842b.S
@@ -0,0 +1,20 @@
+	.text
+	.globl	main
+	.type	main,@function
+main:
+	pushq	%rax
+        movslq  bar(%rip), %rax
+        leaq    bar(%rip), %rdi
+	addq	%rax, %rdi
+
+	callq	foo
+	xorl	%eax, %eax
+	popq	%rcx
+	retq
+
+	.data
+	.p2align 2
+bar:
+	.long	test - .
+
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/pr22842b.rd b/ld/testsuite/ld-x86-64/pr22842b.rd
new file mode 100644
index 0000000000..f1036d545c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr22842b.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_X86_64_PC32 +[0-9a-f]+ +test \+ 0
+#...
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 8442663af1..2a46266e0d 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -1190,6 +1190,23 @@ if { [isnative] && [which $CC] != 0 } {
 	    {{readelf -drW pr22791-2.rd}} \
 	    "pr22791-2" \
 	] \
+	[list \
+	    "Build pr22842.so" \
+	    "-shared" \
+	    "-fPIC" \
+	    { pr22842a.c } \
+	    {} \
+	    "pr22842.so" \
+	] \
+	[list \
+	    "Build pr22842" \
+	    "-pie -Wl,--no-as-needed tmpdir/pr22842.so" \
+	    "" \
+	    { pr22842b.S } \
+	    {{readelf -rW pr22842a.rd} \
+	     {readelf -rW pr22842b.rd}} \
+	    "pr22842" \
+	] \
     ]
 
     if  {[istarget "x86_64-*-linux*-gnux32"]} {
@@ -1524,6 +1541,14 @@ if { [isnative] && [which $CC] != 0 } {
 	    "pass.out" \
 	    "$NOPIE_CFLAGS" \
 	] \
+	[list \
+	    "Build pr22842" \
+	    "-pie -Wl,--no-as-needed tmpdir/pr22842.so" \
+	    "" \
+	    { pr22842b.S } \
+	    "pr22842" \
+	    "pass.out" \
+	] \
     ]
 
     # Run-time tests which require working ifunc attribute support.
Cary Coutant Feb. 14, 2018, 6:20 a.m. | #3
> I'm curious as to why this is necessary, in case other targets need

> the same treatment.  Normally a PIE is built from position independent

> code, and thus addresses of functions are loaded from the GOT.  That

> means there is no need to use any tricks to avoid dynamic text relocs.


I, for one, think it is not necessary, as anywhere it's valid to treat
the PC32 reloc as if it were a PLT32 reloc, the compiler or assembler
could (and should) have simply used a PLT32 reloc. I think it's
dangerous to simply assume that it's always valid to redirect any
arbitrary PC32 reloc to a PLT entry. There's a reason these are two
separate relocations.

I also think this is likely to be unique to the x86 architecture.

-cary
H.J. Lu Feb. 14, 2018, 12:04 p.m. | #4
On Tue, Feb 13, 2018 at 10:20 PM, Cary Coutant <ccoutant@gmail.com> wrote:
>> I'm curious as to why this is necessary, in case other targets need

>> the same treatment.  Normally a PIE is built from position independent

>> code, and thus addresses of functions are loaded from the GOT.  That

>> means there is no need to use any tricks to avoid dynamic text relocs.

>

> I, for one, think it is not necessary, as anywhere it's valid to treat

> the PC32 reloc as if it were a PLT32 reloc, the compiler or assembler

> could (and should) have simply used a PLT32 reloc. I think it's

> dangerous to simply assume that it's always valid to redirect any

> arbitrary PC32 reloc to a PLT entry. There's a reason these are two

> separate relocations.

>

> I also think this is likely to be unique to the x86 architecture.

>


It is normal on x86 for compiler/assembler to generate PC32 reloc and
linker to create PLT which is used as function address when we are
building non-PIE executable.  The issue is PIE.  We can't use PLT in
PIE as function address on i386 since PLT in PIE is EBX relative, which
is module specific.  But PLT on x86-64 is PC relative and PLT in PIE
can be used as function address just like PLT in non-PIE executable/

-- 
H.J.

Patch

diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index fc08d1b977..bd36707fc0 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -200,7 +200,7 @@  elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	     location in the .plt.  This is required to make function
 	     pointers compare as equal between the normal executable and
 	     the shared library.  */
-	  if (! bfd_link_pic (info)
+	  if (! bfd_link_dll (info)
 	      && !h->def_regular)
 	    {
 	      if (use_plt_got)