diff options
author | dfr <dfr@FreeBSD.org> | 1999-07-17 08:04:58 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1999-07-17 08:04:58 +0000 |
commit | 3e4c2ad4a22086967d58cae4d866a37ab55b495a (patch) | |
tree | 65c3054e413569165690292662b3c6998f119cbf /contrib/binutils/bfd/elf64-alpha.c | |
parent | c97b6ef1f6a31f79e1e767e63d1021d3ead85ffd (diff) | |
download | FreeBSD-src-3e4c2ad4a22086967d58cae4d866a37ab55b495a.zip FreeBSD-src-3e4c2ad4a22086967d58cae4d866a37ab55b495a.tar.gz |
Merge some patches from RedHat-6.0. The most important change fixes a bug
when linking large shared libraries where the linker missed out some of
the dynamic relocations from the output. This prevents libqt from linking
properly among other packages.
Obtained from: RedHat-6.0
Diffstat (limited to 'contrib/binutils/bfd/elf64-alpha.c')
-rw-r--r-- | contrib/binutils/bfd/elf64-alpha.c | 120 |
1 files changed, 90 insertions, 30 deletions
diff --git a/contrib/binutils/bfd/elf64-alpha.c b/contrib/binutils/bfd/elf64-alpha.c index 6d9c539..31cd43a 100644 --- a/contrib/binutils/bfd/elf64-alpha.c +++ b/contrib/binutils/bfd/elf64-alpha.c @@ -125,6 +125,8 @@ static boolean elf64_alpha_finish_dynamic_sections PARAMS((bfd *, struct bfd_link_info *)); static boolean elf64_alpha_final_link PARAMS((bfd *, struct bfd_link_info *)); +static boolean elf64_alpha_merge_ind_symbols + PARAMS((struct alpha_elf_link_hash_entry *, PTR)); struct alpha_elf_link_hash_entry @@ -216,10 +218,20 @@ struct alpha_elf_link_hash_table #define alpha_elf_sym_hashes(abfd) \ ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd)) +/* Should we do forced local to this symbol? */ + +#define alpha_elf_force_local_symbol_p(h, info) \ + ((info)->shared \ + && ((h)->dynindx == -1 \ + || ((info)->symbolic \ + && ((h)->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))) + /* Should we do dynamic things to this symbol? */ #define alpha_elf_dynamic_symbol_p(h, info) \ - (((info)->shared && !(info)->symbolic && (h)->dynindx != -1) \ + (((info)->shared \ + && ((h)->root.type == bfd_link_hash_undefweak \ + || !alpha_elf_force_local_symbol_p ((h), (info)))) \ || (((h)->elf_link_hash_flags \ & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) \ == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) @@ -883,8 +895,8 @@ elf64_alpha_do_reloc_gpdisp (abfd, gpdisp, p_ldah, p_lda) gpdisp += addend; - if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma)0x80000000 - || gpdisp >= 0x7fff8000) + if ((bfd_signed_vma) gpdisp < -(bfd_signed_vma) 0x80000000 + || (bfd_signed_vma) gpdisp >= (bfd_signed_vma) 0x7fff8000) ret = bfd_reloc_overflow; /* compensate for the sign extension again. */ @@ -1149,6 +1161,7 @@ static int elf64_alpha_additional_program_headers (abfd) bfd *abfd; { +#ifdef ERIC_neverdef asection *s; int ret; @@ -1169,6 +1182,9 @@ elf64_alpha_additional_program_headers (abfd) } return ret; +#else + return 0; +#endif } /* Create the .got section. */ @@ -1970,7 +1986,8 @@ elf64_alpha_adjust_dynamic_symbol (info, h) generating a shared library, then set the symbol to the location in the .plt. This is required to make function pointers compare equal between the normal executable and the shared library. */ - if (!info->shared) + if (! info->shared + && h->root.type != bfd_link_hash_defweak) { h->root.u.def.section = s; h->root.u.def.value = h->plt_offset; @@ -2407,38 +2424,45 @@ elf64_alpha_calc_dynrel_sizes (h, info) /* If the symbol is dynamic, we'll need all the relocations in their natural form. If it has been forced local, we'll need the same number of RELATIVE relocations. */ - if (alpha_elf_dynamic_symbol_p (&h->root, info) - || (info->shared && h->root.dynindx == -1)) + if (alpha_elf_dynamic_symbol_p (&h->root, info) + || alpha_elf_force_local_symbol_p (&h->root, info)) { struct alpha_elf_reloc_entry *relent; + bfd *dynobj; + struct alpha_elf_got_entry *gotent; + bfd_size_type count; + asection *srel; + /* We need it when we have .o files compiled with PIC, but + linked statically. */ for (relent = h->reloc_entries; relent; relent = relent->next) { relent->srel->_raw_size += sizeof (Elf64_External_Rela) * relent->count; } - /* Only add a .rela.got entry if we're not using a .plt entry. */ - if (h->root.plt_offset == MINUS_ONE) - { - bfd *dynobj = elf_hash_table(info)->dynobj; - struct alpha_elf_got_entry *gotent; - bfd_size_type count = 0; - asection *srel; + dynobj = elf_hash_table(info)->dynobj; + count = 0; - for (gotent = h->got_entries; gotent ; gotent = gotent->next) - count++; - if (count > 0) - { - srel = bfd_get_section_by_name (dynobj, ".rela.got"); - BFD_ASSERT (srel != NULL); - srel->_raw_size += sizeof (Elf64_External_Rela) * count; - } + for (gotent = h->got_entries; gotent ; gotent = gotent->next) + count++; + + /* If we are using a .plt entry, subtract one, as the first + reference uses a .rela.plt entry instead. */ + if (h->root.plt_offset != MINUS_ONE) + count--; + + if (count > 0) + { + srel = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (srel != NULL); + srel->_raw_size += sizeof (Elf64_External_Rela) * count; } } - /* Otherwise, shared objects require RELATIVE relocs for all REFQUAD + + /* Shared objects require at least RELATIVE relocs for all REFQUAD and REFLONG relocations. */ - else if (info->shared) + if (info->shared) { struct alpha_elf_reloc_entry *relent; @@ -2879,7 +2903,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, /* If the symbol has been forced local, output a RELATIVE reloc, otherwise it will be handled in finish_dynamic_symbol. */ - if (info->shared && h->root.dynindx == -1) + if (alpha_elf_force_local_symbol_p (&h->root, info)) { Elf_Internal_Rela outrel; @@ -2895,6 +2919,9 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, ((Elf64_External_Rela *) srelgot->contents) + srelgot->reloc_count++); + BFD_ASSERT (sizeof(Elf64_External_Rela) + * srelgot->reloc_count + <= srelgot->_cooked_size); } gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE; @@ -2930,6 +2957,9 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, ((Elf64_External_Rela *) srelgot->contents) + srelgot->reloc_count++); + BFD_ASSERT (sizeof(Elf64_External_Rela) + * srelgot->reloc_count + <= srelgot->_cooked_size); } gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE; @@ -3023,6 +3053,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, ((Elf64_External_Rela *) srel->contents) + srel->reloc_count++); + BFD_ASSERT (sizeof(Elf64_External_Rela) * srel->reloc_count + <= srel->_cooked_size); } goto default_reloc; @@ -3147,14 +3179,40 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_put_64 (output_bfd, plt_addr, sgot->contents + gotent->got_offset); /* Subsequent .got entries will continue to bounce through the .plt. */ - while ((gotent = gotent->next) != NULL) + if (gotent->next) { - sgot = alpha_elf_tdata(gotent->gotobj)->got; - BFD_ASSERT(sgot != NULL); - BFD_ASSERT(gotent->addend == 0); + srel = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (! info->shared || srel != NULL); - bfd_put_64 (output_bfd, plt_addr, - sgot->contents + gotent->got_offset); + gotent = gotent->next; + do + { + sgot = alpha_elf_tdata(gotent->gotobj)->got; + BFD_ASSERT(sgot != NULL); + BFD_ASSERT(gotent->addend == 0); + + bfd_put_64 (output_bfd, plt_addr, + sgot->contents + gotent->got_offset); + + if (info->shared) + { + outrel.r_offset = (sgot->output_section->vma + + sgot->output_offset + + gotent->got_offset); + outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE); + outrel.r_addend = 0; + + bfd_elf64_swap_reloca_out (output_bfd, &outrel, + ((Elf64_External_Rela *) + srel->contents) + + srel->reloc_count++); + BFD_ASSERT (sizeof(Elf64_External_Rela) * srel->reloc_count + <= srel->_cooked_size); + } + + gotent = gotent->next; + } + while (gotent != NULL); } } else if (alpha_elf_dynamic_symbol_p (h, info)) @@ -3181,6 +3239,8 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_elf64_swap_reloca_out (output_bfd, &outrel, ((Elf64_External_Rela *)srel->contents + srel->reloc_count++)); + BFD_ASSERT (sizeof(Elf64_External_Rela) * srel->reloc_count + <= srel->_cooked_size); } } |