mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-26 11:33:45 +08:00
Check ELF relocs after opening all input files
Delaying checking ELF relocations until opening all input files so that symbol information is final when relocations are checked. This is only enabled for x86 targets. bfd/ * 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. include/ * bfdlink.h (bfd_link_info): Add check_relocs_after_open_input. ld/ * 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.
This commit is contained in:
parent
6885166d99
commit
d968975277
@ -1,3 +1,10 @@
|
|||||||
|
2016-04-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* 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 <tbsaunde+binutils@tbsaunde.org>
|
2016-04-20 Trevor Saunders <tbsaunde+binutils@tbsaunde.org>
|
||||||
|
|
||||||
* cache.c: Update old style function definitions.
|
* cache.c: Update old style function definitions.
|
||||||
|
@ -2261,6 +2261,8 @@ extern bfd_boolean bfd_elf_link_add_symbols
|
|||||||
(bfd *, struct bfd_link_info *);
|
(bfd *, struct bfd_link_info *);
|
||||||
extern bfd_boolean _bfd_elf_add_dynamic_entry
|
extern bfd_boolean _bfd_elf_add_dynamic_entry
|
||||||
(struct bfd_link_info *, bfd_vma, bfd_vma);
|
(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
|
extern bfd_boolean bfd_elf_link_record_dynamic_symbol
|
||||||
(struct bfd_link_info *, struct elf_link_hash_entry *);
|
(struct bfd_link_info *, struct elf_link_hash_entry *);
|
||||||
|
117
bfd/elflink.c
117
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);
|
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. */
|
/* Add symbols from an ELF object file to the linker hash table. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
@ -4950,57 +5013,9 @@ error_free_dyn:
|
|||||||
&& !(*bed->check_directives) (abfd, info))
|
&& !(*bed->check_directives) (abfd, info))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* If this object is the same format as the output object, and it is
|
if (!info->check_relocs_after_open_input
|
||||||
not a shared library, then let the backend look through the
|
&& !_bfd_elf_link_check_relocs (abfd, info))
|
||||||
relocs.
|
return FALSE;
|
||||||
|
|
||||||
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 this is a non-traditional link, try to optimize the handling
|
/* If this is a non-traditional link, try to optimize the handling
|
||||||
of the .stab/.stabstr sections. */
|
of the .stab/.stabstr sections. */
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2016-04-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* bfdlink.h (bfd_link_info): Add check_relocs_after_open_input.
|
||||||
|
|
||||||
2016-04-20 Andrew Burgess <andrew.burgess@embecosm.com>
|
2016-04-20 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||||
|
|
||||||
* elf/arc-reloc.def (ARC_NPS_CMEM16): Add ME modifier to formula.
|
* elf/arc-reloc.def (ARC_NPS_CMEM16): Add ME modifier to formula.
|
||||||
|
@ -440,6 +440,10 @@ struct bfd_link_info
|
|||||||
/* TRUE if the linker script contained an explicit PHDRS command. */
|
/* TRUE if the linker script contained an explicit PHDRS command. */
|
||||||
unsigned int user_phdrs: 1;
|
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. */
|
/* TRUE if BND prefix in PLT entries is always generated. */
|
||||||
unsigned int bndplt: 1;
|
unsigned int bndplt: 1;
|
||||||
|
|
||||||
|
25
ld/ChangeLog
25
ld/ChangeLog
@ -1,3 +1,28 @@
|
|||||||
|
2016-04-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* 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 <hongjiu.lu@intel.com>
|
2016-04-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* testsuite/ld-elf/eh6.s: Replace .long with .dc.a on
|
* testsuite/ld-elf/eh6.s: Replace .long with .dc.a on
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
SCRIPT_NAME=elf
|
SCRIPT_NAME=elf
|
||||||
ELFSIZE=32
|
ELFSIZE=32
|
||||||
OUTPUT_FORMAT="elf32-x86-64"
|
OUTPUT_FORMAT="elf32-x86-64"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
NO_REL_RELOCS=yes
|
NO_REL_RELOCS=yes
|
||||||
TEXT_START_ADDR=0x400000
|
TEXT_START_ADDR=0x400000
|
||||||
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
. ${srcdir}/emulparams/call_nop.sh
|
. ${srcdir}/emulparams/call_nop.sh
|
||||||
SCRIPT_NAME=elf
|
SCRIPT_NAME=elf
|
||||||
OUTPUT_FORMAT="elf32-i386"
|
OUTPUT_FORMAT="elf32-i386"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
NO_RELA_RELOCS=yes
|
NO_RELA_RELOCS=yes
|
||||||
TEXT_START_ADDR=0x08048000
|
TEXT_START_ADDR=0x08048000
|
||||||
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
. ${srcdir}/emulparams/call_nop.sh
|
. ${srcdir}/emulparams/call_nop.sh
|
||||||
SCRIPT_NAME=elf
|
SCRIPT_NAME=elf
|
||||||
OUTPUT_FORMAT="elf32-i386"
|
OUTPUT_FORMAT="elf32-i386"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
NO_RELA_RELOCS=yes
|
NO_RELA_RELOCS=yes
|
||||||
TEXT_START_ADDR=0x80000000
|
TEXT_START_ADDR=0x80000000
|
||||||
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
. ${srcdir}/emulparams/call_nop.sh
|
. ${srcdir}/emulparams/call_nop.sh
|
||||||
SCRIPT_NAME=elf_chaos
|
SCRIPT_NAME=elf_chaos
|
||||||
OUTPUT_FORMAT="elf32-i386"
|
OUTPUT_FORMAT="elf32-i386"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
TEXT_START_ADDR=0x40000000
|
TEXT_START_ADDR=0x40000000
|
||||||
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
||||||
ARCH=i386
|
ARCH=i386
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
. ${srcdir}/emulparams/call_nop.sh
|
. ${srcdir}/emulparams/call_nop.sh
|
||||||
SCRIPT_NAME=elf
|
SCRIPT_NAME=elf
|
||||||
OUTPUT_FORMAT="elf32-i386"
|
OUTPUT_FORMAT="elf32-i386"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
NO_RELA_RELOCS=yes
|
NO_RELA_RELOCS=yes
|
||||||
TEXT_START_ADDR=0x08048000
|
TEXT_START_ADDR=0x08048000
|
||||||
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
SCRIPT_NAME=elf
|
SCRIPT_NAME=elf
|
||||||
OUTPUT_FORMAT="elf32-i386-vxworks"
|
OUTPUT_FORMAT="elf32-i386-vxworks"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
NO_RELA_RELOCS=yes
|
NO_RELA_RELOCS=yes
|
||||||
TEXT_START_ADDR=0x08048000
|
TEXT_START_ADDR=0x08048000
|
||||||
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
SCRIPT_NAME=elf
|
SCRIPT_NAME=elf
|
||||||
ELFSIZE=64
|
ELFSIZE=64
|
||||||
OUTPUT_FORMAT="elf64-x86-64"
|
OUTPUT_FORMAT="elf64-x86-64"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
NO_REL_RELOCS=yes
|
NO_REL_RELOCS=yes
|
||||||
TEXT_START_ADDR=0x400000
|
TEXT_START_ADDR=0x400000
|
||||||
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
SCRIPT_NAME=elf
|
SCRIPT_NAME=elf
|
||||||
OUTPUT_FORMAT="elf32-i386"
|
OUTPUT_FORMAT="elf32-i386"
|
||||||
|
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
|
||||||
NO_RELA_RELOCS=yes
|
NO_RELA_RELOCS=yes
|
||||||
TEXT_START_ADDR=0x08048000
|
TEXT_START_ADDR=0x08048000
|
||||||
TEXT_START_SYMBOLS='_btext = .;'
|
TEXT_START_SYMBOLS='_btext = .;'
|
||||||
|
@ -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.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`;
|
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`;
|
`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
|
EOF
|
||||||
@ -1025,6 +1026,20 @@ gld${EMULATION_NAME}_after_open (void)
|
|||||||
if (!is_elf_hash_table (htab))
|
if (!is_elf_hash_table (htab))
|
||||||
return;
|
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)
|
if (emit_note_gnu_build_id != NULL)
|
||||||
{
|
{
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
|
Loading…
Reference in New Issue
Block a user