diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 13270c1f9d..789137a3ee 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,26 @@ +Mon Aug 14 11:39:24 1995 Ian Lance Taylor + + * elflink.h (elf_link_add_object_symbols): If a symbol is a weak + definition, add it to the dynamic symbol table if any dynamic + object mentions it. If we do add it, make sure we add the + corresponding real symbol. + (elf_adjust_dynamic_symbol): Adjust a weak defined symbol which we + put in the dynamic symbol table, even if no regular object refers + to it. + * elf32-i386.c (elf_i386_check_relocs): When creating a shared + library, don't allocate space for a PC relative reloc against a + local symbol. + * elf32-m68k.c (elf_m68k_check_relocs): Likewise. + * elf32-sparc.c (elf32_sparc_check_relocs): Likewise. + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Change assertion + to accept symbol with weakdef set. + * elf32-m68k.c (elf_m68k_adjust_dynamic_symbol): Likewise. + * elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise. + * elf32-m68k.c (elf_m68k_relocate_section): When creating a shared + libary, don't copy over a PC relative reloc against a local + symbol. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + Sun Aug 13 00:40:58 1995 Jeff Law (law@snake.cs.utah.edu) * som.h (R_HPPA_BEGIN_BRTAB): Define. diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index a3622620c7..e20651605d 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -417,7 +417,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs) case R_386_32: case R_386_PC32: if (info->shared - && (sec->flags & SEC_ALLOC) != 0) + && (sec->flags & SEC_ALLOC) != 0 + && (r_type != R_386_PC32 || h != NULL)) { /* When creating a shared object, we must copy these reloc types into the output file. We create a reloc @@ -486,6 +487,7 @@ elf_i386_adjust_dynamic_symbol (info, h) /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) + || h->weakdef != NULL || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 && (h->elf_link_hash_flags @@ -909,7 +911,11 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, || (r_type == R_386_PLT32 && h->plt_offset != (bfd_vma) -1) || (r_type == R_386_GOT32 - && elf_hash_table (info)->dynamic_sections_created) + && elf_hash_table (info)->dynamic_sections_created + && (! info->shared + || ! info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)) || (info->shared && (r_type == R_386_32 || r_type == R_386_PC32) @@ -927,7 +933,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; - else if (info->shared) + else if (info->shared && !info->symbolic) relocation = 0; else { @@ -957,13 +963,18 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, off = h->got_offset; BFD_ASSERT (off != (bfd_vma) -1); - if (! elf_hash_table (info)->dynamic_sections_created) + if (! elf_hash_table (info)->dynamic_sections_created + || (info->shared + && info->symbolic + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) { - /* This is actually a static link. We must - initialize this entry in the global offset table. - Since the offset must always be a multiple of 4, - we use the least significant bit to record - whether we have initialized it already. + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally. We must initialize this entry in the + global offset table. Since the offset must + always be a multiple of 4, we use the least + significant bit to record whether we have + initialized it already. When doing a dynamic link, we create a .rel.got relocation entry to initialize the value. This @@ -1069,7 +1080,8 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, if (h->plt_offset == (bfd_vma) -1) { /* We didn't make a PLT entry for this symbol. This - happens when statically linking PIC code. */ + happens when statically linking PIC code, or when + using -Bsymbolic. */ break; } @@ -1304,12 +1316,24 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym) srel = bfd_get_section_by_name (dynobj, ".rel.got"); BFD_ASSERT (sgot != NULL && srel != NULL); - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset); - rel.r_offset = (sgot->output_section->vma + sgot->output_offset - + h->got_offset); - rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); + + (h->got_offset &~ 1)); + + /* If this is a -Bsymbolic link, and the symbol is defined + locally, we just want to emit a RELATIVE reloc. The entry in + the global offset table will already have been initialized in + the relocate_section function. */ + if (info->shared + && info->symbolic + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) + rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + else + { + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset); + rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); + } + bfd_elf32_swap_reloc_out (output_bfd, &rel, ((Elf32_External_Rel *) srel->contents + srel->reloc_count)); diff --git a/bfd/elflink.h b/bfd/elflink.h index ecacfbbddd..07ab9bbb98 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -16,6 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + /* ELF linker code. */ static boolean elf_link_add_object_symbols @@ -507,6 +508,7 @@ elf_link_add_object_symbols (abfd, info) const char *name; struct elf_link_hash_entry *h = NULL; boolean definition; + boolean new_weakdef; elf_swap_symbol_in (abfd, esym, &sym); @@ -646,6 +648,7 @@ elf_link_add_object_symbols (abfd, info) false, collect, (struct bfd_link_hash_entry **) sym_hash))) goto error_return; + new_weakdef = false; if (dynamic && definition && (flags & BSF_WEAK) != 0 @@ -667,6 +670,7 @@ elf_link_add_object_symbols (abfd, info) (*sym_hash)->weakdef = weaks; weaks = *sym_hash; + new_weakdef = true; } /* Get the alignment of a common symbol. */ @@ -721,7 +725,10 @@ elf_link_add_object_symbols (abfd, info) new_flag = ELF_LINK_HASH_DEF_DYNAMIC; if ((old_flags & new_flag) != 0 || (old_flags & (ELF_LINK_HASH_DEF_REGULAR - | ELF_LINK_HASH_REF_REGULAR)) != 0) + | ELF_LINK_HASH_REF_REGULAR)) != 0 + || (h->weakdef != NULL + && (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC + | ELF_LINK_HASH_REF_DYNAMIC)) != 0)) dynsym = true; } @@ -730,6 +737,14 @@ elf_link_add_object_symbols (abfd, info) { if (! _bfd_elf_link_record_dynamic_symbol (info, h)) goto error_return; + if (h->weakdef != NULL + && ! new_weakdef + && h->weakdef->dynindx == -1) + { + if (! _bfd_elf_link_record_dynamic_symbol (info, + h->weakdef)) + goto error_return; + } } } } @@ -1432,13 +1447,16 @@ elf_adjust_dynamic_symbol (h, data) /* If this symbol does not require a PLT entry, and it is not defined by a dynamic object, or is not referenced by a regular - object, ignore it. FIXME: Do we need to worry about symbols - which are defined by one dynamic object and referenced by another - one? */ + object, ignore it. We do have to handle a weak defined symbol, + even if no regular object refers to it, if we decided to add it + to the dynamic symbol table. FIXME: Do we normally need to worry + about symbols which are defined by one dynamic object and + referenced by another one? */ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0 && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 - || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)) + || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0 + && (h->weakdef == NULL || h->weakdef->dynindx == -1)))) return true; /* If we've already adjusted this symbol, don't do it again. This