diff options
-rw-r--r-- | bfd/ChangeLog | 12 | ||||
-rw-r--r-- | bfd/elf32-i386.c | 94 |
2 files changed, 63 insertions, 43 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e0ba4d1..74cdcec 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2000-08-27 Alan Modra <alan@linuxcare.com.au> + + * elf32-i386.c (elf_i386_check_relocs): Keep info on relocs copied + for any shared link, not just shared -Bsymbolic. + (elf_i386_size_dynamic_sections): Call elf_i386_discard_copies on + any shared link, and pass link info to it. + (elf_i386_size_dynamic_sections): Update comment. + (elf_i386_discard_copies): Modify to discard relocs for symbols + that have been forced local. + (elf_i386_finish_dynamic_symbol): Don't copy relocs for symbols + that have been forced local. + 2000-08-24 Denis Chertykov <denisc@overta.ru> & Nick Clifton <nickc@redhat.com> * elflink.h (elf_link_add_object_symbols): Allow common diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index bed0315..bdc27f7 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -636,17 +636,19 @@ elf_i386_check_relocs (abfd, info, sec, relocs) h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; /* If we are creating a shared library, and this is a reloc - against a global symbol, or a non PC relative reloc - against a local symbol, then we need to copy the reloc - into the shared library. However, if we are linking with - -Bsymbolic, we do not need to copy a reloc against a - global symbol which is defined in an object we are - including in the link (i.e., DEF_REGULAR is set). At - this point we have not seen all the input files, so it is - possible that DEF_REGULAR is not set now but will be set - later (it is never cleared). We account for that - possibility below by storing information in the - pcrel_relocs_copied field of the hash table entry. */ + against a global symbol, or a non PC relative reloc + against a local symbol, then we need to copy the reloc + into the shared library. However, if we are linking with + -Bsymbolic, we do not need to copy a reloc against a + global symbol which is defined in an object we are + including in the link (i.e., DEF_REGULAR is set). At + this point we have not seen all the input files, so it is + possible that DEF_REGULAR is not set now but will be set + later (it is never cleared). We account for that + possibility below by storing information in the + pcrel_relocs_copied field of the hash table entry. + A similar situation occurs when creating shared libraries + and symbol visibility changes render the symbol local. */ if (info->shared && (sec->flags & SEC_ALLOC) != 0 && (ELF32_R_TYPE (rel->r_info) != R_386_PC32 @@ -656,8 +658,8 @@ elf_i386_check_relocs (abfd, info, sec, relocs) & ELF_LINK_HASH_DEF_REGULAR) == 0)))) { /* When creating a shared object, we must copy these - reloc types into the output file. We create a reloc - section in dynobj and make room for this reloc. */ + reloc types into the output file. We create a reloc + section in dynobj and make room for this reloc. */ if (sreloc == NULL) { const char *name; @@ -692,15 +694,13 @@ elf_i386_check_relocs (abfd, info, sec, relocs) sreloc->_raw_size += sizeof (Elf32_External_Rel); - /* If we are linking with -Bsymbolic, and this is a - global symbol, we count the number of PC relative - relocations we have entered for this symbol, so that - we can discard them again if the symbol is later - defined by a regular object. Note that this function - is only called if we are using an elf_i386 linker - hash table, which means that h is really a pointer to - an elf_i386_link_hash_entry. */ - if (h != NULL && info->symbolic + /* If this is a global symbol, we count the number of PC + relative relocations we have entered for this symbol, + so that we can discard them later as necessary. Note + that this function is only called if we are using an + elf_i386 linker hash table, which means that h is + really a pointer to an elf_i386_link_hash_entry. */ + if (h != NULL && ELF32_R_TYPE (rel->r_info) == R_386_PC32) { struct elf_i386_link_hash_entry *eh; @@ -1100,10 +1100,10 @@ elf_i386_size_dynamic_sections (output_bfd, info) PC relative relocs against symbols defined in a regular object. We allocated space for them in the check_relocs routine, but we will not fill them in in the relocate_section routine. */ - if (info->shared && info->symbolic) + if (info->shared) elf_i386_link_hash_traverse (elf_i386_hash_table (info), elf_i386_discard_copies, - (PTR) NULL); + (PTR) info); /* The check_relocs and adjust_dynamic_symbol entry points have determined the sizes of the various dynamic sections. Allocate @@ -1197,12 +1197,11 @@ elf_i386_size_dynamic_sections (output_bfd, info) continue; } - /* Allocate memory for the section contents. */ - /* FIXME: This should be a call to bfd_alloc not bfd_zalloc. - Unused entries should be reclaimed before the section's contents - are written out, but at the moment this does not happen. Thus in - order to prevent writing out garbage, we initialise the section's - contents to zero. */ + /* Allocate memory for the section contents. We use bfd_zalloc + here in case unused entries are not reclaimed before the + section's contents are written out. This should not happen, + but this way if it does, we get a R_386_NONE reloc instead + of garbage. */ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); if (s->contents == NULL && s->_raw_size != 0) return false; @@ -1251,26 +1250,33 @@ elf_i386_size_dynamic_sections (output_bfd, info) } /* This function is called via elf_i386_link_hash_traverse if we are - creating a shared object with -Bsymbolic. It discards the space - allocated to copy PC relative relocs against symbols which are - defined in regular objects. We allocated space for them in the + creating a shared object. In the -Bsymbolic case, it discards the + space allocated to copy PC relative relocs against symbols which + are defined in regular objects. For the normal non-symbolic case, + we also discard space for relocs that have become local due to + symbol visibility changes. We allocated space for them in the check_relocs routine, but we won't fill them in in the relocate_section routine. */ /*ARGSUSED*/ static boolean -elf_i386_discard_copies (h, ignore) +elf_i386_discard_copies (h, inf) struct elf_i386_link_hash_entry *h; - PTR ignore ATTRIBUTE_UNUSED; + PTR inf; { struct elf_i386_pcrel_relocs_copied *s; - - /* We only discard relocs for symbols defined in a regular object. */ - if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - return true; - - for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) - s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel); + struct bfd_link_info *info = (struct bfd_link_info *) inf; + + /* If a symbol has been forced local or we have found a regular + definition for the symbolic link case, then we won't be needing + any relocs. */ + if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 + && ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 + || info->symbolic)) + { + for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) + s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel); + } return true; } @@ -1878,7 +1884,9 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym) ++srel->reloc_count; } - if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) + if ((h->elf_link_hash_flags & (ELF_LINK_HASH_NEEDS_COPY + | ELF_LINK_FORCED_LOCAL)) + == ELF_LINK_HASH_NEEDS_COPY) { asection *s; Elf_Internal_Rel rel; |