* 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> 2004-02-23 Mark Kettenis <kettenis@gnu.org>
* libaout.h (enum machine_type): Add M_SPARC64_NETBSD and * 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) \ #define FRV_SYM_LOCAL(INFO, H) \
(_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \ (_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
|| ! elf_hash_table (INFO)->dynamic_sections_created \ || ! 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 || (/* The condition below is an ugly hack to get .scommon data to
be regarded as local. For some reason the be regarded as local. For some reason the
ELF_LINK_HASH_DEF_REGULAR bit is not set on such common 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) if (entry->fdgot_entry)
{ {
int reloc, idx; int reloc, idx;
bfd_vma ad; bfd_vma ad = 0;
/* If the symbol is dynamic and there may be dynamic symbol if (! (entry->symndx == -1
resolution because we are or are linked with a shared && entry->d.h->root.type == bfd_link_hash_undefweak
library, emit a FUNCDESC relocation such that the dynamic && FRV_SYM_LOCAL (info, entry->d.h)))
linker will allocate the function descriptor. */
if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h))
{ {
reloc = R_FRV_FUNCDESC; /* If the symbol is dynamic and there may be dynamic symbol
idx = dynindx; resolution because we are, or are linked with, a shared
ad = addend; library, emit a FUNCDESC relocation such that the dynamic
if (ad) linker will allocate the function descriptor. If the
return FALSE; symbol needs a non-local function descriptor but binds
} locally (e.g., its visibility is protected, emit a
else dynamic relocation decayed to section+offset. */
{ if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h)
/* Otherwise, we know we have a private function descriptor, && FRV_SYM_LOCAL (info, entry->d.h)
so reference it directly. */ && !(info->executable && !info->pie))
if (elf_hash_table (info)->dynamic_sections_created) {
BFD_ASSERT (entry->privfd); reloc = R_FRV_FUNCDESC;
reloc = R_FRV_32; idx = elf_section_data (entry->d.h->root.u.def.section
idx = elf_section_data (frv_got_section (info)->output_section) ->output_section)->dynindx;
->dynindx; ad = entry->d.h->root.u.def.section->output_offset
ad = frv_got_section (info)->output_offset + + entry->d.h->root.u.def.value;
frv_got_initial_offset (info) + entry->fd_entry; }
} else if (entry->symndx == -1
&& ! FRV_FUNCDESC_LOCAL (info, entry->d.h))
/* If there is room for dynamic symbol resolution, emit the {
dynamic relocation. However, if we're linking an executable reloc = R_FRV_FUNCDESC;
at a fixed location, we won't have emitted a dynamic symbol idx = dynindx;
entry for the got section, so idx will be zero, which means ad = addend;
we can and should compute the address of the private if (ad)
descriptor ourselves. */ return FALSE;
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;
else 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; ad += frv_got_section (info)->output_section->vma;
_frv_add_rofixup (output_bfd, frv_gotfixup_section (info), _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) + frv_got_initial_offset (info)
+ entry->fdgot_entry); + 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, bfd_put_32 (output_bfd, ad,
frv_got_section (info)->contents frv_got_section (info)->contents
@ -2005,89 +2018,104 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
int dynindx; int dynindx;
bfd_vma addend = rel->r_addend; bfd_vma addend = rel->r_addend;
/* If the symbol is dynamic and there may be dynamic if (! (h && h->root.type == bfd_link_hash_undefweak
symbol resolution because we are or are linked with a && FRV_SYM_LOCAL (info, h)))
shared library, emit a FUNCDESC relocation such that
the dynamic linker will allocate the function
descriptor. */
if (h && ! FRV_FUNCDESC_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 dynindx = elf_section_data (h->root.u.def.section
(info, _("R_FRV_FUNCDESC references dynamic symbol with nonzero addend"), ->output_section)->dynindx;
name, input_bfd, input_section, rel->r_offset); addend += h->root.u.def.section->output_offset
return FALSE; + 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 /* If there is room for dynamic symbol resolution, emit
the dynamic relocation. However, if we're linking an the dynamic relocation. However, if we're linking an
executable at a fixed location, we won't have emitted a executable at a fixed location, we won't have emitted a
dynamic symbol entry for the got section, so idx will dynamic symbol entry for the got section, so idx will
be zero, which means we can and should compute the be zero, which means we can and should compute the
address of the private descriptor ourselves. */ address of the private descriptor ourselves. */
if (info->executable && !info->pie if (info->executable && !info->pie
&& (!h || FRV_FUNCDESC_LOCAL (info, h))) && (!h || FRV_FUNCDESC_LOCAL (info, h)))
{ {
addend += frv_got_section (info)->output_section->vma; addend += frv_got_section (info)->output_section->vma;
if ((bfd_get_section_flags (output_bfd, if ((bfd_get_section_flags (output_bfd,
input_section->output_section) input_section->output_section)
& (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD)) & (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, if (_frv_osec_readonly_p (output_bfd,
input_section->output_section)) input_section->output_section))
{ {
info->callbacks->warning info->callbacks->warning
(info, (info,
_("cannot emit fixups in read-only section"), _("cannot emit dynamic relocations in read-only section"),
name, input_bfd, input_section, rel->r_offset); name, input_bfd, input_section, rel->r_offset);
return FALSE; return FALSE;
} }
if (! h || h->root.type != bfd_link_hash_undefweak) _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
_frv_add_rofixup (output_bfd,
frv_gotfixup_section (info),
_bfd_elf_section_offset _bfd_elf_section_offset
(output_bfd, info, (output_bfd, info,
input_section, rel->r_offset) input_section, rel->r_offset)
+ input_section->output_section->vma + 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 /* We want the addend in-place because dynamic
relocations are REL. Setting relocation to it should relocations are REL. Setting relocation to it should