From 072c89031ac1a43428f4984f4895d891ebc95026 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Tue, 24 Feb 2004 16:39:01 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 8 ++ bfd/elf32-frv.c | 252 +++++++++++++++++++++++++++--------------------- 2 files changed, 148 insertions(+), 112 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index bde4f4fbf1..0ccab082a5 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2004-02-24 Alexandre Oliva + + * 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 * libaout.h (enum machine_type): Add M_SPARC64_NETBSD and diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c index 488438e59b..b8c325f1b0 100644 --- a/bfd/elf32-frv.c +++ b/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