diff options
Diffstat (limited to 'bfd/elf64-hppa.c')
-rw-r--r-- | bfd/elf64-hppa.c | 121 |
1 files changed, 76 insertions, 45 deletions
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 3f5a3fe..6a63ce2 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -247,6 +247,24 @@ static bool get_stub static int elf64_hppa_elf_get_symbol_type (Elf_Internal_Sym *, int); +/* Search for the index of a global symbol in it's defining object file. */ + +static long +global_sym_index (struct elf_link_hash_entry *h) +{ + struct elf_link_hash_entry **p; + bfd *obj; + + BFD_ASSERT (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak); + + obj = h->root.u.def.section->owner; + for (p = elf_sym_hashes (obj); *p != h; ++p) + continue; + + return p - elf_sym_hashes (obj) + elf_tdata (obj)->symtab_hdr.sh_info; +} + /* Initialize an entry in the link hash table. */ static struct bfd_hash_entry * @@ -641,7 +659,10 @@ elf64_hppa_check_relocs (bfd *abfd, /* PR15323, ref flags aren't set for references in the same object. */ - hh->eh.ref_regular = 1; + if (!hh->eh.root.linker_def && !hh->eh.root.ldscript_def) + hh->eh.ref_regular = 1; + else + hh = NULL; } else hh = NULL; @@ -744,7 +765,7 @@ elf64_hppa_check_relocs (bfd *abfd, case R_PARISC_LTOFF_FPTR16WF: case R_PARISC_LTOFF_FPTR16DF: if (bfd_link_pic (info) || maybe_dynamic) - need_entry = (NEED_DLT | NEED_OPD | NEED_PLT); + need_entry = (NEED_DLT | NEED_OPD | NEED_PLT | NEED_DYNREL); else need_entry = (NEED_DLT | NEED_OPD | NEED_PLT); dynrel_type = R_PARISC_FPTR64; @@ -762,9 +783,7 @@ elf64_hppa_check_relocs (bfd *abfd, /* Add more cases as needed. */ } - if (!need_entry) - continue; - + /* We may need this information later for OPD. */ if (hh) { /* Stash away enough information to be able to find this symbol @@ -773,6 +792,9 @@ elf64_hppa_check_relocs (bfd *abfd, hh->sym_indx = r_symndx; } + if (!need_entry) + continue; + /* Create what's needed. */ if (need_entry & NEED_DLT) { @@ -874,6 +896,13 @@ elf64_hppa_check_relocs (bfd *abfd, sec_symndx, rel->r_offset, rel->r_addend)) goto err_out; + /* Add symbol to dynamic symbol table. */ + if (hh != NULL + && bfd_link_pic (info) + && ! (bfd_elf_link_record_local_dynamic_symbol + (info, abfd, r_symndx))) + goto err_out; + /* If we are building a shared library and we just recorded a dynamic R_PARISC_FPTR64 relocation, then make sure the section symbol for this section ends up in the dynamic @@ -881,7 +910,7 @@ elf64_hppa_check_relocs (bfd *abfd, if (bfd_link_pic (info) && dynrel_type == R_PARISC_FPTR64 && ! (bfd_elf_link_record_local_dynamic_symbol (info, abfd, sec_symndx))) - return false; + goto err_out; } } @@ -969,10 +998,14 @@ allocate_global_data_dlt (struct elf_link_hash_entry *eh, void *data) against it. */ if (eh->dynindx == -1 && eh->type != STT_PARISC_MILLI) { - bfd *owner = eh->root.u.def.section->owner; + if (!hh->owner) + { + hh->owner = eh->root.u.def.section->owner; + hh->sym_indx = global_sym_index (eh); + } if (! (bfd_elf_link_record_local_dynamic_symbol - (x->info, owner, hh->sym_indx))) + (x->info, hh->owner, hh->sym_indx))) return false; } } @@ -983,7 +1016,7 @@ allocate_global_data_dlt (struct elf_link_hash_entry *eh, void *data) return true; } -/* Allocate space for a DLT.PLT entry. */ +/* Allocate space for a PLT entry. */ static bool allocate_global_data_plt (struct elf_link_hash_entry *eh, void *data) @@ -1046,37 +1079,41 @@ allocate_global_data_opd (struct elf_link_hash_entry *eh, void *data) struct elf64_hppa_link_hash_entry *hh = hppa_elf_hash_entry (eh); struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data; - if (hh && hh->want_opd) + if (hh->want_opd) { /* We never need an opd entry for a symbol which is not defined by this output file. */ - if (hh && (hh->eh.root.type == bfd_link_hash_undefined - || hh->eh.root.type == bfd_link_hash_undefweak - || hh->eh.root.u.def.section->output_section == NULL)) - hh->want_opd = 0; + if (hh->eh.root.type == bfd_link_hash_undefined + || hh->eh.root.type == bfd_link_hash_undefweak + || hh->eh.root.u.def.section->output_section == NULL) + { + hh->want_opd = 0; + return true; + } /* If we are creating a shared library, took the address of a local function or might export this function from this object file, then we have to create an opd descriptor. */ - else if (bfd_link_pic (x->info) - || hh == NULL - || (hh->eh.dynindx == -1 && hh->eh.type != STT_PARISC_MILLI) - || (hh->eh.root.type == bfd_link_hash_defined - || hh->eh.root.type == bfd_link_hash_defweak)) + if (bfd_link_pic (x->info) + || (hh->eh.dynindx == -1 && hh->eh.type != STT_PARISC_MILLI) + || hh->eh.root.type == bfd_link_hash_defined + || hh->eh.root.type == bfd_link_hash_defweak) { /* If we are creating a shared library, then we will have to create a runtime relocation for the symbol to properly initialize the .opd entry. Make sure the symbol gets added to the dynamic symbol table. */ - if (bfd_link_pic (x->info) - && (hh == NULL || (hh->eh.dynindx == -1))) + if (bfd_link_pic (x->info) && hh->eh.dynindx == -1) { - bfd *owner; /* PR 6511: Default to using the dynamic symbol table. */ - owner = (hh->owner ? hh->owner: eh->root.u.def.section->owner); + if (!hh->owner) + { + hh->owner = eh->root.u.def.section->owner; + hh->sym_indx = global_sym_index (eh); + } if (!bfd_elf_link_record_local_dynamic_symbol - (x->info, owner, hh->sym_indx)) + (x->info, hh->owner, hh->sym_indx)) return false; } @@ -1419,15 +1456,8 @@ allocate_dynrel_entries (struct elf_link_hash_entry *eh, void *data) if (!shared && rent->type == R_PARISC_FPTR64 && hh->want_opd) continue; - hppa_info->other_rel_sec->size += sizeof (Elf64_External_Rela); - - /* Make sure this symbol gets into the dynamic symbol table if it is - not already recorded. ?!? This should not be in the loop since - the symbol need only be added once. */ - if (eh->dynindx == -1 && eh->type != STT_PARISC_MILLI) - if (!bfd_elf_link_record_local_dynamic_symbol - (x->info, rent->sec->owner, hh->sym_indx)) - return false; + if (!discarded_section (hppa_info->other_rel_sec)) + hppa_info->other_rel_sec->size += sizeof (Elf64_External_Rela); } /* Take care of the GOT and PLT relocations. */ @@ -1555,7 +1585,7 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info) /* Set the contents of the .interp section to the interpreter. */ if (bfd_link_executable (info) && !info->nointerp) { - sec = bfd_get_linker_section (dynobj, ".interp"); + sec = hppa_info->root.interp; BFD_ASSERT (sec != NULL); sec->size = sizeof ELF_DYNAMIC_INTERPRETER; sec->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; @@ -2200,11 +2230,7 @@ elf64_hppa_finalize_dlt (struct elf_link_hash_entry *eh, void *data) sdlt = hppa_info->dlt_sec; sdltrel = hppa_info->dlt_rel_sec; - /* H/DYN_H may refer to a local variable and we know it's - address, so there is no need to create a relocation. Just install - the proper value into the DLT, note this shortcut can not be - skipped when building a shared library. */ - if (! bfd_link_pic (info) && hh && hh->want_dlt) + if (! bfd_link_pic (info) && hh->want_dlt) { bfd_vma value; @@ -2293,15 +2319,18 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh, if (!dynamic_symbol && !bfd_link_pic (info)) return true; + hppa_info = hppa_link_hash_table (info); + if (hppa_info == NULL) + return false; + + if (discarded_section (hppa_info->other_rel_sec)) + return true; + if (hh->reloc_entries) { struct elf64_hppa_dyn_reloc_entry *rent; int dynindx; - hppa_info = hppa_link_hash_table (info); - if (hppa_info == NULL) - return false; - /* We may need to do a relocation against a local symbol, in which case we have to look up it's dynamic symbol index off the local symbol hash table. */ @@ -2382,6 +2411,7 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh, else rel.r_addend = rent->addend; + BFD_ASSERT (dynindx != -1); rel.r_info = ELF64_R_INFO (dynindx, rent->type); loc = hppa_info->other_rel_sec->contents; @@ -3162,7 +3192,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, switch (r_type) { case R_PARISC_NONE: - break; + return bfd_reloc_ok; /* Basic function call support. @@ -3865,7 +3895,8 @@ elf64_hppa_relocate_section (bfd *output_bfd, if (sym_sec != NULL && discarded_section (sym_sec)) RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, - rel, 1, relend, howto, 0, contents); + rel, 1, relend, R_PARISC_NONE, + howto, 0, contents); if (bfd_link_relocatable (info)) continue; |