forked from Imagelibrary/binutils-gdb
x86: Properly handle __ehdr_start
After _bfd_i386_elf_convert_load and _bfd_x86_64_elf_convert_load are removed, elf_i386_convert_load_reloc and elf_x86_64_convert_load_reloc see __ehdr_start as an undefined symbol when they are called from check_relocs to convert GOT relocations against local symbols. But __ehdr_start will be defined as a hidden symbol by linker at the later stage if it is referenced. This patch marks __ehdr_start as a defined local symbol at the start of check_relocs if it is referenced and not defined. bfd/ PR ld/22115 * elf32-i386.c (elf_i386_convert_load_reloc): Check linker_def. Don't use UNDEFINED_WEAK_RESOLVED_TO_ZERO. * elf64-x86-64.c (elf_x86_64_convert_load_reloc): Check linker_def. Don't use UNDEFINED_WEAK_RESOLVED_TO_ZERO. * elfxx-x86.c (_bfd_x86_elf_link_check_relocs): Set local_ref and linker_def on __ehdr_start if it is referenced and not defined. (_bfd_x86_elf_link_symbol_references_local): Also set local_ref and return TRUE when building executable, if a symbol has non-GOT/non-PLT relocations in text section or there is no dynamic linker. * elfxx-x86.h (elf_x86_link_hash_entry): Add linker_def. ld/ PR ld/22115 * ld-i386/i386.exp: Run PR ld/22115 tests, * ld/testsuite/ld-x86-64/x86-64.exp: Likewise. * testsuite/ld-i386/pr22115-1.s: New file. * testsuite/ld-i386/pr22115-1a.d: Likewise. * testsuite/ld-i386/pr22115-1b.d: Likewise. * testsuite/ld-i386/pr22115-1c.d: Likewise. * testsuite/ld-i386/pr22115-1d.d: Likewise. * testsuite/ld-x86-64/pr22115-1.s: Likewise. * testsuite/ld-x86-64/pr22115-1a-x32.d: Likewise. * testsuite/ld-x86-64/pr22115-1a.d: Likewise. * testsuite/ld-x86-64/pr22115-1b-x32.d: Likewise. * testsuite/ld-x86-64/pr22115-1b.d: Likewise. * testsuite/ld-x86-64/pr22115-1c-x32.d: Likewise. * testsuite/ld-x86-64/pr22115-1c.d: Likewise. * testsuite/ld-x86-64/pr22115-1d-x32.d: Likewise. * testsuite/ld-x86-64/pr22115-1d.d: Likewise.
This commit is contained in:
@@ -1229,6 +1229,8 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
||||
unsigned int r_type;
|
||||
unsigned int r_symndx;
|
||||
bfd_vma roff = irel->r_offset;
|
||||
bfd_boolean local_ref;
|
||||
struct elf_x86_link_hash_entry *eh;
|
||||
|
||||
if (roff < 2)
|
||||
return TRUE;
|
||||
@@ -1276,6 +1278,8 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
||||
register. */
|
||||
to_reloc_32 = !is_pic || baseless;
|
||||
|
||||
eh = elf_x86_hash_entry (h);
|
||||
|
||||
/* Try to convert R_386_GOT32X. Get the symbol referred to by the
|
||||
reloc. */
|
||||
if (h == NULL)
|
||||
@@ -1290,10 +1294,14 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
||||
goto convert_load;
|
||||
}
|
||||
|
||||
/* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */
|
||||
local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
|
||||
|
||||
/* Undefined weak symbol is only bound locally in executable
|
||||
and its reference is resolved as 0. */
|
||||
if (UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, I386_ELF_DATA, TRUE,
|
||||
elf_x86_hash_entry (h)))
|
||||
if (h->root.type == bfd_link_hash_undefweak
|
||||
&& !eh->linker_def
|
||||
&& local_ref)
|
||||
{
|
||||
if (opcode == 0xff)
|
||||
{
|
||||
@@ -1316,16 +1324,13 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
||||
/* We have "call/jmp *foo@GOT[(%reg)]". */
|
||||
if ((h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (link_info, h))
|
||||
&& local_ref)
|
||||
{
|
||||
/* The function is locally defined. */
|
||||
convert_branch:
|
||||
/* Convert R_386_GOT32X to R_386_PC32. */
|
||||
if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
|
||||
{
|
||||
struct elf_x86_link_hash_entry *eh
|
||||
= (struct elf_x86_link_hash_entry *) h;
|
||||
|
||||
/* Convert to "nop call foo". ADDR_PREFIX_OPCODE
|
||||
is a nop prefix. */
|
||||
modrm = 0xe8;
|
||||
@@ -1381,10 +1386,11 @@ convert_branch:
|
||||
bfd_elf_record_link_assignment. start_stop is set on
|
||||
__start_SECNAME/__stop_SECNAME which mark section SECNAME. */
|
||||
if (h->start_stop
|
||||
|| eh->linker_def
|
||||
|| ((h->def_regular
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (link_info, h)))
|
||||
&& local_ref))
|
||||
{
|
||||
convert_load:
|
||||
if (opcode == 0x8b)
|
||||
|
||||
Reference in New Issue
Block a user