* 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:
Alexandre Oliva 2004-02-24 16:39:01 +00:00
parent 74aee4eb9f
commit 072c89031a
2 changed files with 148 additions and 112 deletions

View File

@ -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

View File

@ -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