x86: Add _bfd_x86_elf_adjust_dynamic_symbol
Share _bfd_x86_elf_adjust_dynamic_symbol in elf32-i386.c and elf64-x86-64.c. * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Removed. (elf_backend_adjust_dynamic_symbol): Likewise. * elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol): Likewise. (elf_backend_adjust_dynamic_symbol): Likewise. * elfxx-x86.c (_bfd_x86_elf_adjust_dynamic_symbol): New function. (_bfd_x86_elf_link_setup_gnu_properties): Copy is_vxworks. * elfxx-x86.h (elf_x86_link_hash_table): Add is_vxworks. (_bfd_x86_elf_adjust_dynamic_symbol): New. (elf_backend_adjust_dynamic_symbol): Likewise.
This commit is contained in:
parent
18da07cd12
commit
eeb2f20a76
|
@ -1,3 +1,15 @@
|
||||||
|
2017-09-01 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* elf32-i386.c (elf_i386_adjust_dynamic_symbol): Removed.
|
||||||
|
(elf_backend_adjust_dynamic_symbol): Likewise.
|
||||||
|
* elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol): Likewise.
|
||||||
|
(elf_backend_adjust_dynamic_symbol): Likewise.
|
||||||
|
* elfxx-x86.c (_bfd_x86_elf_adjust_dynamic_symbol): New function.
|
||||||
|
(_bfd_x86_elf_link_setup_gnu_properties): Copy is_vxworks.
|
||||||
|
* elfxx-x86.h (elf_x86_link_hash_table): Add is_vxworks.
|
||||||
|
(_bfd_x86_elf_adjust_dynamic_symbol): New.
|
||||||
|
(elf_backend_adjust_dynamic_symbol): Likewise.
|
||||||
|
|
||||||
2017-09-01 H.J. Lu <hongjiu.lu@intel.com>
|
2017-09-01 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* elfxx-x86.h (elf_x86_plt_layout_table): Fix a typo in
|
* elfxx-x86.h (elf_x86_plt_layout_table): Fix a typo in
|
||||||
|
|
194
bfd/elf32-i386.c
194
bfd/elf32-i386.c
|
@ -1995,199 +1995,6 @@ elf_i386_gc_mark_hook (asection *sec,
|
||||||
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
|
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust a symbol defined by a dynamic object and referenced by a
|
|
||||||
regular object. The current definition is in some section of the
|
|
||||||
dynamic object, but we're not including those sections. We have to
|
|
||||||
change the definition to something the rest of the link can
|
|
||||||
understand. */
|
|
||||||
|
|
||||||
static bfd_boolean
|
|
||||||
elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|
||||||
struct elf_link_hash_entry *h)
|
|
||||||
{
|
|
||||||
struct elf_x86_link_hash_table *htab;
|
|
||||||
asection *s, *srel;
|
|
||||||
struct elf_x86_link_hash_entry *eh;
|
|
||||||
struct elf_dyn_relocs *p;
|
|
||||||
|
|
||||||
/* STT_GNU_IFUNC symbol must go through PLT. */
|
|
||||||
if (h->type == STT_GNU_IFUNC)
|
|
||||||
{
|
|
||||||
/* All local STT_GNU_IFUNC references must be treate as local
|
|
||||||
calls via local PLT. */
|
|
||||||
if (h->ref_regular
|
|
||||||
&& SYMBOL_CALLS_LOCAL (info, h))
|
|
||||||
{
|
|
||||||
bfd_size_type pc_count = 0, count = 0;
|
|
||||||
struct elf_dyn_relocs **pp;
|
|
||||||
|
|
||||||
eh = (struct elf_x86_link_hash_entry *) h;
|
|
||||||
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
|
||||||
{
|
|
||||||
pc_count += p->pc_count;
|
|
||||||
p->count -= p->pc_count;
|
|
||||||
p->pc_count = 0;
|
|
||||||
count += p->count;
|
|
||||||
if (p->count == 0)
|
|
||||||
*pp = p->next;
|
|
||||||
else
|
|
||||||
pp = &p->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pc_count || count)
|
|
||||||
{
|
|
||||||
h->non_got_ref = 1;
|
|
||||||
if (pc_count)
|
|
||||||
{
|
|
||||||
/* Increment PLT reference count only for PC-relative
|
|
||||||
references. */
|
|
||||||
h->needs_plt = 1;
|
|
||||||
if (h->plt.refcount <= 0)
|
|
||||||
h->plt.refcount = 1;
|
|
||||||
else
|
|
||||||
h->plt.refcount += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h->plt.refcount <= 0)
|
|
||||||
{
|
|
||||||
h->plt.offset = (bfd_vma) -1;
|
|
||||||
h->needs_plt = 0;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this is a function, put it in the procedure linkage table. We
|
|
||||||
will fill in the contents of the procedure linkage table later,
|
|
||||||
when we know the address of the .got section. */
|
|
||||||
if (h->type == STT_FUNC
|
|
||||||
|| h->needs_plt)
|
|
||||||
{
|
|
||||||
if (h->plt.refcount <= 0
|
|
||||||
|| SYMBOL_CALLS_LOCAL (info, h)
|
|
||||||
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
|
|
||||||
&& h->root.type == bfd_link_hash_undefweak))
|
|
||||||
{
|
|
||||||
/* This case can occur if we saw a PLT32 reloc in an input
|
|
||||||
file, but the symbol was never referred to by a dynamic
|
|
||||||
object, or if all references were garbage collected. In
|
|
||||||
such a case, we don't actually need to build a procedure
|
|
||||||
linkage table, and we can just do a PC32 reloc instead. */
|
|
||||||
h->plt.offset = (bfd_vma) -1;
|
|
||||||
h->needs_plt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* It's possible that we incorrectly decided a .plt reloc was
|
|
||||||
needed for an R_386_PC32 reloc to a non-function sym in
|
|
||||||
check_relocs. We can't decide accurately between function and
|
|
||||||
non-function syms in check-relocs; Objects loaded later in
|
|
||||||
the link may change h->type. So fix it now. */
|
|
||||||
h->plt.offset = (bfd_vma) -1;
|
|
||||||
|
|
||||||
eh = (struct elf_x86_link_hash_entry *) h;
|
|
||||||
|
|
||||||
/* If this is a weak symbol, and there is a real definition, the
|
|
||||||
processor independent code will have arranged for us to see the
|
|
||||||
real definition first, and we can just use the same value. */
|
|
||||||
if (h->u.weakdef != NULL)
|
|
||||||
{
|
|
||||||
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
|
|
||||||
|| h->u.weakdef->root.type == bfd_link_hash_defweak);
|
|
||||||
h->root.u.def.section = h->u.weakdef->root.u.def.section;
|
|
||||||
h->root.u.def.value = h->u.weakdef->root.u.def.value;
|
|
||||||
if (ELIMINATE_COPY_RELOCS
|
|
||||||
|| info->nocopyreloc
|
|
||||||
|| SYMBOL_NO_COPYRELOC (info, eh))
|
|
||||||
h->non_got_ref = h->u.weakdef->non_got_ref;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is a reference to a symbol defined by a dynamic object which
|
|
||||||
is not a function. */
|
|
||||||
|
|
||||||
/* If we are creating a shared library, we must presume that the
|
|
||||||
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 (!bfd_link_executable (info))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* If there are no references to this symbol that do not use the
|
|
||||||
GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
|
|
||||||
reloc. */
|
|
||||||
if (!h->non_got_ref && !eh->gotoff_ref)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* If -z nocopyreloc was given, we won't generate them either. */
|
|
||||||
if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
|
|
||||||
{
|
|
||||||
h->non_got_ref = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
htab = elf_x86_hash_table (info, I386_ELF_DATA);
|
|
||||||
if (htab == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* 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)->os != is_vxworks)
|
|
||||||
{
|
|
||||||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
|
||||||
{
|
|
||||||
s = p->sec->output_section;
|
|
||||||
if (s != NULL && (s->flags & SEC_READONLY) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
h->non_got_ref = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We must allocate the symbol in our .dynbss section, which will
|
|
||||||
become part of the .bss section of the executable. There will be
|
|
||||||
an entry for this symbol in the .dynsym section. The dynamic
|
|
||||||
object will contain position independent code, so all references
|
|
||||||
from the dynamic object to this symbol will go through the global
|
|
||||||
offset table. The dynamic linker will use the .dynsym entry to
|
|
||||||
determine the address it must put in the global offset table, so
|
|
||||||
both the dynamic object and the regular object will refer to the
|
|
||||||
same memory location for the variable. */
|
|
||||||
|
|
||||||
/* We must generate a R_386_COPY reloc to tell the dynamic linker to
|
|
||||||
copy the initial value out of the dynamic object and into the
|
|
||||||
runtime process image. */
|
|
||||||
if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
|
|
||||||
{
|
|
||||||
s = htab->elf.sdynrelro;
|
|
||||||
srel = htab->elf.sreldynrelro;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s = htab->elf.sdynbss;
|
|
||||||
srel = htab->elf.srelbss;
|
|
||||||
}
|
|
||||||
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
|
|
||||||
{
|
|
||||||
srel->size += sizeof (Elf32_External_Rel);
|
|
||||||
h->needs_copy = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _bfd_elf_adjust_dynamic_copy (info, h, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate space in .plt, .got and associated reloc sections for
|
/* Allocate space in .plt, .got and associated reloc sections for
|
||||||
dynamic relocs. */
|
dynamic relocs. */
|
||||||
|
|
||||||
|
@ -5876,7 +5683,6 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
|
||||||
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
|
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
|
||||||
#define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab
|
#define bfd_elf32_get_synthetic_symtab elf_i386_get_synthetic_symtab
|
||||||
|
|
||||||
#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol
|
|
||||||
#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible
|
#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible
|
||||||
#define elf_backend_check_relocs elf_i386_check_relocs
|
#define elf_backend_check_relocs elf_i386_check_relocs
|
||||||
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
|
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
|
||||||
|
|
|
@ -2435,199 +2435,6 @@ elf_x86_64_gc_mark_hook (asection *sec,
|
||||||
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
|
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust a symbol defined by a dynamic object and referenced by a
|
|
||||||
regular object. The current definition is in some section of the
|
|
||||||
dynamic object, but we're not including those sections. We have to
|
|
||||||
change the definition to something the rest of the link can
|
|
||||||
understand. */
|
|
||||||
|
|
||||||
static bfd_boolean
|
|
||||||
elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|
||||||
struct elf_link_hash_entry *h)
|
|
||||||
{
|
|
||||||
struct elf_x86_link_hash_table *htab;
|
|
||||||
asection *s, *srel;
|
|
||||||
struct elf_x86_link_hash_entry *eh;
|
|
||||||
struct elf_dyn_relocs *p;
|
|
||||||
|
|
||||||
/* STT_GNU_IFUNC symbol must go through PLT. */
|
|
||||||
if (h->type == STT_GNU_IFUNC)
|
|
||||||
{
|
|
||||||
/* All local STT_GNU_IFUNC references must be treate as local
|
|
||||||
calls via local PLT. */
|
|
||||||
if (h->ref_regular
|
|
||||||
&& SYMBOL_CALLS_LOCAL (info, h))
|
|
||||||
{
|
|
||||||
bfd_size_type pc_count = 0, count = 0;
|
|
||||||
struct elf_dyn_relocs **pp;
|
|
||||||
|
|
||||||
eh = (struct elf_x86_link_hash_entry *) h;
|
|
||||||
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
|
||||||
{
|
|
||||||
pc_count += p->pc_count;
|
|
||||||
p->count -= p->pc_count;
|
|
||||||
p->pc_count = 0;
|
|
||||||
count += p->count;
|
|
||||||
if (p->count == 0)
|
|
||||||
*pp = p->next;
|
|
||||||
else
|
|
||||||
pp = &p->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pc_count || count)
|
|
||||||
{
|
|
||||||
h->non_got_ref = 1;
|
|
||||||
if (pc_count)
|
|
||||||
{
|
|
||||||
/* Increment PLT reference count only for PC-relative
|
|
||||||
references. */
|
|
||||||
h->needs_plt = 1;
|
|
||||||
if (h->plt.refcount <= 0)
|
|
||||||
h->plt.refcount = 1;
|
|
||||||
else
|
|
||||||
h->plt.refcount += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h->plt.refcount <= 0)
|
|
||||||
{
|
|
||||||
h->plt.offset = (bfd_vma) -1;
|
|
||||||
h->needs_plt = 0;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this is a function, put it in the procedure linkage table. We
|
|
||||||
will fill in the contents of the procedure linkage table later,
|
|
||||||
when we know the address of the .got section. */
|
|
||||||
if (h->type == STT_FUNC
|
|
||||||
|| h->needs_plt)
|
|
||||||
{
|
|
||||||
if (h->plt.refcount <= 0
|
|
||||||
|| SYMBOL_CALLS_LOCAL (info, h)
|
|
||||||
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
|
|
||||||
&& h->root.type == bfd_link_hash_undefweak))
|
|
||||||
{
|
|
||||||
/* This case can occur if we saw a PLT32 reloc in an input
|
|
||||||
file, but the symbol was never referred to by a dynamic
|
|
||||||
object, or if all references were garbage collected. In
|
|
||||||
such a case, we don't actually need to build a procedure
|
|
||||||
linkage table, and we can just do a PC32 reloc instead. */
|
|
||||||
h->plt.offset = (bfd_vma) -1;
|
|
||||||
h->needs_plt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* It's possible that we incorrectly decided a .plt reloc was
|
|
||||||
needed for an R_X86_64_PC32 reloc to a non-function sym in
|
|
||||||
check_relocs. We can't decide accurately between function and
|
|
||||||
non-function syms in check-relocs; Objects loaded later in
|
|
||||||
the link may change h->type. So fix it now. */
|
|
||||||
h->plt.offset = (bfd_vma) -1;
|
|
||||||
|
|
||||||
eh = (struct elf_x86_link_hash_entry *) h;
|
|
||||||
|
|
||||||
/* If this is a weak symbol, and there is a real definition, the
|
|
||||||
processor independent code will have arranged for us to see the
|
|
||||||
real definition first, and we can just use the same value. */
|
|
||||||
if (h->u.weakdef != NULL)
|
|
||||||
{
|
|
||||||
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
|
|
||||||
|| h->u.weakdef->root.type == bfd_link_hash_defweak);
|
|
||||||
h->root.u.def.section = h->u.weakdef->root.u.def.section;
|
|
||||||
h->root.u.def.value = h->u.weakdef->root.u.def.value;
|
|
||||||
if (ELIMINATE_COPY_RELOCS
|
|
||||||
|| info->nocopyreloc
|
|
||||||
|| SYMBOL_NO_COPYRELOC (info, eh))
|
|
||||||
{
|
|
||||||
h->non_got_ref = h->u.weakdef->non_got_ref;
|
|
||||||
eh->needs_copy = h->u.weakdef->needs_copy;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is a reference to a symbol defined by a dynamic object which
|
|
||||||
is not a function. */
|
|
||||||
|
|
||||||
/* If we are creating a shared library, we must presume that the
|
|
||||||
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 (!bfd_link_executable (info))
|
|
||||||
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)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* If -z nocopyreloc was given, we won't generate them either. */
|
|
||||||
if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
|
|
||||||
{
|
|
||||||
h->non_got_ref = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ELIMINATE_COPY_RELOCS)
|
|
||||||
{
|
|
||||||
eh = (struct elf_x86_link_hash_entry *) h;
|
|
||||||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
|
||||||
{
|
|
||||||
s = p->sec->output_section;
|
|
||||||
if (s != NULL && (s->flags & SEC_READONLY) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we didn't find any dynamic relocs in read-only sections, then
|
|
||||||
we'll be keeping the dynamic relocs and avoiding the copy reloc. */
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
h->non_got_ref = 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We must allocate the symbol in our .dynbss section, which will
|
|
||||||
become part of the .bss section of the executable. There will be
|
|
||||||
an entry for this symbol in the .dynsym section. The dynamic
|
|
||||||
object will contain position independent code, so all references
|
|
||||||
from the dynamic object to this symbol will go through the global
|
|
||||||
offset table. The dynamic linker will use the .dynsym entry to
|
|
||||||
determine the address it must put in the global offset table, so
|
|
||||||
both the dynamic object and the regular object will refer to the
|
|
||||||
same memory location for the variable. */
|
|
||||||
|
|
||||||
htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
|
|
||||||
if (htab == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
|
|
||||||
to copy the initial value out of the dynamic object and into the
|
|
||||||
runtime process image. */
|
|
||||||
if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
|
|
||||||
{
|
|
||||||
s = htab->elf.sdynrelro;
|
|
||||||
srel = htab->elf.sreldynrelro;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s = htab->elf.sdynbss;
|
|
||||||
srel = htab->elf.srelbss;
|
|
||||||
}
|
|
||||||
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
|
|
||||||
{
|
|
||||||
const struct elf_backend_data *bed;
|
|
||||||
bed = get_elf_backend_data (info->output_bfd);
|
|
||||||
srel->size += bed->s->sizeof_rela;
|
|
||||||
h->needs_copy = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _bfd_elf_adjust_dynamic_copy (info, h, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate space in .plt, .got and associated reloc sections for
|
/* Allocate space in .plt, .got and associated reloc sections for
|
||||||
dynamic relocs. */
|
dynamic relocs. */
|
||||||
|
|
||||||
|
@ -6453,7 +6260,6 @@ elf_x86_64_special_sections[]=
|
||||||
#define bfd_elf64_bfd_reloc_name_lookup \
|
#define bfd_elf64_bfd_reloc_name_lookup \
|
||||||
elf_x86_64_reloc_name_lookup
|
elf_x86_64_reloc_name_lookup
|
||||||
|
|
||||||
#define elf_backend_adjust_dynamic_symbol elf_x86_64_adjust_dynamic_symbol
|
|
||||||
#define elf_backend_relocs_compatible elf_x86_64_relocs_compatible
|
#define elf_backend_relocs_compatible elf_x86_64_relocs_compatible
|
||||||
#define elf_backend_check_relocs elf_x86_64_check_relocs
|
#define elf_backend_check_relocs elf_x86_64_check_relocs
|
||||||
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
|
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
|
||||||
|
|
209
bfd/elfxx-x86.c
209
bfd/elfxx-x86.c
|
@ -539,6 +539,211 @@ _bfd_x86_elf_hash_symbol (struct elf_link_hash_entry *h)
|
||||||
return _bfd_elf_hash_symbol (h);
|
return _bfd_elf_hash_symbol (h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Adjust a symbol defined by a dynamic object and referenced by a
|
||||||
|
regular object. The current definition is in some section of the
|
||||||
|
dynamic object, but we're not including those sections. We have to
|
||||||
|
change the definition to something the rest of the link can
|
||||||
|
understand. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
_bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
||||||
|
struct elf_link_hash_entry *h)
|
||||||
|
{
|
||||||
|
struct elf_x86_link_hash_table *htab;
|
||||||
|
asection *s, *srel;
|
||||||
|
struct elf_x86_link_hash_entry *eh;
|
||||||
|
struct elf_dyn_relocs *p;
|
||||||
|
const struct elf_backend_data *bed
|
||||||
|
= get_elf_backend_data (info->output_bfd);
|
||||||
|
|
||||||
|
/* STT_GNU_IFUNC symbol must go through PLT. */
|
||||||
|
if (h->type == STT_GNU_IFUNC)
|
||||||
|
{
|
||||||
|
/* All local STT_GNU_IFUNC references must be treate as local
|
||||||
|
calls via local PLT. */
|
||||||
|
if (h->ref_regular
|
||||||
|
&& SYMBOL_CALLS_LOCAL (info, h))
|
||||||
|
{
|
||||||
|
bfd_size_type pc_count = 0, count = 0;
|
||||||
|
struct elf_dyn_relocs **pp;
|
||||||
|
|
||||||
|
eh = (struct elf_x86_link_hash_entry *) h;
|
||||||
|
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
|
||||||
|
{
|
||||||
|
pc_count += p->pc_count;
|
||||||
|
p->count -= p->pc_count;
|
||||||
|
p->pc_count = 0;
|
||||||
|
count += p->count;
|
||||||
|
if (p->count == 0)
|
||||||
|
*pp = p->next;
|
||||||
|
else
|
||||||
|
pp = &p->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc_count || count)
|
||||||
|
{
|
||||||
|
h->non_got_ref = 1;
|
||||||
|
if (pc_count)
|
||||||
|
{
|
||||||
|
/* Increment PLT reference count only for PC-relative
|
||||||
|
references. */
|
||||||
|
h->needs_plt = 1;
|
||||||
|
if (h->plt.refcount <= 0)
|
||||||
|
h->plt.refcount = 1;
|
||||||
|
else
|
||||||
|
h->plt.refcount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->plt.refcount <= 0)
|
||||||
|
{
|
||||||
|
h->plt.offset = (bfd_vma) -1;
|
||||||
|
h->needs_plt = 0;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is a function, put it in the procedure linkage table. We
|
||||||
|
will fill in the contents of the procedure linkage table later,
|
||||||
|
when we know the address of the .got section. */
|
||||||
|
if (h->type == STT_FUNC
|
||||||
|
|| h->needs_plt)
|
||||||
|
{
|
||||||
|
if (h->plt.refcount <= 0
|
||||||
|
|| SYMBOL_CALLS_LOCAL (info, h)
|
||||||
|
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
|
||||||
|
&& h->root.type == bfd_link_hash_undefweak))
|
||||||
|
{
|
||||||
|
/* This case can occur if we saw a PLT32 reloc in an input
|
||||||
|
file, but the symbol was never referred to by a dynamic
|
||||||
|
object, or if all references were garbage collected. In
|
||||||
|
such a case, we don't actually need to build a procedure
|
||||||
|
linkage table, and we can just do a PC32 reloc instead. */
|
||||||
|
h->plt.offset = (bfd_vma) -1;
|
||||||
|
h->needs_plt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* It's possible that we incorrectly decided a .plt reloc was needed
|
||||||
|
* for an R_386_PC32/R_X86_64_PC32 reloc to a non-function sym in
|
||||||
|
check_relocs. We can't decide accurately between function and
|
||||||
|
non-function syms in check-relocs; Objects loaded later in
|
||||||
|
the link may change h->type. So fix it now. */
|
||||||
|
h->plt.offset = (bfd_vma) -1;
|
||||||
|
|
||||||
|
eh = (struct elf_x86_link_hash_entry *) h;
|
||||||
|
|
||||||
|
/* If this is a weak symbol, and there is a real definition, the
|
||||||
|
processor independent code will have arranged for us to see the
|
||||||
|
real definition first, and we can just use the same value. */
|
||||||
|
if (h->u.weakdef != NULL)
|
||||||
|
{
|
||||||
|
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
|
||||||
|
|| h->u.weakdef->root.type == bfd_link_hash_defweak);
|
||||||
|
h->root.u.def.section = h->u.weakdef->root.u.def.section;
|
||||||
|
h->root.u.def.value = h->u.weakdef->root.u.def.value;
|
||||||
|
if (ELIMINATE_COPY_RELOCS
|
||||||
|
|| info->nocopyreloc
|
||||||
|
|| SYMBOL_NO_COPYRELOC (info, eh))
|
||||||
|
{
|
||||||
|
/* NB: needs_copy is always 0 for i386. */
|
||||||
|
h->non_got_ref = h->u.weakdef->non_got_ref;
|
||||||
|
eh->needs_copy = h->u.weakdef->needs_copy;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a reference to a symbol defined by a dynamic object which
|
||||||
|
is not a function. */
|
||||||
|
|
||||||
|
/* If we are creating a shared library, we must presume that the
|
||||||
|
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 (!bfd_link_executable (info))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* If there are no references to this symbol that do not use the
|
||||||
|
GOT nor R_386_GOTOFF relocation, we don't need to generate a copy
|
||||||
|
reloc. NB: gotoff_ref is always 0 for x86-64. */
|
||||||
|
if (!h->non_got_ref && !eh->gotoff_ref)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* If -z nocopyreloc was given, we won't generate them either. */
|
||||||
|
if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh))
|
||||||
|
{
|
||||||
|
h->non_got_ref = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
htab = elf_x86_hash_table (info, bed->target_id);
|
||||||
|
if (htab == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
&& (bed->target_id == X86_64_ELF_DATA
|
||||||
|
|| (!eh->gotoff_ref
|
||||||
|
&& !htab->is_vxworks)))
|
||||||
|
{
|
||||||
|
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||||
|
{
|
||||||
|
s = p->sec->output_section;
|
||||||
|
if (s != NULL && (s->flags & SEC_READONLY) != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we didn't find any dynamic relocs in read-only sections,
|
||||||
|
then we'll be keeping the dynamic relocs and avoiding the copy
|
||||||
|
reloc. */
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
h->non_got_ref = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must allocate the symbol in our .dynbss section, which will
|
||||||
|
become part of the .bss section of the executable. There will be
|
||||||
|
an entry for this symbol in the .dynsym section. The dynamic
|
||||||
|
object will contain position independent code, so all references
|
||||||
|
from the dynamic object to this symbol will go through the global
|
||||||
|
offset table. The dynamic linker will use the .dynsym entry to
|
||||||
|
determine the address it must put in the global offset table, so
|
||||||
|
both the dynamic object and the regular object will refer to the
|
||||||
|
same memory location for the variable. */
|
||||||
|
|
||||||
|
/* We must generate a R_386_COPY/R_X86_64_COPY reloc to tell the
|
||||||
|
dynamic linker to copy the initial value out of the dynamic object
|
||||||
|
and into the runtime process image. */
|
||||||
|
if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
|
||||||
|
{
|
||||||
|
s = htab->elf.sdynrelro;
|
||||||
|
srel = htab->elf.sreldynrelro;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s = htab->elf.sdynbss;
|
||||||
|
srel = htab->elf.srelbss;
|
||||||
|
}
|
||||||
|
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
|
||||||
|
{
|
||||||
|
srel->size += ((bed->target_id == I386_ELF_DATA)
|
||||||
|
? sizeof (Elf32_External_Rel)
|
||||||
|
: bed->s->sizeof_rela);
|
||||||
|
h->needs_copy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _bfd_elf_adjust_dynamic_copy (info, h, s);
|
||||||
|
}
|
||||||
|
|
||||||
static bfd_vma
|
static bfd_vma
|
||||||
elf_i386_get_plt_got_vma (struct elf_x86_plt *plt_p ATTRIBUTE_UNUSED,
|
elf_i386_get_plt_got_vma (struct elf_x86_plt *plt_p ATTRIBUTE_UNUSED,
|
||||||
bfd_vma off,
|
bfd_vma off,
|
||||||
|
@ -997,6 +1202,8 @@ error_alignment:
|
||||||
if (htab == NULL)
|
if (htab == NULL)
|
||||||
return pbfd;
|
return pbfd;
|
||||||
|
|
||||||
|
htab->is_vxworks = plt_layout->is_vxworks;
|
||||||
|
|
||||||
use_ibt_plt = info->ibtplt || info->ibt;
|
use_ibt_plt = info->ibtplt || info->ibt;
|
||||||
if (!use_ibt_plt && pbfd != NULL)
|
if (!use_ibt_plt && pbfd != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1119,7 +1326,7 @@ error_alignment:
|
||||||
if (dynobj == NULL)
|
if (dynobj == NULL)
|
||||||
return pbfd;
|
return pbfd;
|
||||||
|
|
||||||
if (plt_layout->is_vxworks
|
if (htab->is_vxworks
|
||||||
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
|
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
|
||||||
&htab->srelplt2))
|
&htab->srelplt2))
|
||||||
{
|
{
|
||||||
|
|
|
@ -287,6 +287,9 @@ struct elf_x86_link_hash_table
|
||||||
to read-only sections. */
|
to read-only sections. */
|
||||||
bfd_boolean readonly_dynrelocs_against_ifunc;
|
bfd_boolean readonly_dynrelocs_against_ifunc;
|
||||||
|
|
||||||
|
/* TRUE if this is a VxWorks x86 target. */
|
||||||
|
bfd_boolean is_vxworks;
|
||||||
|
|
||||||
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks.
|
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks.
|
||||||
This is used for i386 only. */
|
This is used for i386 only. */
|
||||||
asection *srelplt2;
|
asection *srelplt2;
|
||||||
|
@ -416,6 +419,9 @@ extern bfd_boolean _bfd_x86_elf_fixup_symbol
|
||||||
extern bfd_boolean _bfd_x86_elf_hash_symbol
|
extern bfd_boolean _bfd_x86_elf_hash_symbol
|
||||||
(struct elf_link_hash_entry *);
|
(struct elf_link_hash_entry *);
|
||||||
|
|
||||||
|
extern bfd_boolean _bfd_x86_elf_adjust_dynamic_symbol
|
||||||
|
(struct bfd_link_info *, struct elf_link_hash_entry *);
|
||||||
|
|
||||||
extern long _bfd_x86_elf_get_synthetic_symtab
|
extern long _bfd_x86_elf_get_synthetic_symtab
|
||||||
(bfd *, long, long, bfd_vma, struct elf_x86_plt [], asymbol **,
|
(bfd *, long, long, bfd_vma, struct elf_x86_plt [], asymbol **,
|
||||||
asymbol **);
|
asymbol **);
|
||||||
|
@ -452,6 +458,8 @@ extern bfd * _bfd_x86_elf_link_setup_gnu_properties
|
||||||
_bfd_x86_elf_fixup_symbol
|
_bfd_x86_elf_fixup_symbol
|
||||||
#define elf_backend_hash_symbol \
|
#define elf_backend_hash_symbol \
|
||||||
_bfd_x86_elf_hash_symbol
|
_bfd_x86_elf_hash_symbol
|
||||||
|
#define elf_backend_adjust_dynamic_symbol \
|
||||||
|
_bfd_x86_elf_adjust_dynamic_symbol
|
||||||
#define elf_backend_omit_section_dynsym \
|
#define elf_backend_omit_section_dynsym \
|
||||||
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
|
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
|
||||||
#define elf_backend_parse_gnu_properties \
|
#define elf_backend_parse_gnu_properties \
|
||||||
|
|
Loading…
Reference in New Issue