From 631d040f80d99b7b993abd77c9d064fa8bccd711 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 2 Dec 2014 15:14:28 -0800 Subject: [PATCH] X86-64: Allow copy relocs for building PIE This patch allows copy relocs for non-GOT pc-relative relocation in PIE. bfd/ * elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Always allow copy relocs for building executables. (elf_x86_64_adjust_dynamic_symbol): Allocate copy relocs for PIE. (elf_x86_64_allocate_dynrelocs): For PIE, discard space for relocs against symbols which turn out to need copy relocs. (elf_x86_64_relocate_section): Don't copy a pc-relative relocation into the output file if the symbol needs copy reloc. ld/testsuite/ * ld-x86-64/copyreloc-lib.c: New file. * ld-x86-64/copyreloc-main.c: Likewise. * ld-x86-64/copyreloc-main.out: Likewise. * ld-x86-64/copyreloc-main1.rd: Likewise. * ld-x86-64/copyreloc-main2.rd: Likewise. * ld-x86-64/x86-64.exp: Run copyreloc tests. --- bfd/ChangeLog | 25 +++++++++++ bfd/elf64-x86-64.c | 71 ++++++++++++++++++++++--------- ld/testsuite/ChangeLog | 10 +++++ ld/testsuite/ld-x86-64/copyreloc-lib.c | 1 + ld/testsuite/ld-x86-64/copyreloc-main.c | 7 +++ ld/testsuite/ld-x86-64/copyreloc-main.out | 0 ld/testsuite/ld-x86-64/copyreloc-main1.rd | 3 ++ ld/testsuite/ld-x86-64/copyreloc-main2.rd | 4 ++ ld/testsuite/ld-x86-64/x86-64.exp | 38 +++++++++++++++++ 9 files changed, 139 insertions(+), 20 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/copyreloc-lib.c create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main.c create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main.out create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main1.rd create mode 100644 ld/testsuite/ld-x86-64/copyreloc-main2.rd diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c35c522..681759e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,28 @@ +2014-12-02 H.J. Lu + + * elf64-x86-64.c (elf_x86_64_relocate_section): Check + info->executable for symbols which need copy relocs. + +2014-12-02 H.J. Lu + + * elf64-x86-64.c (elf_x86_64_check_relocs): Revert the last + change. + (elf_x86_64_adjust_dynamic_symbol): Don't check !info->shared + with ELIMINATE_COPY_RELOCS. + (elf_x86_64_allocate_dynrelocs): For PIE, discard space for + relocs against symbols which turn out to need copy relocs. + +2014-12-02 H.J. Lu + + * elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Always + allow copy relocs for building executables. + (elf_x86_64_check_relocs): Allow copy relocs for non-GOT + pc-relative relocation in shared object. + (elf_x86_64_adjust_dynamic_symbol): Allocate copy relocs for + PIE. + (elf_x86_64_relocate_section): Don't copy a pc-relative + relocation into the output file if the symbol needs copy reloc. + 2014-11-30 Alan Modra PR 16452, 16457 diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 3881f60..fb27f0d 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1053,13 +1053,29 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj, return FALSE; htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); - if (!info->shared) - htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); - - if (!htab->sdynbss - || (!info->shared && !htab->srelbss)) + if (!htab->sdynbss) abort (); + if (info->executable) + { + /* Always allow copy relocs for building executables. */ + asection *s; + s = bfd_get_linker_section (dynobj, ".rela.bss"); + if (s == NULL) + { + const struct elf_backend_data *bed = get_elf_backend_data (dynobj); + s = bfd_make_section_anyway_with_flags (dynobj, + ".rela.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 (!info->no_ld_generated_unwind_info && htab->plt_eh_frame == NULL && htab->elf.splt != NULL) @@ -2343,7 +2359,7 @@ elf_x86_64_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 @@ -2636,20 +2652,28 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) /* Also discard relocs on undefined weak syms with non-default visibility. */ - if (eh->dyn_relocs != NULL - && h->root.type == bfd_link_hash_undefweak) + if (eh->dyn_relocs != NULL) { - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + if (h->root.type == bfd_link_hash_undefweak) + { + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + eh->dyn_relocs = NULL; + + /* Make sure undefined weak symbols are output as a dynamic + symbol in PIEs. */ + else if (h->dynindx == -1 + && ! h->forced_local + && ! 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. */ + else if (info->executable + && h->needs_copy + && h->def_dynamic + && !h->def_regular) eh->dyn_relocs = NULL; - - /* Make sure undefined weak symbols are output as a dynamic - symbol in PIEs. */ - else if (h->dynindx == -1 - && ! h->forced_local - && ! bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; } - } else if (ELIMINATE_COPY_RELOCS) { @@ -3962,10 +3986,11 @@ elf_x86_64_relocate_section (bfd *output_bfd, defined locally or for a branch. */ fail = !h->def_regular && !branch; } - else + else if (!(info->executable && h->needs_copy)) { - /* Symbol isn't referenced locally. We only allow - branch to symbol with non-default visibility. */ + /* Symbol doesn't need copy reloc and isn't referenced + locally. We only allow branch to symbol with + non-default visibility. */ fail = (!branch || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT); } @@ -4019,7 +4044,13 @@ direct: if ((input_section->flags & SEC_ALLOC) == 0) break; + /* Don't copy a pc-relative relocation into the output file + if the symbol needs copy reloc. */ if ((info->shared + && !(info->executable + && h != NULL + && h->needs_copy + && IS_X86_64_PCREL_TYPE (r_type)) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 881f5ce..d00586d 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2014-12-02 H.J. Lu + + * ld-x86-64/copyreloc-lib.c: New file. + * ld-x86-64/copyreloc-main.c: Likewise. + * ld-x86-64/copyreloc-main.out: Likewise. + * ld-x86-64/copyreloc-main1.rd: Likewise. + * ld-x86-64/copyreloc-main2.rd: Likewise. + + * ld-x86-64/x86-64.exp: Run copyreloc tests. + 2014-12-01 H.J. Lu PR ld/16452 diff --git a/ld/testsuite/ld-x86-64/copyreloc-lib.c b/ld/testsuite/ld-x86-64/copyreloc-lib.c new file mode 100644 index 0000000..cbbc5e2 --- /dev/null +++ b/ld/testsuite/ld-x86-64/copyreloc-lib.c @@ -0,0 +1 @@ +int a_glob = 2; diff --git a/ld/testsuite/ld-x86-64/copyreloc-main.c b/ld/testsuite/ld-x86-64/copyreloc-main.c new file mode 100644 index 0000000..430eefb --- /dev/null +++ b/ld/testsuite/ld-x86-64/copyreloc-main.c @@ -0,0 +1,7 @@ +extern int a_glob; + +int +main (void) +{ + return a_glob != 2; +} diff --git a/ld/testsuite/ld-x86-64/copyreloc-main.out b/ld/testsuite/ld-x86-64/copyreloc-main.out new file mode 100644 index 0000000..e69de29 diff --git a/ld/testsuite/ld-x86-64/copyreloc-main1.rd b/ld/testsuite/ld-x86-64/copyreloc-main1.rd new file mode 100644 index 0000000..dcb52dc --- /dev/null +++ b/ld/testsuite/ld-x86-64/copyreloc-main1.rd @@ -0,0 +1,3 @@ +#... +[0-9a-f ]+R_X86_64_COPY+[0-9a-f ]+ +a_glob \+ 0 +#... diff --git a/ld/testsuite/ld-x86-64/copyreloc-main2.rd b/ld/testsuite/ld-x86-64/copyreloc-main2.rd new file mode 100644 index 0000000..d78ea2f --- /dev/null +++ b/ld/testsuite/ld-x86-64/copyreloc-main2.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 54786a7..c8d105b 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -331,4 +331,42 @@ if { [isnative] && [which $CC] != 0 } { "-shared -melf32_x86_64 tmpdir/simple-x32.o" "" "--x32" {dummy.s} {{readelf {-s --wide} x86-64-x32.rd}} "x86-64-x32"} } + + run_cc_link_tests [list \ + [list \ + "Build copyreloc-lib.so" \ + "-shared" \ + "-fPIC" \ + { copyreloc-lib.c } \ + {} \ + "copyreloc-lib.so" \ + ] \ + [list \ + "Build copyreloc-main with PIE without -fPIE (1)" \ + "tmpdir/copyreloc-lib.so -pie" \ + "" \ + { copyreloc-main.c } \ + {{readelf {-Wr} copyreloc-main1.rd}} \ + "copyreloc-main" \ + ] \ + [list \ + "Build copyreloc-main with PIE without -fPIE (2)" \ + "tmpdir/copyreloc-lib.so -pie" \ + "" \ + { copyreloc-main.c } \ + {{readelf {-Wr} copyreloc-main2.rd}} \ + "copyreloc-main" \ + ] \ + ] + + run_ld_link_exec_tests [] [list \ + [list \ + "Run copyreloc-main with PIE without -fPIE" \ + "tmpdir/copyreloc-lib.so -pie" \ + "" \ + { copyreloc-main.c } \ + "copyreloc-main" \ + "copyreloc-main.out" \ + ] \ + ] } -- 2.7.4