On Linux/x86-64 with GCC 5: [hjl@gnu-tools-1 pr17689-2]$ cat x.c #if 0 #include <stdio.h> extern char *program_invocation_name; int main () { printf ("%s\n", program_invocation_name); return 0; } #else extern char *bar_alias; extern void foo (char *); char **ptr = &bar_alias; int main () { foo (bar_alias); foo (*ptr); return 0; } #endif [hjl@gnu-tools-1 pr17689-2]$ cat bar.c #include <stdio.h> char *bar = "PASS"; extern char *bar_alias __attribute__ ((weak, alias ("bar"))); void foo (char *x) { printf ("%s\n", x); } [hjl@gnu-tools-1 pr17689-2]$ make gcc -pie -o x x.o libbar.so -Wl,-rpath,. /usr/local/bin/ld: x.o(.data.rel+0x0): reloc against `bar_alias': error 4 /usr/local/bin/ld: final link failed: Nonrepresentable section on output collect2: error: ld returned 1 exit status make: *** [x] Error 1 [hjl@gnu-tools-1 pr17689-2]$
commit 9d1d54d5a7e3b634895e6e434646c706eb55c082 Author: H.J. Lu <hjl.tools@gmail.com> Date: Sun Jan 11 08:04:27 2015 -0800 Only discard space for pc-relative relocs symbols When building PIE, we should only discard space for pc-relative relocs symbols which turn out to need copy relocs. bfd/ PR ld/17827 * elf64-x86-64.c (elf_x86_64_allocate_dynrelocs): For PIE, only discard space for pc-relative relocs symbols which turn out to need copy relocs. ld/testsuite/ PR ld/17827 * ld-x86-64/pr17689.out: Updated. * ld-x86-64/pr17689b.S: Likewise. * ld-x86-64/pr17827.rd: New file. * ld-x86-64/x86-64.exp: Run PR ld/17827 test. diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 70b138b..234d559 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2015-01-11 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/17827 + * elf64-x86-64.c (elf_x86_64_allocate_dynrelocs): For PIE, + only discard space for pc-relative relocs symbols which turn + out to need copy relocs. + 2015-01-09 Nick Clifton <nickc@redhat.com> * tekhex.c (getvalue): Fix thinko in test for correct extraction diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 581ee17..6b7d3c9 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2742,13 +2742,23 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) && ! bfd_elf_link_record_dynamic_symbol (info, h)) return FALSE; } - /* For PIE, discard space for relocs against symbols which - turn out to need copy relocs. */ + /* For PIE, discard space for pc-relative relocs against + symbols which turn out to need copy relocs. */ else if (info->executable && (h->needs_copy || eh->needs_copy) && h->def_dynamic && !h->def_regular) - eh->dyn_relocs = NULL; + { + struct elf_dyn_relocs **pp; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + { + if (p->pc_count != 0) + *pp = p->next; + else + pp = &p->next; + } + } } } else if (ELIMINATE_COPY_RELOCS) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 229e006..e6903f7 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2015-01-11 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/17827 + * ld-x86-64/pr17689.out: Updated. + * ld-x86-64/pr17689b.S: Likewise. + + * ld-x86-64/pr17827.rd: New file. + + * ld-x86-64/x86-64.exp: Run PR ld/17827 test. + 2015-01-08 Jan Beulich <jbeulich@suse.com> * ld-x86-64/pr14207.d: Adjust expecations to cover the diff --git a/ld/testsuite/ld-x86-64/pr17689.out b/ld/testsuite/ld-x86-64/pr17689.out index 7ef22e9..38e0352 100644 --- a/ld/testsuite/ld-x86-64/pr17689.out +++ b/ld/testsuite/ld-x86-64/pr17689.out @@ -1 +1,2 @@ PASS +PASS diff --git a/ld/testsuite/ld-x86-64/pr17689b.S b/ld/testsuite/ld-x86-64/pr17689b.S index c95f891..64485c7 100644 --- a/ld/testsuite/ld-x86-64/pr17689b.S +++ b/ld/testsuite/ld-x86-64/pr17689b.S @@ -5,8 +5,18 @@ main: subq $8, %rsp movq bar_alias(%rip), %rdi call foo@PLT + movq ptr(%rip), %rax + movq (%rax), %rdi + call foo@PLT xorl %eax, %eax addq $8, %rsp ret .size main, .-main + .globl ptr + .section .data.rel,"aw",@progbits + .align 8 + .type ptr, @object + .size ptr, 8 +ptr: + .quad bar_alias .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/pr17827.rd b/ld/testsuite/ld-x86-64/pr17827.rd new file mode 100644 index 0000000..d78ea2f --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr17827.rd @@ -0,0 +1,4 @@ +#failif +#... +[0-9a-f ]+R_X86_64_NONE.* +#... diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index aa8555f..5b49bff 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -432,6 +432,14 @@ if { [isnative] && [which $CC] != 0 } { {{readelf {-Wr} pr17689.rd}} \ "pr17689" \ ] \ + [list \ + "Build pr17827 with PIE without -fPIE" \ + "tmpdir/pr17689.so -pie" \ + "" \ + { pr17689b.S } \ + {{readelf {-Wr} pr17827.rd}} \ + "pr17827" \ + ] \ ] run_ld_link_exec_tests [] [list \
Sorry about the diff. I was trying to reproduce, and forgot to exclude the diff from the call to the script that fails those commits. It's a one-off.
Checked the fix into master and 2.25 branches.