From 446f28631310205b7515598fdbcd88a4d1838da2 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 27 Jun 2001 02:42:09 +0000 Subject: [PATCH] Avoid creating COPY relocs. * elf32-hppa.c (elf32_hppa_check_relocs): Don't make syms dynamic here.. (elf32_hppa_adjust_dynamic_symbol): ..nor here.. (allocate_plt_and_got_and_discard_relocs): .. instead do so here after gc has run. * elf32-hppa.c (RELATIVE_DYNAMIC_RELOCS): Delete. (IS_ABSOLUTE_RELOC): Define. (elf32_hppa_link_hash_entry): Always include reloc_entries field. (hppa_link_hash_newfunc): Always init it. (elf32_hppa_check_relocs): Mark symbols as ELF_LINK_NON_GOT_REF to create COPY relocs only when the reloc is in a read-only section. Instead, allocate space for a dynamic reloc to reference the library symbol directly. Keep track of space we allocate using relocs_entries. (hppa_discard_copies): Delete, and move code to.. (allocate_plt_and_got): ..here. Rename to allocate_plt_and_got_and_discard_relocs. Remove unneeded dynamic relocs for non-shared link. (elf32_hppa_size_dynamic_sections): Update calls to above. (elf32_hppa_relocate_section): Write out the dynamic relocs used in lieu of COPY relocs. --- bfd/ChangeLog | 23 +++++ bfd/elf32-hppa.c | 245 +++++++++++++++++++++++++---------------------- 2 files changed, 152 insertions(+), 116 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6600d6b79b9..ec761840b0c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,28 @@ 2001-06-27 Alan Modra + * elf32-hppa.c (elf32_hppa_check_relocs): Don't make syms dynamic + here.. + (elf32_hppa_adjust_dynamic_symbol): ..nor here.. + (allocate_plt_and_got_and_discard_relocs): .. instead do so here + after gc has run. + + * elf32-hppa.c (RELATIVE_DYNAMIC_RELOCS): Delete. + (IS_ABSOLUTE_RELOC): Define. + (elf32_hppa_link_hash_entry): Always include reloc_entries field. + (hppa_link_hash_newfunc): Always init it. + (elf32_hppa_check_relocs): Mark symbols as ELF_LINK_NON_GOT_REF to + create COPY relocs only when the reloc is in a read-only section. + Instead, allocate space for a dynamic reloc to reference the + library symbol directly. Keep track of space we allocate using + relocs_entries. + (hppa_discard_copies): Delete, and move code to.. + (allocate_plt_and_got): ..here. Rename to + allocate_plt_and_got_and_discard_relocs. Remove unneeded dynamic + relocs for non-shared link. + (elf32_hppa_size_dynamic_sections): Update calls to above. + (elf32_hppa_relocate_section): Write out the dynamic relocs used + in lieu of COPY relocs. + * elf32-i386.c (elf_i386_check_relocs): Don't make syms dynamic here.. (elf_i386_adjust_dynamic_symbol): ..nor here.. diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index a58600921d1..cc086095f11 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -149,9 +149,10 @@ static const bfd_byte plt_stub[] = #endif /* We don't need to copy any PC- or GP-relative dynamic relocs into a - shared object's dynamic section. */ -#ifndef RELATIVE_DYNAMIC_RELOCS -#define RELATIVE_DYNAMIC_RELOCS 0 + shared object's dynamic section. All the relocs of the limited + class we are interested in, are absolute. See check_relocs. */ +#ifndef IS_ABSOLUTE_RELOC +#define IS_ABSOLUTE_RELOC(r_type) 1 #endif enum elf32_hppa_stub_type { @@ -208,7 +209,6 @@ struct elf32_hppa_link_hash_entry { asection *stub_reloc_sec; #endif -#if ! LONG_BRANCH_PIC_IN_SHLIB || RELATIVE_DYNAMIC_RELOCS /* Used to count relocations for delayed sizing of relocation sections. */ struct elf32_hppa_dyn_reloc_entry { @@ -222,7 +222,6 @@ struct elf32_hppa_link_hash_entry { /* Number of relocs copied in this section. */ bfd_size_type count; } *reloc_entries; -#endif /* Set during a static link if we detect a function is PIC. */ unsigned int maybe_pic_call:1; @@ -366,14 +365,8 @@ static boolean elf32_hppa_adjust_dynamic_symbol static boolean hppa_handle_PIC_calls PARAMS ((struct elf_link_hash_entry *, PTR)); -static boolean allocate_plt_and_got - PARAMS ((struct elf_link_hash_entry *, PTR)); - -#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \ - || RELATIVE_DYNAMIC_RELOCS) -static boolean hppa_discard_copies +static boolean allocate_plt_and_got_and_discard_relocs PARAMS ((struct elf_link_hash_entry *, PTR)); -#endif static boolean clobber_millicode_symbols PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *)); @@ -494,9 +487,7 @@ hppa_link_hash_newfunc (entry, table, string) ret->stub_reloc_sec = NULL; #endif ret->stub_cache = NULL; -#if ! LONG_BRANCH_PIC_IN_SHLIB || RELATIVE_DYNAMIC_RELOCS ret->reloc_entries = NULL; -#endif ret->maybe_pic_call = 0; ret->pic_call = 0; ret->plabel = 0; @@ -1452,17 +1443,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) if (h != NULL) { if (h->elf.got.refcount == -1) - { - h->elf.got.refcount = 1; - - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->elf.dynindx == -1) - { - if (! bfd_elf32_link_record_dynamic_symbol (info, - &h->elf)) - return false; - } - } + h->elf.got.refcount = 1; else h->elf.got.refcount += 1; } @@ -1553,7 +1534,10 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) /* Flag this symbol as having a non-got, non-plt reference so that we generate copy relocs if it turns out to be dynamic. */ - if (h != NULL) + if (need_entry == NEED_DYNREL + && h != NULL + && !info->shared + && (sec->flags & SEC_READONLY) != 0) h->elf.elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; /* If we are creating a shared library then we need to copy @@ -1579,16 +1563,21 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) is absolute too, as in that case it is the reloc in the stub we will be creating, rather than copying the PCREL reloc in the branch. */ - if ((sec->flags & SEC_ALLOC) != 0 - && info->shared -#if RELATIVE_DYNAMIC_RELOCS - && (!info->symbolic - || is_absolute_reloc (r_type) - || (h != NULL - && ((h->elf.elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0))) -#endif - ) + if ((info->shared + && (sec->flags & SEC_ALLOC) != 0 + && (IS_ABSOLUTE_RELOC (r_type) + || (h != NULL + && (!info->symbolic + || h->elf.root.type == bfd_link_hash_defweak + || (h->elf.elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || (!info->shared + && (sec->flags & SEC_ALLOC) != 0 + && h != NULL + && (h->elf.elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 + && (h->elf.root.type == bfd_link_hash_defweak + || (h->elf.elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0))) { boolean doit; asection *srel; @@ -1676,16 +1665,13 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) { srel->_raw_size += sizeof (Elf32_External_Rela); -#if ! LONG_BRANCH_PIC_IN_SHLIB || RELATIVE_DYNAMIC_RELOCS /* Keep track of relocations we have entered for this global symbol, so that we can discard them later if necessary. */ - if (h != NULL - && (0 -#if RELATIVE_DYNAMIC_RELOCS - || ! is_absolute_reloc (rtype) -#endif - || (need_entry & NEED_STUBREL))) + if (!info->shared + || (h != NULL + && (! IS_ABSOLUTE_RELOC (rtype) + || (need_entry & NEED_STUBREL)))) { struct elf32_hppa_dyn_reloc_entry *p; @@ -1709,11 +1695,10 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs) set. Leave the count at zero for the NEED_STUBREL case as we only ever have one stub reloc per section per symbol, and this - simplifies code in hppa_discard_copies. */ + simplifies code to discard unneeded relocs. */ if (! (need_entry & NEED_STUBREL)) ++p->count; } -#endif } } } @@ -1941,18 +1926,6 @@ elf32_hppa_adjust_dynamic_symbol (info, h) { h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; - return true; - } - } - - if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call) - { - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) - { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; } } @@ -2070,13 +2043,14 @@ hppa_handle_PIC_calls (h, inf) global syms. */ static boolean -allocate_plt_and_got (h, inf) +allocate_plt_and_got_and_discard_relocs (h, inf) struct elf_link_hash_entry *h; PTR inf; { struct bfd_link_info *info; struct elf32_hppa_link_hash_table *hplink; asection *s; + struct elf32_hppa_link_hash_entry *eh; if (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) @@ -2088,6 +2062,17 @@ allocate_plt_and_got (h, inf) && h->plt.refcount > 0) || ((struct elf32_hppa_link_hash_entry *) h)->pic_call) { + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0 + && h->type != STT_PARISC_MILLI + && !((struct elf32_hppa_link_hash_entry *) h)->pic_call) + { + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } + /* Make an entry in the .plt section. */ s = hplink->splt; h->plt.offset = s->_raw_size; @@ -2119,6 +2104,16 @@ allocate_plt_and_got (h, inf) { boolean dyn; + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0 + && h->type != STT_PARISC_MILLI) + { + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } + s = hplink->sgot; h->got.offset = s->_raw_size; s->_raw_size += GOT_ENTRY_SIZE; @@ -2129,58 +2124,75 @@ allocate_plt_and_got (h, inf) else h->got.offset = (bfd_vma) -1; - return true; -} + /* If this is a -Bsymbolic shared link, then we need to discard all + space allocated for dynamic relocs against symbols defined in a + regular object. For the normal shared case, discard space for + relocs that have become local due to symbol visibility changes. + For the non-shared case, discard space for symbols which turn out + to need copy relocs or are not dynamic. We also need to lose + relocs we've allocated for long branch stubs if we know we won't + be generating a stub. */ -#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \ - || RELATIVE_DYNAMIC_RELOCS) -/* This function is called via elf_link_hash_traverse to discard space - we allocated for relocs that it turned out we didn't need. */ + eh = (struct elf32_hppa_link_hash_entry *) h; + if (eh->reloc_entries == NULL) + return true; -static boolean -hppa_discard_copies (h, inf) - struct elf_link_hash_entry *h; - PTR inf; -{ - struct elf32_hppa_dyn_reloc_entry *s; - struct elf32_hppa_link_hash_entry *eh; - struct bfd_link_info *info; + /* First handle the non-shared case. */ + if (!info->shared + && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 + && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + || h->root.type == bfd_link_hash_undefweak + || h->root.type == bfd_link_hash_undefined)) + { + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0 + && h->type != STT_PARISC_MILLI) + { + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return false; + } - eh = (struct elf32_hppa_link_hash_entry *) h; - info = (struct bfd_link_info *) inf; + /* If that succeeded, we know we'll be keeping all the relocs. */ + if (h->dynindx != -1) + return true; + } #if ! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT /* Handle the stub reloc case. If we have a plt entry for the - function, we won't be needing long branch stubs. s->count will + function, we won't be needing long branch stubs. c->count will only be zero for stub relocs, which provides a handy way of flagging these relocs, and means we need do nothing special for the forced local and symbolic link case. */ if (eh->stub_reloc_sec != NULL && eh->elf.plt.offset != (bfd_vma) -1) { - for (s = eh->reloc_entries; s != NULL; s = s->next) - if (s->count == 0) - s->section->_raw_size -= sizeof (Elf32_External_Rela); + struct elf32_hppa_dyn_reloc_entry *c; + + for (c = eh->reloc_entries; c != NULL; c = c->next) + if (c->count == 0) + c->section->_raw_size -= sizeof (Elf32_External_Rela); } #endif -#if RELATIVE_DYNAMIC_RELOCS - /* If a symbol has been forced local or we have found a regular + /* Discard any relocs in the non-shared case. For the shared case, + 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 (eh->elf.dynindx == -1 + if (!info->shared || ((eh->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 - && !is_absolute_reloc (r_type) - && info->symbolic)) + && ((eh->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 + || info->symbolic))) { - for (s = eh->reloc_entries; s != NULL; s = s->next) - s->section->_raw_size -= s->count * sizeof (Elf32_External_Rela); + struct elf32_hppa_dyn_reloc_entry *c; + + for (c = eh->reloc_entries; c != NULL; c = c->next) + c->section->_raw_size -= c->count * sizeof (Elf32_External_Rela); } -#endif return true; } -#endif /* This function is called via elf_link_hash_traverse to force millicode symbols local so they do not end up as globals in the @@ -2228,7 +2240,6 @@ elf32_hppa_size_dynamic_sections (output_bfd, info) if (hplink->root.dynamic_sections_created) { - /* Set the contents of the .interp section to the interpreter. */ if (! info->shared) { @@ -2318,22 +2329,11 @@ elf32_hppa_size_dynamic_sections (output_bfd, info) } } - /* Allocate global sym .plt and .got entries. */ + /* Allocate global sym .plt and .got entries. Also discard all + unneeded relocs. */ elf_link_hash_traverse (&hplink->root, - allocate_plt_and_got, - info); - -#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \ - || RELATIVE_DYNAMIC_RELOCS) - /* If this is a -Bsymbolic shared link, then we need to discard all - relocs against symbols defined in a regular object. We also need - to lose relocs we've allocated for long branch stubs if we know - we won't be generating a stub. */ - if (info->shared) - elf_link_hash_traverse (&hplink->root, - hppa_discard_copies, - info); -#endif + allocate_plt_and_got_and_discard_relocs, + (PTR) info); /* The check_relocs and adjust_dynamic_symbol entry points have determined the sizes of the various dynamic sections. Allocate @@ -3896,19 +3896,30 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, hppa_discard_copies. ie. We need exactly the same condition as in check_relocs, with some extra conditions (dynindx test in this case) to cater for relocs removed - by hppa_discard_copies. */ - if ((input_section->flags & SEC_ALLOC) != 0 - && info->shared -#if RELATIVE_DYNAMIC_RELOCS - && (is_absolute_reloc (r_type) - || ((!info->symbolic - || (h != NULL - && ((h->elf.elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0 - || h->elf.root.type == bfd_link_hash_defweak))) - && (h == NULL || h->elf.dynindx != -1))) -#endif - ) + by hppa_discard_copies. If you squint, the non-shared + test here does indeed match the one in check_relocs, the + difference being that here we test DEF_DYNAMIC rather + than a maybe-DEF_DYNAMIC via !DEF_REGULAR. Common syms + end up with !DEF_REGULAR, which is why we can't use that + here. Conversely, DEF_DYNAMIC can't be used in + check_relocs as there all files have not been loaded. */ + if ((info->shared + && (input_section->flags & SEC_ALLOC) != 0 + && (IS_ABSOLUTE_RELOC (r_type) + || (h != NULL + && h->elf.dynindx != -1 + && (!info->symbolic + || (h->elf.elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || (!info->shared + && (input_section->flags & SEC_ALLOC) != 0 + && h != NULL + && h->elf.dynindx != -1 + && (h->elf.elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 + && ((h->elf.elf_link_hash_flags + & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + || h->elf.root.type == bfd_link_hash_undefweak + || h->elf.root.type == bfd_link_hash_undefined))) { Elf_Internal_Rela outrel; boolean skip; @@ -3959,6 +3970,8 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, else if (h != NULL && h->elf.dynindx != -1 && (plabel + || !IS_ABSOLUTE_RELOC (r_type) + || !info->shared || !info->symbolic || (h->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) -- 2.30.2