* elf32-frv.c (FRV_SYM_LOCAL): Weak undefined doesn't imply local.
(_frv_emit_got_relocs_plt_entries): Decay relocation to protected function's descriptor to symbol+offset, and map local undefweak symbol to NULL function descriptor. (elf32_frv_relocate_section): Likewise.
This commit is contained in:
parent
74aee4eb9f
commit
072c89031a
|
@ -1,3 +1,11 @@
|
|||
2004-02-24 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* elf32-frv.c (FRV_SYM_LOCAL): Weak undefined doesn't imply local.
|
||||
(_frv_emit_got_relocs_plt_entries): Decay relocation to protected
|
||||
function's descriptor to symbol+offset, and map local undefweak
|
||||
symbol to NULL function descriptor.
|
||||
(elf32_frv_relocate_section): Likewise.
|
||||
|
||||
2004-02-23 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* libaout.h (enum machine_type): Add M_SPARC64_NETBSD and
|
||||
|
|
252
bfd/elf32-frv.c
252
bfd/elf32-frv.c
|
@ -659,7 +659,6 @@ frv_elf_link_hash_table_create (bfd *abfd)
|
|||
#define FRV_SYM_LOCAL(INFO, H) \
|
||||
(_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
|
||||
|| ! elf_hash_table (INFO)->dynamic_sections_created \
|
||||
|| (H)->root.type == bfd_link_hash_undefweak \
|
||||
|| (/* The condition below is an ugly hack to get .scommon data to
|
||||
be regarded as local. For some reason the
|
||||
ELF_LINK_HASH_DEF_REGULAR bit is not set on such common
|
||||
|
@ -1029,46 +1028,60 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
if (entry->fdgot_entry)
|
||||
{
|
||||
int reloc, idx;
|
||||
bfd_vma ad;
|
||||
bfd_vma ad = 0;
|
||||
|
||||
/* If the symbol is dynamic and there may be dynamic symbol
|
||||
resolution because we are or are linked with a shared
|
||||
library, emit a FUNCDESC relocation such that the dynamic
|
||||
linker will allocate the function descriptor. */
|
||||
if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h))
|
||||
if (! (entry->symndx == -1
|
||||
&& entry->d.h->root.type == bfd_link_hash_undefweak
|
||||
&& FRV_SYM_LOCAL (info, entry->d.h)))
|
||||
{
|
||||
reloc = R_FRV_FUNCDESC;
|
||||
idx = dynindx;
|
||||
ad = addend;
|
||||
if (ad)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we know we have a private function descriptor,
|
||||
so reference it directly. */
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
BFD_ASSERT (entry->privfd);
|
||||
reloc = R_FRV_32;
|
||||
idx = elf_section_data (frv_got_section (info)->output_section)
|
||||
->dynindx;
|
||||
ad = frv_got_section (info)->output_offset +
|
||||
frv_got_initial_offset (info) + entry->fd_entry;
|
||||
}
|
||||
|
||||
/* If there is room for dynamic symbol resolution, emit the
|
||||
dynamic relocation. However, if we're linking an executable
|
||||
at a fixed location, we won't have emitted a dynamic symbol
|
||||
entry for the got section, so idx will be zero, which means
|
||||
we can and should compute the address of the private
|
||||
descriptor ourselves. */
|
||||
if (info->executable && !info->pie
|
||||
&& (entry->symndx != -1 || FRV_FUNCDESC_LOCAL (info, entry->d.h)))
|
||||
{
|
||||
if (entry->symndx == -1
|
||||
&& entry->d.h->root.type == bfd_link_hash_undefweak)
|
||||
ad = 0;
|
||||
/* If the symbol is dynamic and there may be dynamic symbol
|
||||
resolution because we are, or are linked with, a shared
|
||||
library, emit a FUNCDESC relocation such that the dynamic
|
||||
linker will allocate the function descriptor. If the
|
||||
symbol needs a non-local function descriptor but binds
|
||||
locally (e.g., its visibility is protected, emit a
|
||||
dynamic relocation decayed to section+offset. */
|
||||
if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h)
|
||||
&& FRV_SYM_LOCAL (info, entry->d.h)
|
||||
&& !(info->executable && !info->pie))
|
||||
{
|
||||
reloc = R_FRV_FUNCDESC;
|
||||
idx = elf_section_data (entry->d.h->root.u.def.section
|
||||
->output_section)->dynindx;
|
||||
ad = entry->d.h->root.u.def.section->output_offset
|
||||
+ entry->d.h->root.u.def.value;
|
||||
}
|
||||
else if (entry->symndx == -1
|
||||
&& ! FRV_FUNCDESC_LOCAL (info, entry->d.h))
|
||||
{
|
||||
reloc = R_FRV_FUNCDESC;
|
||||
idx = dynindx;
|
||||
ad = addend;
|
||||
if (ad)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we know we have a private function descriptor,
|
||||
so reference it directly. */
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
BFD_ASSERT (entry->privfd);
|
||||
reloc = R_FRV_32;
|
||||
idx = elf_section_data (frv_got_section (info)
|
||||
->output_section)->dynindx;
|
||||
ad = frv_got_section (info)->output_offset
|
||||
+ frv_got_initial_offset (info) + entry->fd_entry;
|
||||
}
|
||||
|
||||
/* If there is room for dynamic symbol resolution, emit the
|
||||
dynamic relocation. However, if we're linking an
|
||||
executable at a fixed location, we won't have emitted a
|
||||
dynamic symbol entry for the got section, so idx will be
|
||||
zero, which means we can and should compute the address
|
||||
of the private descriptor ourselves. */
|
||||
if (info->executable && !info->pie
|
||||
&& (entry->symndx != -1
|
||||
|| FRV_FUNCDESC_LOCAL (info, entry->d.h)))
|
||||
{
|
||||
ad += frv_got_section (info)->output_section->vma;
|
||||
_frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
|
||||
|
@ -1077,17 +1090,17 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
+ frv_got_initial_offset (info)
|
||||
+ entry->fdgot_entry);
|
||||
}
|
||||
else
|
||||
_frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
|
||||
_bfd_elf_section_offset
|
||||
(output_bfd, info,
|
||||
frv_got_section (info),
|
||||
frv_got_initial_offset (info)
|
||||
+ entry->fdgot_entry)
|
||||
+ frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset,
|
||||
reloc, idx, ad);
|
||||
}
|
||||
else
|
||||
_frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
|
||||
_bfd_elf_section_offset
|
||||
(output_bfd, info,
|
||||
frv_got_section (info),
|
||||
frv_got_initial_offset (info)
|
||||
+ entry->fdgot_entry)
|
||||
+ frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset,
|
||||
reloc, idx, ad);
|
||||
|
||||
bfd_put_32 (output_bfd, ad,
|
||||
frv_got_section (info)->contents
|
||||
|
@ -2005,89 +2018,104 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
int dynindx;
|
||||
bfd_vma addend = rel->r_addend;
|
||||
|
||||
/* If the symbol is dynamic and there may be dynamic
|
||||
symbol resolution because we are or are linked with a
|
||||
shared library, emit a FUNCDESC relocation such that
|
||||
the dynamic linker will allocate the function
|
||||
descriptor. */
|
||||
if (h && ! FRV_FUNCDESC_LOCAL (info, h))
|
||||
if (! (h && h->root.type == bfd_link_hash_undefweak
|
||||
&& FRV_SYM_LOCAL (info, h)))
|
||||
{
|
||||
if (addend)
|
||||
/* If the symbol is dynamic and there may be dynamic
|
||||
symbol resolution because we are or are linked with a
|
||||
shared library, emit a FUNCDESC relocation such that
|
||||
the dynamic linker will allocate the function
|
||||
descriptor. If the symbol needs a non-local function
|
||||
descriptor but binds locally (e.g., its visibility is
|
||||
protected, emit a dynamic relocation decayed to
|
||||
section+offset. */
|
||||
if (h && ! FRV_FUNCDESC_LOCAL (info, h)
|
||||
&& FRV_SYM_LOCAL (info, h)
|
||||
&& !(info->executable && !info->pie))
|
||||
{
|
||||
info->callbacks->warning
|
||||
(info, _("R_FRV_FUNCDESC references dynamic symbol with nonzero addend"),
|
||||
name, input_bfd, input_section, rel->r_offset);
|
||||
return FALSE;
|
||||
dynindx = elf_section_data (h->root.u.def.section
|
||||
->output_section)->dynindx;
|
||||
addend += h->root.u.def.section->output_offset
|
||||
+ h->root.u.def.value;
|
||||
}
|
||||
else if (h && ! FRV_FUNCDESC_LOCAL (info, h))
|
||||
{
|
||||
if (addend)
|
||||
{
|
||||
info->callbacks->warning
|
||||
(info, _("R_FRV_FUNCDESC references dynamic symbol with nonzero addend"),
|
||||
name, input_bfd, input_section, rel->r_offset);
|
||||
return FALSE;
|
||||
}
|
||||
dynindx = h->dynindx;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we know we have a private function
|
||||
descriptor, so reference it directly. */
|
||||
BFD_ASSERT (picrel->privfd);
|
||||
r_type = R_FRV_32;
|
||||
dynindx = elf_section_data (frv_got_section (info)
|
||||
->output_section)->dynindx;
|
||||
addend = frv_got_section (info)->output_offset
|
||||
+ frv_got_initial_offset (info)
|
||||
+ picrel->fd_entry;
|
||||
}
|
||||
dynindx = h->dynindx;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we know we have a private function
|
||||
descriptor, so reference it directly. */
|
||||
BFD_ASSERT (picrel->privfd);
|
||||
r_type = R_FRV_32;
|
||||
dynindx = elf_section_data (frv_got_section
|
||||
(info)->output_section)->dynindx;
|
||||
addend = frv_got_section (info)->output_offset
|
||||
+ frv_got_initial_offset (info)
|
||||
+ picrel->fd_entry;
|
||||
}
|
||||
|
||||
/* If there is room for dynamic symbol resolution, emit
|
||||
the dynamic relocation. However, if we're linking an
|
||||
executable at a fixed location, we won't have emitted a
|
||||
dynamic symbol entry for the got section, so idx will
|
||||
be zero, which means we can and should compute the
|
||||
address of the private descriptor ourselves. */
|
||||
if (info->executable && !info->pie
|
||||
&& (!h || FRV_FUNCDESC_LOCAL (info, h)))
|
||||
{
|
||||
addend += frv_got_section (info)->output_section->vma;
|
||||
if ((bfd_get_section_flags (output_bfd,
|
||||
input_section->output_section)
|
||||
& (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
|
||||
/* If there is room for dynamic symbol resolution, emit
|
||||
the dynamic relocation. However, if we're linking an
|
||||
executable at a fixed location, we won't have emitted a
|
||||
dynamic symbol entry for the got section, so idx will
|
||||
be zero, which means we can and should compute the
|
||||
address of the private descriptor ourselves. */
|
||||
if (info->executable && !info->pie
|
||||
&& (!h || FRV_FUNCDESC_LOCAL (info, h)))
|
||||
{
|
||||
addend += frv_got_section (info)->output_section->vma;
|
||||
if ((bfd_get_section_flags (output_bfd,
|
||||
input_section->output_section)
|
||||
& (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
|
||||
{
|
||||
if (_frv_osec_readonly_p (output_bfd,
|
||||
input_section->output_section))
|
||||
{
|
||||
info->callbacks->warning
|
||||
(info,
|
||||
_("cannot emit fixups in read-only section"),
|
||||
name, input_bfd, input_section, rel->r_offset);
|
||||
return FALSE;
|
||||
}
|
||||
_frv_add_rofixup (output_bfd,
|
||||
frv_gotfixup_section (info),
|
||||
_bfd_elf_section_offset
|
||||
(output_bfd, info,
|
||||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset);
|
||||
}
|
||||
}
|
||||
else if ((bfd_get_section_flags (output_bfd,
|
||||
input_section->output_section)
|
||||
& (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
|
||||
{
|
||||
if (_frv_osec_readonly_p (output_bfd,
|
||||
input_section->output_section))
|
||||
{
|
||||
info->callbacks->warning
|
||||
(info,
|
||||
_("cannot emit fixups in read-only section"),
|
||||
_("cannot emit dynamic relocations in read-only section"),
|
||||
name, input_bfd, input_section, rel->r_offset);
|
||||
return FALSE;
|
||||
}
|
||||
if (! h || h->root.type != bfd_link_hash_undefweak)
|
||||
_frv_add_rofixup (output_bfd,
|
||||
frv_gotfixup_section (info),
|
||||
_frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
|
||||
_bfd_elf_section_offset
|
||||
(output_bfd, info,
|
||||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset);
|
||||
+ input_section->output_offset,
|
||||
r_type, dynindx, addend);
|
||||
}
|
||||
}
|
||||
else if ((bfd_get_section_flags (output_bfd,
|
||||
input_section->output_section)
|
||||
& (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
|
||||
{
|
||||
if (_frv_osec_readonly_p (output_bfd,
|
||||
input_section->output_section))
|
||||
{
|
||||
info->callbacks->warning
|
||||
(info,
|
||||
_("cannot emit dynamic relocations in read-only section"),
|
||||
name, input_bfd, input_section, rel->r_offset);
|
||||
return FALSE;
|
||||
}
|
||||
_frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
|
||||
_bfd_elf_section_offset
|
||||
(output_bfd, info,
|
||||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
r_type, dynindx, addend);
|
||||
}
|
||||
|
||||
/* We want the addend in-place because dynamic
|
||||
relocations are REL. Setting relocation to it should
|
||||
|
|
Loading…
Reference in New Issue