diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f4bebd9d28..a0304b682a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2016-04-20 H.J. Lu + + * elf-bfd.h (_bfd_elf_link_check_relocs): New. + * elflink.c (_bfd_elf_link_check_relocs): New function. + (elf_link_add_object_symbols): Call _bfd_elf_link_check_relocs + if check_relocs_after_open_input is FALSE. + 2016-04-20 Trevor Saunders * cache.c: Update old style function definitions. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 5c93d78c39..5dce70e93d 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2261,6 +2261,8 @@ extern bfd_boolean bfd_elf_link_add_symbols (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_elf_add_dynamic_entry (struct bfd_link_info *, bfd_vma, bfd_vma); +extern bfd_boolean _bfd_elf_link_check_relocs + (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *); diff --git a/bfd/elflink.c b/bfd/elflink.c index 37638b2f2c..5af334ad17 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3480,6 +3480,69 @@ _bfd_elf_notice_as_needed (bfd *ibfd, return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0); } +/* Check relocations an ELF object file. */ + +bfd_boolean +_bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct elf_link_hash_table *htab = elf_hash_table (info); + + /* If this object is the same format as the output object, and it is + not a shared library, then let the backend look through the + relocs. + + This is required to build global offset table entries and to + arrange for dynamic relocs. It is not required for the + particular common case of linking non PIC code, even when linking + against shared libraries, but unfortunately there is no way of + knowing whether an object file has been compiled PIC or not. + Looking through the relocs is not particularly time consuming. + The problem is that we must either (1) keep the relocs in memory, + which causes the linker to require additional runtime memory or + (2) read the relocs twice from the input file, which wastes time. + This would be a good case for using mmap. + + I have no idea how to handle linking PIC code into a file of a + different format. It probably can't be done. */ + if ((abfd->flags & DYNAMIC) == 0 + && is_elf_hash_table (htab) + && bed->check_relocs != NULL + && elf_object_id (abfd) == elf_hash_table_id (htab) + && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) + { + asection *o; + + for (o = abfd->sections; o != NULL; o = o->next) + { + Elf_Internal_Rela *internal_relocs; + bfd_boolean ok; + + if ((o->flags & SEC_RELOC) == 0 + || o->reloc_count == 0 + || ((info->strip == strip_all || info->strip == strip_debugger) + && (o->flags & SEC_DEBUGGING) != 0) + || bfd_is_abs_section (o->output_section)) + continue; + + internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, + info->keep_memory); + if (internal_relocs == NULL) + return FALSE; + + ok = (*bed->check_relocs) (abfd, info, o, internal_relocs); + + if (elf_section_data (o)->relocs != internal_relocs) + free (internal_relocs); + + if (! ok) + return FALSE; + } + } + + return TRUE; +} + /* Add symbols from an ELF object file to the linker hash table. */ static bfd_boolean @@ -4950,57 +5013,9 @@ error_free_dyn: && !(*bed->check_directives) (abfd, info)) return FALSE; - /* If this object is the same format as the output object, and it is - not a shared library, then let the backend look through the - relocs. - - This is required to build global offset table entries and to - arrange for dynamic relocs. It is not required for the - particular common case of linking non PIC code, even when linking - against shared libraries, but unfortunately there is no way of - knowing whether an object file has been compiled PIC or not. - Looking through the relocs is not particularly time consuming. - The problem is that we must either (1) keep the relocs in memory, - which causes the linker to require additional runtime memory or - (2) read the relocs twice from the input file, which wastes time. - This would be a good case for using mmap. - - I have no idea how to handle linking PIC code into a file of a - different format. It probably can't be done. */ - if (! dynamic - && is_elf_hash_table (htab) - && bed->check_relocs != NULL - && elf_object_id (abfd) == elf_hash_table_id (htab) - && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) - { - asection *o; - - for (o = abfd->sections; o != NULL; o = o->next) - { - Elf_Internal_Rela *internal_relocs; - bfd_boolean ok; - - if ((o->flags & SEC_RELOC) == 0 - || o->reloc_count == 0 - || ((info->strip == strip_all || info->strip == strip_debugger) - && (o->flags & SEC_DEBUGGING) != 0) - || bfd_is_abs_section (o->output_section)) - continue; - - internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, - info->keep_memory); - if (internal_relocs == NULL) - goto error_return; - - ok = (*bed->check_relocs) (abfd, info, o, internal_relocs); - - if (elf_section_data (o)->relocs != internal_relocs) - free (internal_relocs); - - if (! ok) - goto error_return; - } - } + if (!info->check_relocs_after_open_input + && !_bfd_elf_link_check_relocs (abfd, info)) + return FALSE; /* If this is a non-traditional link, try to optimize the handling of the .stab/.stabstr sections. */ diff --git a/include/ChangeLog b/include/ChangeLog index c4bc144675..a419ef2279 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2016-04-20 H.J. Lu + + * bfdlink.h (bfd_link_info): Add check_relocs_after_open_input. + 2016-04-20 Andrew Burgess * elf/arc-reloc.def (ARC_NPS_CMEM16): Add ME modifier to formula. diff --git a/include/bfdlink.h b/include/bfdlink.h index a285f6dc5e..90467b54ed 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -440,6 +440,10 @@ struct bfd_link_info /* TRUE if the linker script contained an explicit PHDRS command. */ unsigned int user_phdrs: 1; + /* TRUE if we should check relocations after all input files have + been opened. */ + unsigned int check_relocs_after_open_input: 1; + /* TRUE if BND prefix in PLT entries is always generated. */ unsigned int bndplt: 1; diff --git a/ld/ChangeLog b/ld/ChangeLog index c1dc58948c..ac908e5239 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,28 @@ +2016-04-20 H.J. Lu + + * emulparams/elf32_x86_64.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + New. + * emulparams/elf_i386.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + Likewise. + * emulparams/elf_i386_be.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + Likewise. + * emulparams/elf_i386_chaos.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + Likewise. + * emulparams/elf_i386_ldso.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + Likewise. + * emulparams/elf_i386_vxworks.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + Likewise. + * emulparams/elf_x86_64.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + Likewise. + * emulparams/i386nto.sh (CHECK_RELOCS_AFTER_OPEN_INPUT): + Likewise. + * emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): + Set check_relocs_after_open_input to TRUE if + CHECK_RELOCS_AFTER_OPEN_INPUT is yes. + (gld${EMULATION_NAME}_after_open): Call + _bfd_elf_link_check_relocs on all inputs if + check_relocs_after_open_input is TRUE. + 2016-04-20 H.J. Lu * testsuite/ld-elf/eh6.s: Replace .long with .dc.a on diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh index 967c1b45cd..9050730834 100644 --- a/ld/emulparams/elf32_x86_64.sh +++ b/ld/emulparams/elf32_x86_64.sh @@ -6,6 +6,7 @@ SCRIPT_NAME=elf ELFSIZE=32 OUTPUT_FORMAT="elf32-x86-64" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes NO_REL_RELOCS=yes TEXT_START_ADDR=0x400000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh index 3451bb2b1e..b08e6610d0 100644 --- a/ld/emulparams/elf_i386.sh +++ b/ld/emulparams/elf_i386.sh @@ -4,6 +4,7 @@ . ${srcdir}/emulparams/call_nop.sh SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes NO_RELA_RELOCS=yes TEXT_START_ADDR=0x08048000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" diff --git a/ld/emulparams/elf_i386_be.sh b/ld/emulparams/elf_i386_be.sh index 70db443239..4a24b02012 100644 --- a/ld/emulparams/elf_i386_be.sh +++ b/ld/emulparams/elf_i386_be.sh @@ -3,6 +3,7 @@ . ${srcdir}/emulparams/call_nop.sh SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes NO_RELA_RELOCS=yes TEXT_START_ADDR=0x80000000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" diff --git a/ld/emulparams/elf_i386_chaos.sh b/ld/emulparams/elf_i386_chaos.sh index aa36cb51c2..5349108174 100644 --- a/ld/emulparams/elf_i386_chaos.sh +++ b/ld/emulparams/elf_i386_chaos.sh @@ -4,6 +4,7 @@ . ${srcdir}/emulparams/call_nop.sh SCRIPT_NAME=elf_chaos OUTPUT_FORMAT="elf32-i386" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes TEXT_START_ADDR=0x40000000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" ARCH=i386 diff --git a/ld/emulparams/elf_i386_ldso.sh b/ld/emulparams/elf_i386_ldso.sh index 1328520c57..dc4eef4889 100644 --- a/ld/emulparams/elf_i386_ldso.sh +++ b/ld/emulparams/elf_i386_ldso.sh @@ -4,6 +4,7 @@ . ${srcdir}/emulparams/call_nop.sh SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes NO_RELA_RELOCS=yes TEXT_START_ADDR=0x08048000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" diff --git a/ld/emulparams/elf_i386_vxworks.sh b/ld/emulparams/elf_i386_vxworks.sh index aaea8c4874..ac1bbeb4e3 100644 --- a/ld/emulparams/elf_i386_vxworks.sh +++ b/ld/emulparams/elf_i386_vxworks.sh @@ -1,5 +1,6 @@ SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386-vxworks" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes NO_RELA_RELOCS=yes TEXT_START_ADDR=0x08048000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh index e935f90d7e..6055204874 100644 --- a/ld/emulparams/elf_x86_64.sh +++ b/ld/emulparams/elf_x86_64.sh @@ -6,6 +6,7 @@ SCRIPT_NAME=elf ELFSIZE=64 OUTPUT_FORMAT="elf64-x86-64" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes NO_REL_RELOCS=yes TEXT_START_ADDR=0x400000 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" diff --git a/ld/emulparams/i386nto.sh b/ld/emulparams/i386nto.sh index 626f9c13aa..51284be2bd 100644 --- a/ld/emulparams/i386nto.sh +++ b/ld/emulparams/i386nto.sh @@ -1,5 +1,6 @@ SCRIPT_NAME=elf OUTPUT_FORMAT="elf32-i386" +CHECK_RELOCS_AFTER_OPEN_INPUT=yes NO_RELA_RELOCS=yes TEXT_START_ADDR=0x08048000 TEXT_START_SYMBOLS='_btext = .;' diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 3e9f684985..312f935e6a 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -104,6 +104,7 @@ gld${EMULATION_NAME}_before_parse (void) config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`; config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`; `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`; + link_info.check_relocs_after_open_input = `if test "x${CHECK_RELOCS_AFTER_OPEN_INPUT}" = xyes ; then echo TRUE ; else echo FALSE ; fi`; } EOF @@ -1025,6 +1026,20 @@ gld${EMULATION_NAME}_after_open (void) if (!is_elf_hash_table (htab)) return; + if (link_info.check_relocs_after_open_input) + { + bfd *abfd; + + for (abfd = link_info.input_bfds; + abfd != (bfd *) NULL; abfd = abfd->link.next) + if (!_bfd_elf_link_check_relocs (abfd, &link_info)) + { + /* no object output, fail return */ + config.make_executable = FALSE; + return; + } + } + if (emit_note_gnu_build_id != NULL) { bfd *abfd;