From 58ac9f718e25a6654808010ec6b9b19a9c1f21f7 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 13 Feb 2003 23:48:31 +0000 Subject: * elf64-ppc.c (ppc64_elf_link_hash_table_create): Init tls_get_addr. (ppc64_elf_copy_indirect_symbol): Merge tls_mask too. (ppc64_elf_gc_sweep_hook): Simplify removal of dyn_relocs. (allocate_dynrelocs): Don't treat undefined and undefweak specially. (ppc_size_one_stub): Fix warning, and tighten plt entry check. (group_sections): Don't share a stub section if stubs are for a large section. Adjust comment. (ppc64_elf_size_stubs): Roughly double the size left for stubs if !stubs_always_before_branch. (ppc64_elf_relocate_section): Initialize tlsld GOT entry once. Don't treat undefined and undefweak specially when processing dyn relocs. --- bfd/ChangeLog | 16 ++++- bfd/elf64-ppc.c | 183 ++++++++++++++++++++++---------------------------------- 2 files changed, 88 insertions(+), 111 deletions(-) (limited to 'bfd') diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 419e7e8..0a8081f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2003-02-14 Alan Modra + + * elf64-ppc.c (ppc64_elf_link_hash_table_create): Init tls_get_addr. + (ppc64_elf_copy_indirect_symbol): Merge tls_mask too. + (ppc64_elf_gc_sweep_hook): Simplify removal of dyn_relocs. + (allocate_dynrelocs): Don't treat undefined and undefweak specially. + (ppc_size_one_stub): Fix warning, and tighten plt entry check. + (group_sections): Don't share a stub section if stubs are for a large + section. Adjust comment. + (ppc64_elf_size_stubs): Roughly double the size left for stubs if + !stubs_always_before_branch. + (ppc64_elf_relocate_section): Initialize tlsld GOT entry once. Don't + treat undefined and undefweak specially when processing dyn relocs. + 2003-02-13 Jakub Jelinek * elflink.h (elf_link_add_object_symbols): Handle .symver x, x@FOO. @@ -142,7 +156,7 @@ TLS_EXPLICIT): Define. (struct ppc_link_hash_table): Add tls_sec, tls_get_addr, tlsld_got. (link_hash_newfunc): Init new fields. - (ppc64_elf_link_hash_table_create): Likewise. Set init_relcount and + (ppc64_elf_link_hash_table_create): Likewise. Set init_refcount and init_offset to NULL. (ppc64_elf_copy_indirect_symbol): Copy got and plt info. Don't call _bfd_elf_link_hash_copy_indirect, rather insert relevant code from diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 7bf926f..0419c48 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -2533,7 +2533,8 @@ struct plt_entry }; /* Of those relocs that might be copied as dynamic relocs, this macro - selects those that must be copied when linking a shared library. */ + selects those that must be copied when linking a shared library, + even when the symbol is local. */ #define MUST_BE_DYN_RELOC(RTYPE) \ ((RTYPE) != R_PPC64_REL32 \ @@ -2968,6 +2969,7 @@ ppc64_elf_link_hash_table_create (abfd) htab->sbrlt = NULL; htab->srelbrlt = NULL; htab->tls_sec = NULL; + htab->tls_get_addr = NULL; htab->tlsld_got.refcount = 0; htab->stub_error = 0; htab->has_14bit_branch = 0; @@ -3306,6 +3308,7 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind) edir->is_func |= eind->is_func; edir->is_func_descriptor |= eind->is_func_descriptor; edir->is_entry |= eind->is_entry; + edir->tls_mask |= eind->tls_mask; /* Copy down any references that we may have already seen to the symbol which just became indirect. */ @@ -4106,11 +4109,29 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) { unsigned long r_symndx; enum elf_ppc64_reloc_type r_type; - struct elf_link_hash_entry *h; + struct elf_link_hash_entry *h = NULL; char tls_type = 0; r_symndx = ELF64_R_SYM (rel->r_info); r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct ppc_link_hash_entry *eh; + struct ppc_dyn_relocs **pp; + struct ppc_dyn_relocs *p; + + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct ppc_link_hash_entry *) h; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } + switch (r_type) { case R_PPC64_GOT_TLSLD16: @@ -4152,11 +4173,8 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) { struct got_entry *ent; - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - ent = h->got.glist; - } + if (h != NULL) + ent = h->got.glist; else ent = local_got_ents[r_symndx]; @@ -4180,11 +4198,10 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) case R_PPC64_REL14_BRNTAKEN: case R_PPC64_REL14_BRTAKEN: case R_PPC64_REL24: - if (r_symndx >= symtab_hdr->sh_info) + if (h != NULL) { struct plt_entry *ent; - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; for (ent = h->plt.plist; ent != NULL; ent = ent->next) if (ent->addend == rel->r_addend) break; @@ -4195,73 +4212,6 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) } break; - case R_PPC64_REL30: - case R_PPC64_REL32: - case R_PPC64_REL64: - if (r_symndx >= symtab_hdr->sh_info) - { - struct ppc_link_hash_entry *eh; - struct ppc_dyn_relocs **pp; - struct ppc_dyn_relocs *p; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - eh = (struct ppc_link_hash_entry *) h; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; - - case R_PPC64_DTPMOD64: - case R_PPC64_DTPREL64: - case R_PPC64_TPREL64: - case R_PPC64_ADDR14: - case R_PPC64_ADDR14_BRNTAKEN: - case R_PPC64_ADDR14_BRTAKEN: - case R_PPC64_ADDR16: - case R_PPC64_ADDR16_DS: - case R_PPC64_ADDR16_HA: - case R_PPC64_ADDR16_HI: - case R_PPC64_ADDR16_HIGHER: - case R_PPC64_ADDR16_HIGHERA: - case R_PPC64_ADDR16_HIGHEST: - case R_PPC64_ADDR16_HIGHESTA: - case R_PPC64_ADDR16_LO: - case R_PPC64_ADDR16_LO_DS: - case R_PPC64_ADDR24: - case R_PPC64_ADDR32: - case R_PPC64_ADDR64: - case R_PPC64_UADDR16: - case R_PPC64_UADDR32: - case R_PPC64_UADDR64: - case R_PPC64_TOC: - if (r_symndx >= symtab_hdr->sh_info) - { - struct ppc_link_hash_entry *eh; - struct ppc_dyn_relocs **pp; - struct ppc_dyn_relocs *p; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - eh = (struct ppc_link_hash_entry *) h; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; - default: break; } @@ -5663,11 +5613,8 @@ allocate_dynrelocs (h, inf) dynamic. */ if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 - && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - || (htab->elf.dynamic_sections_created - && (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_undefined)))) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ @@ -6272,13 +6219,14 @@ ppc_size_one_stub (gen_entry, in_arg) if (stub_entry->stub_type == ppc_stub_plt_call) { struct plt_entry *ent; + off = (bfd_vma) -1; for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next) if (ent->addend == stub_entry->addend) { off = ent->plt.offset & ~(bfd_vma) 1; break; } - if (ent == NULL) + if (off >= (bfd_vma) -2) abort (); off += (htab->splt->output_offset + htab->splt->output_section->vma @@ -6458,12 +6406,15 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) asection *curr; asection *prev; bfd_size_type total; + bfd_boolean big_sec; curr = tail; if (tail->_cooked_size) total = tail->_cooked_size; else total = tail->_raw_size; + big_sec = total >= stub_group_size; + while ((prev = PREV_SEC (curr)) != NULL && ((total += curr->output_offset - prev->output_offset) < stub_group_size)) @@ -6478,7 +6429,7 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) section size. That's a little tricky, and this way will only break if stubs added make the total size more than 2^25, ie. for the default stub_group_size, if stubs total - more than 2834432 bytes, or over 100000 plt call stubs. */ + more than 2097152 bytes, or nearly 75000 plt call stubs. */ do { prev = PREV_SEC (tail); @@ -6488,8 +6439,11 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) while (tail != curr && (tail = prev) != NULL); /* But wait, there's more! Input sections up to stub_group_size - bytes before the stub section can be handled by it too. */ - if (!stubs_always_before_branch) + bytes before the stub section can be handled by it too. + Don't do this if we have a really large section after the + stubs, as adding more stubs increases the chance that + branches may not reach into the stub section. */ + if (!stubs_always_before_branch && !big_sec) { total = 0; while (prev != NULL @@ -6541,9 +6495,18 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, if (stub_group_size == 1) { /* Default values. */ - stub_group_size = 30720000; - if (htab->has_14bit_branch) - stub_group_size = 30000; + if (stubs_always_before_branch) + { + stub_group_size = 0x1e00000; + if (htab->has_14bit_branch) + stub_group_size = 0x7800; + } + else + { + stub_group_size = 0x1c00000; + if (htab->has_14bit_branch) + stub_group_size = 0x7000; + } } group_sections (htab, stub_group_size, stubs_always_before_branch); @@ -6998,20 +6961,26 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, ppc_howto_init (); htab = ppc_hash_table (info); - if (info->shared && (htab->tlsld_got.offset & 1) == 0) + if ((htab->tlsld_got.offset & 1) == 0) { - outrel.r_offset = (htab->sgot->output_section->vma - + htab->sgot->output_offset - + htab->tlsld_got.offset); - outrel.r_info = ELF64_R_INFO (0, R_PPC64_DTPMOD64); - outrel.r_addend = 0; - - loc = htab->srelgot->contents; - loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); - bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); + if (info->shared) + { + outrel.r_offset = (htab->sgot->output_section->vma + + htab->sgot->output_offset + + htab->tlsld_got.offset); + outrel.r_info = ELF64_R_INFO (0, R_PPC64_DTPMOD64); + outrel.r_addend = 0; + + loc = htab->srelgot->contents; + loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); + bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); + } + else + bfd_put_64 (output_bfd, (bfd_vma) 1, + htab->sgot->contents + htab->tlsld_got.offset); + htab->tlsld_got.offset |= 1; } - local_got_ents = elf_local_got_ents (input_bfd); TOCstart = elf_gp (output_bfd); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; @@ -7692,9 +7661,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* Init the .got section contents if we're not emitting a reloc. */ - if (!(info->shared || indx != 0)) + if (!(info->shared || indx != 0) + && tls_type != (TLS_TLS | TLS_LD)) { - relocation += ent->addend; if (tls_type != 0) { @@ -7703,10 +7672,8 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, relocation += DTP_OFFSET - TP_OFFSET; } - if ((tls_type & (TLS_GD | TLS_LD)) != 0) + if ((tls_type & TLS_GD) != 0) { - if ((tls_type & TLS_LD) != 0) - relocation = - DTP_OFFSET; bfd_put_64 (output_bfd, relocation, htab->sgot->contents + off + 8); relocation = 1; @@ -7879,12 +7846,8 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, && h != NULL && h->dynindx != -1 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 - && (((h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0) - || h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_undefined))) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) { Elf_Internal_Rela outrel; bfd_boolean skip, relocate; -- cgit v1.1