aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog13
-rw-r--r--bfd/elf32-i386.c64
-rw-r--r--ld/testsuite/ChangeLog17
-rw-r--r--ld/testsuite/ld-i386/copyreloc-lib.c1
-rw-r--r--ld/testsuite/ld-i386/copyreloc-main.S24
-rw-r--r--ld/testsuite/ld-i386/copyreloc-main.out0
-rw-r--r--ld/testsuite/ld-i386/copyreloc-main1.rd3
-rw-r--r--ld/testsuite/ld-i386/copyreloc-main2.rd4
-rw-r--r--ld/testsuite/ld-i386/dummy.c1
-rw-r--r--ld/testsuite/ld-i386/i386.exp96
-rw-r--r--ld/testsuite/ld-i386/pr17689.out2
-rw-r--r--ld/testsuite/ld-i386/pr17689.rd3
-rw-r--r--ld/testsuite/ld-i386/pr17689a.c10
-rw-r--r--ld/testsuite/ld-i386/pr17689a.t6
-rw-r--r--ld/testsuite/ld-i386/pr17689b.S44
-rw-r--r--ld/testsuite/ld-i386/pr17689ver.rd3
-rw-r--r--ld/testsuite/ld-i386/pr17827.rd4
17 files changed, 277 insertions, 18 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1f95fd5..94aca52 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+2015-04-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/18289
+ * elf32-i386.c (elf_i386_link_hash_entry): Add gotoff_ref.
+ (elf_i386_link_hash_newfunc): Initialize gotoff_ref to 0.
+ (elf_i386_create_dynamic_sections): Always allow copy relocs for
+ building executables.
+ (elf_i386_copy_indirect_symbol): Also copy gotoff_ref.
+ (elf_i386_check_relocs): Set gotoff_ref for R_386_GOTOFF.
+ (elf_i386_adjust_dynamic_symbol): Also allocate copy relocs for
+ PIE and R_386_GOTOFF.
+ (elf_i386_relocate_section): Allow R_386_GOTOFF in executable.
+
2015-04-20 H.J. Lu <hongjiu.lu@intel.com>
* elf.c (assign_section_numbers): Always set up sh_name.
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index f71bce1..d76addb 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -756,6 +756,9 @@ struct elf_i386_link_hash_entry
(GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
unsigned char tls_type;
+ /* Symbol is referenced by R_386_GOTOFF relocation. */
+ unsigned int gotoff_ref : 1;
+
/* Information about the GOT PLT entry. Filled when there are both
GOT and PLT relocations against the same function. */
union gotplt_union plt_got;
@@ -879,6 +882,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
eh = (struct elf_i386_link_hash_entry *) entry;
eh->dyn_relocs = NULL;
eh->tls_type = GOT_UNKNOWN;
+ eh->gotoff_ref = 0;
eh->plt_got.offset = (bfd_vma) -1;
eh->tlsdesc_got = (bfd_vma) -1;
}
@@ -1022,13 +1026,28 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
return FALSE;
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
- if (!info->shared)
- htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss");
-
- if (!htab->sdynbss
- || (!info->shared && !htab->srelbss))
+ if (!htab->sdynbss)
abort ();
+ if (info->executable)
+ {
+ /* Always allow copy relocs for building executables. */
+ asection *s = bfd_get_linker_section (dynobj, ".rel.bss");
+ if (s == NULL)
+ {
+ const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
+ s = bfd_make_section_anyway_with_flags (dynobj,
+ ".rel.bss",
+ (bed->dynamic_sec_flags
+ | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (dynobj, s,
+ bed->s->log_file_align))
+ return FALSE;
+ }
+ htab->srelbss = s;
+ }
+
if (get_elf_i386_backend_data (dynobj)->is_vxworks
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
&htab->srelplt2))
@@ -1101,6 +1120,10 @@ elf_i386_copy_indirect_symbol (struct bfd_link_info *info,
eind->tls_type = GOT_UNKNOWN;
}
+ /* Copy gotoff_ref so that elf_i386_adjust_dynamic_symbol will
+ generate a R_386_COPY reloc. */
+ edir->gotoff_ref |= eind->gotoff_ref;
+
if (ELIMINATE_COPY_RELOCS
&& ind->root.type != bfd_link_hash_indirect
&& dir->dynamic_adjusted)
@@ -1475,6 +1498,7 @@ elf_i386_check_relocs (bfd *abfd,
unsigned int r_type;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
+ struct elf_i386_link_hash_entry *eh;
Elf_Internal_Sym *isym;
const char *name;
bfd_boolean size_reloc;
@@ -1524,6 +1548,7 @@ elf_i386_check_relocs (bfd *abfd,
h = (struct elf_link_hash_entry *) h->root.u.i.link;
}
+ eh = (struct elf_i386_link_hash_entry *) h;
if (h != NULL)
{
/* Create the ifunc sections for static executables. If we
@@ -1535,11 +1560,12 @@ elf_i386_check_relocs (bfd *abfd,
default:
break;
+ case R_386_GOTOFF:
+ eh->gotoff_ref = 1;
case R_386_32:
case R_386_PC32:
case R_386_PLT32:
case R_386_GOT32:
- case R_386_GOTOFF:
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
@@ -1791,7 +1817,7 @@ do_size:
relocations we need for this symbol. */
if (h != NULL)
{
- head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
+ head = &eh->dyn_relocs;
}
else
{
@@ -2175,12 +2201,14 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
only references to the symbol are via the global offset table.
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
- if (info->shared)
+ if (!info->executable)
return TRUE;
/* If there are no references to this symbol that do not use the
- GOT, we don't need to generate a copy reloc. */
- if (!h->non_got_ref)
+ GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
+ reloc. */
+ eh = (struct elf_i386_link_hash_entry *) h;
+ if (!h->non_got_ref && !eh->gotoff_ref)
return TRUE;
/* If -z nocopyreloc was given, we won't generate them either. */
@@ -2194,14 +2222,15 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
if (htab == NULL)
return FALSE;
- /* If there aren't any dynamic relocs in read-only sections, then
- we can keep the dynamic relocs and avoid the copy reloc. This
- doesn't work on VxWorks, where we can not have dynamic relocations
- (other than copy and jump slot relocations) in an executable. */
+ /* If there aren't any dynamic relocs in read-only sections nor
+ R_386_GOTOFF relocation, then we can keep the dynamic relocs and
+ avoid the copy reloc. This doesn't work on VxWorks, where we can
+ not have dynamic relocations (other than copy and jump slot
+ relocations) in an executable. */
if (ELIMINATE_COPY_RELOCS
+ && !eh->gotoff_ref
&& !get_elf_i386_backend_data (info->output_bfd)->is_vxworks)
{
- eh = (struct elf_i386_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
s = p->sec->output_section;
@@ -3718,7 +3747,7 @@ elf_i386_relocate_section (bfd *output_bfd,
symbol for shared library since it may not be local when
used as function address or with copy relocation. We also
need to make sure that a symbol is referenced locally. */
- if (info->shared && h)
+ if (!info->executable && h)
{
if (!h->def_regular)
{
@@ -3746,8 +3775,7 @@ elf_i386_relocate_section (bfd *output_bfd,
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
- else if (!info->executable
- && !SYMBOL_REFERENCES_LOCAL (info, h)
+ else if (!SYMBOL_REFERENCES_LOCAL (info, h)
&& (h->type == STT_FUNC
|| h->type == STT_OBJECT)
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 240a444..ea6a863 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,20 @@
+2015-04-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/18289
+ * ld-i386/copyreloc-lib.c: New file.
+ * ld-i386/copyreloc-main.S: Likewise.
+ * ld-i386/copyreloc-main.out: Likewise.
+ * ld-i386/copyreloc-main1.rd: Likewise.
+ * ld-i386/copyreloc-main2.rd: Likewise.
+ * ld-i386/dummy.c: Likewise.
+ * ld-i386/pr17689.out: Likewise.
+ * ld-i386/pr17689.rd: Likewise.
+ * ld-i386/pr17689a.c: Likewise.
+ * ld-i386/pr17689b.S: Likewise.
+ * ld-i386/pr17827.rd: Likewise.
+ * ld-i386/pr17827ver.rd: Likewise.
+ * ld-i386/i386.exp: Run copyreloc tests.
+
2015-04-20 H.J. Lu <hongjiu.lu@intel.com>
* ld-mmix/bspec1.d: Don't hardcode offset of .shstrtab section.
diff --git a/ld/testsuite/ld-i386/copyreloc-lib.c b/ld/testsuite/ld-i386/copyreloc-lib.c
new file mode 100644
index 0000000..cbbc5e2
--- /dev/null
+++ b/ld/testsuite/ld-i386/copyreloc-lib.c
@@ -0,0 +1 @@
+int a_glob = 2;
diff --git a/ld/testsuite/ld-i386/copyreloc-main.S b/ld/testsuite/ld-i386/copyreloc-main.S
new file mode 100644
index 0000000..98aef83
--- /dev/null
+++ b/ld/testsuite/ld-i386/copyreloc-main.S
@@ -0,0 +1,24 @@
+ .section .text.startup,"ax",@progbits
+ .p2align 4,,15
+ .globl main
+ .type main, @function
+main:
+ .cfi_startproc
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ cmpl $2, a_glob@GOTOFF(%eax)
+ setne %al
+ movzbl %al, %eax
+ ret
+ .cfi_endproc
+ .size main, .-main
+ .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
+ .globl __x86.get_pc_thunk.ax
+ .hidden __x86.get_pc_thunk.ax
+ .type __x86.get_pc_thunk.ax, @function
+__x86.get_pc_thunk.ax:
+ .cfi_startproc
+ movl (%esp), %eax
+ ret
+ .cfi_endproc
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/copyreloc-main.out b/ld/testsuite/ld-i386/copyreloc-main.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ld/testsuite/ld-i386/copyreloc-main.out
diff --git a/ld/testsuite/ld-i386/copyreloc-main1.rd b/ld/testsuite/ld-i386/copyreloc-main1.rd
new file mode 100644
index 0000000..a6bd67c
--- /dev/null
+++ b/ld/testsuite/ld-i386/copyreloc-main1.rd
@@ -0,0 +1,3 @@
+#...
+[0-9a-f ]+R_386_COPY+[0-9a-f ]+ +a_glob
+#...
diff --git a/ld/testsuite/ld-i386/copyreloc-main2.rd b/ld/testsuite/ld-i386/copyreloc-main2.rd
new file mode 100644
index 0000000..ed61aa1
--- /dev/null
+++ b/ld/testsuite/ld-i386/copyreloc-main2.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_386_NONE.*
+#...
diff --git a/ld/testsuite/ld-i386/dummy.c b/ld/testsuite/ld-i386/dummy.c
new file mode 100644
index 0000000..5c03287
--- /dev/null
+++ b/ld/testsuite/ld-i386/dummy.c
@@ -0,0 +1 @@
+/* An empty file. */
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index f214d89..8399cbc 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -335,6 +335,78 @@ if { [isnative]
{{readelf {-Wr} plt-main.rd}} \
"plt-main" \
] \
+ [list \
+ "Build copyreloc-lib.so" \
+ "-shared" \
+ "-fPIC" \
+ { copyreloc-lib.c } \
+ {} \
+ "copyreloc-lib.so" \
+ ] \
+ [list \
+ "Build copyreloc-main with PIE and GOTOFF (1)" \
+ "tmpdir/copyreloc-lib.so -pie" \
+ "" \
+ { copyreloc-main.S } \
+ {{readelf {-Wr} copyreloc-main1.rd}} \
+ "copyreloc-main" \
+ ] \
+ [list \
+ "Build copyreloc-main with PIE and GOTOFF (2)" \
+ "tmpdir/copyreloc-lib.so -pie" \
+ "" \
+ { copyreloc-main.S } \
+ {{readelf {-Wr} copyreloc-main2.rd}} \
+ "copyreloc-main" \
+ ] \
+ [list \
+ "Build pr17689.so" \
+ "-shared" \
+ "-fPIC" \
+ { pr17689a.c } \
+ {} \
+ "pr17689.so" \
+ ] \
+ [list \
+ "Build pr17689ver.so" \
+ "-shared -Wl,--version-script,pr17689a.t" \
+ "-fPIC" \
+ { pr17689a.c } \
+ {} \
+ "pr17689ver.so" \
+ ] \
+ [list \
+ "Build pr17689.a" \
+ "" \
+ "" \
+ { pr17689b.S } \
+ {} \
+ "pr17689.a" \
+ ] \
+ [list \
+ "Build pr17689 with PIE and GOTOFF" \
+ "tmpdir/pr17689b.o tmpdir/pr17689.so -pie" \
+ "" \
+ { dummy.c } \
+ {{readelf {-Wr} pr17689.rd}} \
+ "pr17689" \
+ ] \
+ [list \
+ "Build pr17689ver with PIE and GOTOFF" \
+ "tmpdir/pr17689b.o tmpdir/pr17689ver.so -pie" \
+ "" \
+ { dummy.c } \
+ {{readelf {-Wr} pr17689ver.rd}} \
+ "pr17689ver" \
+ ] \
+ [list \
+ "Build pr17827 with PIE and GOTOFF" \
+ "tmpdir/pr17689b.o tmpdir/pr17689.so -pie" \
+ "" \
+ { dummy.c } \
+ {{readelf {-Wr} pr17827.rd}} \
+ "pr17827" \
+ ] \
]
run_ld_link_exec_tests [] [list \
@@ -357,5 +429,29 @@ if { [isnative]
"plt-main.out" \
"-fPIC" \
] \
+ [list \
+ "Run copyreloc-main with PIE and GOTOFF" \
+ "tmpdir/copyreloc-lib.so -pie" \
+ "" \
+ { copyreloc-main.S } \
+ "copyreloc-main" \
+ "copyreloc-main.out" \
+ ] \
+ [list \
+ "Run pr17689 with PIE and GOTOFF" \
+ "tmpdir/pr17689b.o tmpdir/pr17689.so -pie" \
+ "" \
+ { dummy.c } \
+ "pr17689" \
+ "pr17689.out" \
+ ] \
+ [list \
+ "Run pr17689ver with PIE and GOTOFF" \
+ "tmpdir/pr17689b.o tmpdir/pr17689ver.so -pie" \
+ "" \
+ { dummy.c } \
+ "pr17689ver" \
+ "pr17689.out" \
+ ] \
]
}
diff --git a/ld/testsuite/ld-i386/pr17689.out b/ld/testsuite/ld-i386/pr17689.out
new file mode 100644
index 0000000..38e0352
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr17689.out
@@ -0,0 +1,2 @@
+PASS
+PASS
diff --git a/ld/testsuite/ld-i386/pr17689.rd b/ld/testsuite/ld-i386/pr17689.rd
new file mode 100644
index 0000000..dda1850
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr17689.rd
@@ -0,0 +1,3 @@
+#...
+[0-9a-f ]+R_386_COPY+[0-9a-f ]+ +bar
+#...
diff --git a/ld/testsuite/ld-i386/pr17689a.c b/ld/testsuite/ld-i386/pr17689a.c
new file mode 100644
index 0000000..5317668
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr17689a.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+char *bar = "PASS";
+extern char *bar_alias __attribute__ ((weak, alias ("bar")));
+
+void
+foo (char *x)
+{
+ printf ("%s\n", x);
+}
diff --git a/ld/testsuite/ld-i386/pr17689a.t b/ld/testsuite/ld-i386/pr17689a.t
new file mode 100644
index 0000000..7f0efef
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr17689a.t
@@ -0,0 +1,6 @@
+VERSION {
+ global:
+ bar_alias; bar; foo;
+ local:
+ *;
+};
diff --git a/ld/testsuite/ld-i386/pr17689b.S b/ld/testsuite/ld-i386/pr17689b.S
new file mode 100644
index 0000000..24daf36
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr17689b.S
@@ -0,0 +1,44 @@
+ .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
+ pushl bar_alias@GOTOFF(%ebx)
+ call foo@PLT
+ popl %eax
+ movl ptr@GOTOFF(%ebx), %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
+ .globl ptr
+ .section .data.rel.local,"aw",@progbits
+ .align 4
+ .type ptr, @object
+ .size ptr, 4
+ptr:
+ .long bar_alias
+ .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-i386/pr17689ver.rd b/ld/testsuite/ld-i386/pr17689ver.rd
new file mode 100644
index 0000000..6cebe73
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr17689ver.rd
@@ -0,0 +1,3 @@
+#...
+[0-9a-f ]+R_386_COPY+[0-9a-f ]+ +bar@VERSION
+#...
diff --git a/ld/testsuite/ld-i386/pr17827.rd b/ld/testsuite/ld-i386/pr17827.rd
new file mode 100644
index 0000000..ed61aa1
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr17827.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_386_NONE.*
+#...