summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-08-24 06:34:19 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-08-24 06:34:38 -0700
commit7073b5b9edc9e06974bd733b7e4b3845d6d6f690 (patch)
treee732f58dcdb8352c0fd8f288e529993ece2fd312
parent5b5f4e6f8cd250e07ec98278f7223e57b3d3bb0c (diff)
downloadbinutils-gdb-7073b5b9edc9e06974bd733b7e4b3845d6d6f690.tar.gz
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.
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf64-x86-64.c39
-rw-r--r--ld/ChangeLog14
-rw-r--r--ld/testsuite/ld-i386/i386.exp55
-rw-r--r--ld/testsuite/ld-i386/pr22001-1a.c13
-rw-r--r--ld/testsuite/ld-i386/pr22001-1b.c14
-rw-r--r--ld/testsuite/ld-i386/pr22001-1c.S51
-rw-r--r--ld/testsuite/ld-x86-64/pr22001-1a.c13
-rw-r--r--ld/testsuite/ld-x86-64/pr22001-1a.err2
-rw-r--r--ld/testsuite/ld-x86-64/pr22001-1b.c13
-rw-r--r--ld/testsuite/ld-x86-64/pr22001-1b.err2
-rw-r--r--ld/testsuite/ld-x86-64/pr22001-1c.c12
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp60
13 files changed, 283 insertions, 12 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index a45b896e520..bb389205217 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,12 @@
2017-08-24 H.J. Lu <hongjiu.lu@intel.com>
+ 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.
+
+2017-08-24 H.J. Lu <hongjiu.lu@intel.com>
+
* elf32-i386.c (elf_i386_check_relocs): Revert the last change.
Undefined symbols may not have a type.
* elf64-x86-64.c (elf_x86_64_check_relocs): Likewise.
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 84d63f404e1..e30428d6d80 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/ChangeLog b/ld/ChangeLog
index e3faa792f5d..0c445920232 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,17 @@
+2017-08-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ 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.
+
2017-08-17 Andrew Burgess <andrew.burgess@embecosm.com>
PR 21961
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 3c5de021b2b..c91a8611f37 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 00000000000..2b55ea8efbf
--- /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 &copy;
+}
diff --git a/ld/testsuite/ld-i386/pr22001-1b.c b/ld/testsuite/ld-i386/pr22001-1b.c
new file mode 100644
index 00000000000..8eadd42109f
--- /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 00000000000..2c1041dba77
--- /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 00000000000..2b55ea8efbf
--- /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 00000000000..640aa072b86
--- /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 00000000000..a172236f4f2
--- /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 00000000000..9617e73f58c
--- /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 00000000000..8fd925c8f76
--- /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 0b795df60bb..6dc36657121 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.