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>
|
||||
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
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_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_check_relocs elf_i386_check_relocs
|
||||
#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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
dynamic relocs. */
|
||||
|
||||
|
@ -6453,7 +6260,6 @@ elf_x86_64_special_sections[]=
|
|||
#define bfd_elf64_bfd_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_check_relocs elf_x86_64_check_relocs
|
||||
#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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
elf_i386_get_plt_got_vma (struct elf_x86_plt *plt_p ATTRIBUTE_UNUSED,
|
||||
bfd_vma off,
|
||||
|
@ -997,6 +1202,8 @@ error_alignment:
|
|||
if (htab == NULL)
|
||||
return pbfd;
|
||||
|
||||
htab->is_vxworks = plt_layout->is_vxworks;
|
||||
|
||||
use_ibt_plt = info->ibtplt || info->ibt;
|
||||
if (!use_ibt_plt && pbfd != NULL)
|
||||
{
|
||||
|
@ -1119,7 +1326,7 @@ error_alignment:
|
|||
if (dynobj == NULL)
|
||||
return pbfd;
|
||||
|
||||
if (plt_layout->is_vxworks
|
||||
if (htab->is_vxworks
|
||||
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
|
||||
&htab->srelplt2))
|
||||
{
|
||||
|
|
|
@ -287,6 +287,9 @@ struct elf_x86_link_hash_table
|
|||
to read-only sections. */
|
||||
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.
|
||||
This is used for i386 only. */
|
||||
asection *srelplt2;
|
||||
|
@ -416,6 +419,9 @@ extern bfd_boolean _bfd_x86_elf_fixup_symbol
|
|||
extern bfd_boolean _bfd_x86_elf_hash_symbol
|
||||
(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
|
||||
(bfd *, long, long, bfd_vma, struct elf_x86_plt [], asymbol **,
|
||||
asymbol **);
|
||||
|
@ -452,6 +458,8 @@ extern bfd * _bfd_x86_elf_link_setup_gnu_properties
|
|||
_bfd_x86_elf_fixup_symbol
|
||||
#define elf_backend_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 \
|
||||
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
|
||||
#define elf_backend_parse_gnu_properties \
|
||||
|
|
Loading…
Reference in New Issue