* 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,13 +1028,31 @@ _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 (! (entry->symndx == -1
&& entry->d.h->root.type == bfd_link_hash_undefweak
&& FRV_SYM_LOCAL (info, entry->d.h)))
{
/* If the symbol is dynamic and there may be dynamic symbol /* If the symbol is dynamic and there may be dynamic symbol
resolution because we are or are linked with a shared resolution because we are, or are linked with, a shared
library, emit a FUNCDESC relocation such that the dynamic library, emit a FUNCDESC relocation such that the dynamic
linker will allocate the function descriptor. */ linker will allocate the function descriptor. If the
if (entry->symndx == -1 && ! FRV_FUNCDESC_LOCAL (info, entry->d.h)) 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; reloc = R_FRV_FUNCDESC;
idx = dynindx; idx = dynindx;
@ -1050,25 +1067,21 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
if (elf_hash_table (info)->dynamic_sections_created) if (elf_hash_table (info)->dynamic_sections_created)
BFD_ASSERT (entry->privfd); BFD_ASSERT (entry->privfd);
reloc = R_FRV_32; reloc = R_FRV_32;
idx = elf_section_data (frv_got_section (info)->output_section) idx = elf_section_data (frv_got_section (info)
->dynindx; ->output_section)->dynindx;
ad = frv_got_section (info)->output_offset + ad = frv_got_section (info)->output_offset
frv_got_initial_offset (info) + entry->fd_entry; + frv_got_initial_offset (info) + entry->fd_entry;
} }
/* If there is room for dynamic symbol resolution, emit the /* If there is room for dynamic symbol resolution, emit the
dynamic relocation. However, if we're linking an executable dynamic relocation. However, if we're linking an
at a fixed location, we won't have emitted a dynamic symbol executable at a fixed location, we won't have emitted a
entry for the got section, so idx will be zero, which means dynamic symbol entry for the got section, so idx will be
we can and should compute the address of the private zero, which means we can and should compute the address
descriptor ourselves. */ of the private descriptor ourselves. */
if (info->executable && !info->pie if (info->executable && !info->pie
&& (entry->symndx != -1 || FRV_FUNCDESC_LOCAL (info, entry->d.h))) && (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
{ {
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,7 +1090,6 @@ _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 else
_frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info), _frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
_bfd_elf_section_offset _bfd_elf_section_offset
@ -1088,6 +1100,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
+ frv_got_section (info)->output_section->vma + frv_got_section (info)->output_section->vma
+ frv_got_section (info)->output_offset, + frv_got_section (info)->output_offset,
reloc, idx, ad); 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,12 +2018,27 @@ 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 (! (h && h->root.type == bfd_link_hash_undefweak
&& FRV_SYM_LOCAL (info, h)))
{
/* If the symbol is dynamic and there may be dynamic /* If the symbol is dynamic and there may be dynamic
symbol resolution because we are or are linked with a symbol resolution because we are or are linked with a
shared library, emit a FUNCDESC relocation such that shared library, emit a FUNCDESC relocation such that
the dynamic linker will allocate the function the dynamic linker will allocate the function
descriptor. */ descriptor. If the symbol needs a non-local function
if (h && ! FRV_FUNCDESC_LOCAL (info, h)) 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))
{
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) if (addend)
{ {
@ -2027,8 +2055,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
descriptor, so reference it directly. */ descriptor, so reference it directly. */
BFD_ASSERT (picrel->privfd); BFD_ASSERT (picrel->privfd);
r_type = R_FRV_32; r_type = R_FRV_32;
dynindx = elf_section_data (frv_got_section dynindx = elf_section_data (frv_got_section (info)
(info)->output_section)->dynindx; ->output_section)->dynindx;
addend = frv_got_section (info)->output_offset addend = frv_got_section (info)->output_offset
+ frv_got_initial_offset (info) + frv_got_initial_offset (info)
+ picrel->fd_entry; + picrel->fd_entry;
@ -2057,7 +2085,6 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_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_rofixup (output_bfd, _frv_add_rofixup (output_bfd,
frv_gotfixup_section (info), frv_gotfixup_section (info),
_bfd_elf_section_offset _bfd_elf_section_offset
@ -2088,6 +2115,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
+ input_section->output_offset, + input_section->output_offset,
r_type, dynindx, addend); 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