From: John David Anglin Date: Sun, 2 Nov 2025 21:04:55 +0000 (-0500) Subject: hppa64: Implement segment based relocations for local symbols X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e23cba69ec81f00d7404831f12bdfd4e981fe59d;p=thirdparty%2Fbinutils-gdb.git hppa64: Implement segment based relocations for local symbols There is progress in implementing 64-bit shared library support. Fixes link error compiling vdso64.so. HP-UX dynamic linker no longer complains that libgcc_s.4 linked with GNU ld is an invalid shared library. Relocations are now generated for all slots in .rela.data, .rela.dlt and .rela.opd. Relocation counts for libgcc_s.4 linked using GNU and HP ld are the same except .rela.plt. That may be okay as GNU ld directs pc-relative calls to stubs. Glibc's ld.so.new appears to link okay. However, libgcc_s.4 linked with GNU ld is still broken on HP-UX. There are six unexpected fails in the testsuite and three unexpected passes. There's at least one fail due to name munging in the .dynsym table. 2025-11-02 John David Anglin bfd/ChangeLog: * elf64-hppa.c (struct elf64_hppa_link_hash_entry): Remove sym_ind and owner fields. Rename hash entries for __text_seg and __data_seg. Adjust all users. (global_sym_index): Remove. (hppa64_elf_local_refcounts): Assert size is not 0. (elf64_hppa_check_relocs): Drop NEED_PLT from R_PARISC_FPTR64 relocation. Don't stash abfd and r_symndx in hh->owner and hh->sym_indx. Add global symbols with hh->eh.dynindx equal -1 to dynamic table. Don't record section symbols to the local dynamic symbol table. (allocate_global_data_dlt): Don't add symbol to local dynamic symbol table. (allocate_global_data_opd): Likewise. (elf64_hppa_late_size_sections): Rework code to add __text_seg and __data_seg symbols to the dynamic table. (elf64_hppa_finalize_dlt): Revise to use __text_seg and __data_seg symbols. (elf64_hppa_finalize_dynreloc): Likewise. (elf_hppa_final_link_relocate): When generating a shared library, ignore relocs in debugging sections. Revise relocations needing DLT and OPD dynamic relocations to output dynamic relocatios for local symbols. Move code to initialize segment base values back to SEGREL case. --- diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 4c60bc00939..682f1cbd11d 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -62,12 +62,6 @@ struct elf64_hppa_link_hash_entry bfd_vma opd_offset; bfd_vma stub_offset; - /* The index of the (possibly local) symbol in the input bfd and its - associated BFD. Needed so that we can have relocs against local - symbols in shared libraries. */ - long sym_indx; - bfd *owner; - /* Dynamic symbols may need to have two different values. One for the dynamic symbol table, one for the normal symbol table. @@ -137,9 +131,9 @@ struct elf64_hppa_link_hash_table bfd_vma text_segment_base; bfd_vma data_segment_base; - /* Hash entries for __text_seg and __data_seg. */ - struct elf_link_hash_entry *text_segment; - struct elf_link_hash_entry *data_segment; + /* Hash entries for __text_seg and __data_seg symbols. */ + struct elf_link_hash_entry *text_hash_entry; + struct elf_link_hash_entry *data_hash_entry; /* We build tables to map from an input section back to its symbol index. This is the BFD for which we currently have @@ -251,24 +245,6 @@ 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 * @@ -501,6 +477,7 @@ hppa64_elf_local_refcounts (bfd *abfd) counts. Done this way to save polluting elf_obj_tdata with another target specific pointer. */ size = symtab_hdr->sh_info; + BFD_ASSERT (size); size *= 3 * sizeof (bfd_signed_vma); local_refcounts = bfd_zalloc (abfd, size); elf_local_got_refcounts (abfd) = local_refcounts; @@ -776,24 +753,15 @@ elf64_hppa_check_relocs (bfd *abfd, /* This is a simple OPD entry. */ case R_PARISC_FPTR64: if (bfd_link_pic (info) || maybe_dynamic) - need_entry = (NEED_OPD | NEED_PLT | NEED_DYNREL); + need_entry = (NEED_OPD | NEED_DYNREL); else - need_entry = (NEED_OPD | NEED_PLT); + need_entry = (NEED_OPD); dynrel_type = R_PARISC_FPTR64; break; /* Add more cases as needed. */ } - /* We may need this information later for OPD. */ - if (hh) - { - /* Stash away enough information to be able to find this symbol - regardless of whether or not it is local or global. */ - hh->owner = abfd; - hh->sym_indx = r_symndx; - } - if (!need_entry) continue; @@ -900,18 +868,9 @@ elf64_hppa_check_relocs (bfd *abfd, /* Add symbol to dynamic symbol table. */ if (hh != NULL + && hh->eh.dynindx == -1 && 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 - symbol table. */ - if (bfd_link_pic (info) && dynrel_type == R_PARISC_FPTR64 - && ! (bfd_elf_link_record_local_dynamic_symbol - (info, abfd, sec_symndx))) + && ! (bfd_elf_link_record_dynamic_symbol (info, &hh->eh))) goto err_out; } } @@ -993,25 +952,6 @@ allocate_global_data_dlt (struct elf_link_hash_entry *eh, void *data) if (hh->want_dlt) { - if (bfd_link_pic (x->info)) - { - /* Possibly add the symbol to the local dynamic symbol - table since we might need to create a dynamic relocation - against it. */ - if (eh->dynindx == -1 && eh->type != STT_PARISC_MILLI) - { - 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, hh->owner, hh->sym_indx))) - return false; - } - } - hh->dlt_offset = x->ofs; x->ofs += DLT_ENTRY_SIZE; } @@ -1106,24 +1046,6 @@ allocate_global_data_opd (struct elf_link_hash_entry *eh, void *data) || 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->eh.dynindx == -1) - { - /* PR 6511: Default to using the dynamic symbol table. */ - 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, hh->owner, hh->sym_indx)) - return false; - } - hh->opd_offset = x->ofs; x->ofs += OPD_ENTRY_SIZE; } @@ -1710,50 +1632,58 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info) } /* Add __text_seg section symbol to dynamic table. */ - if (bfd_link_pic (info) && !hppa_info->text_segment) + if (bfd_link_pic (info) && !hppa_info->text_hash_entry) { - struct elf_link_hash_entry *nh; + asection *s; - nh = elf_link_hash_lookup (elf_hash_table (info), - "__text_seg", true, false, false); - if (nh != NULL) + s = bfd_get_section_by_name (info->output_bfd, ".dynamic"); + if (s != NULL) { - asection *s; - - s = bfd_get_section_by_name (info->output_bfd, ".dynamic"); + struct elf_link_hash_entry *nh; - nh->type = STT_SECTION; - nh->root.type = bfd_link_hash_defined; - nh->root.u.def.value = 0; - nh->root.u.def.section = s; - nh->forced_local = 1; - nh->other = STV_DEFAULT; - bfd_elf_link_record_dynamic_symbol (info, nh); - hppa_info->text_segment = nh; + nh = elf_link_hash_lookup (elf_hash_table (info), + "__text_seg", true, false, false); + if (nh != NULL) + { + nh->type = STT_SECTION; + nh->root.type = bfd_link_hash_defined; + nh->root.u.def.value = 0; + nh->root.u.def.section = s; + nh->forced_local = 1; + nh->other = STV_DEFAULT; + bfd_elf_link_record_dynamic_symbol (info, nh); + hppa_info->text_hash_entry = nh; + } } } /* Add __data_seg section symbol to dynamic table. */ - if (bfd_link_pic (info) && !hppa_info->data_segment) + if (bfd_link_pic (info) && !hppa_info->data_hash_entry) { - struct elf_link_hash_entry *nh; - - nh = elf_link_hash_lookup (elf_hash_table (info), - "__data_seg", true, false, false); - if (nh != NULL) + asection *s; + + /* The .data section isn't always present nor is it always the + first section in the data segment. It's too early to call + bfd_map_over_sections, so we assume we don't need any data + segment relocations when .data is missing. */ + s = bfd_get_section_by_name (info->output_bfd, ".data"); + if (s != NULL) { - asection *s; + struct elf_link_hash_entry *nh; - s = bfd_get_section_by_name (info->output_bfd, ".data"); - - nh->type = STT_SECTION; - nh->root.type = bfd_link_hash_defined; - nh->root.u.def.value = 0; - nh->root.u.def.section = s; - nh->forced_local = 1; - nh->other = STV_DEFAULT; - bfd_elf_link_record_dynamic_symbol (info, nh); - hppa_info->data_segment = nh; + nh = elf_link_hash_lookup (elf_hash_table (info), + "__data_seg", true, false, false); + if (nh != NULL) + { + nh->type = STT_SECTION; + nh->root.type = bfd_link_hash_defined; + nh->root.u.def.value = 0; + nh->root.u.def.section = s; + nh->forced_local = 1; + nh->other = STV_DEFAULT; + bfd_elf_link_record_dynamic_symbol (info, nh); + hppa_info->data_hash_entry = nh; + } } } @@ -2201,7 +2131,7 @@ elf64_hppa_finalize_opd (struct elf_link_hash_entry *eh, void *data) + eh->root.u.def.section->output_offset); /* Compute the base address of the segment with this symbol. */ - sec = hppa_info->text_segment->root.u.def.section; + sec = hppa_info->text_hash_entry->root.u.def.section; value2 = sec->output_section->vma; /* Compute the difference between the symbol and the text segment @@ -2211,7 +2141,7 @@ elf64_hppa_finalize_opd (struct elf_link_hash_entry *eh, void *data) /* The result becomes the addend of the relocation. */ rel.r_addend += value; - dynindx = hppa_info->text_segment->dynindx; + dynindx = hppa_info->text_hash_entry->dynindx; BFD_ASSERT (dynindx != -1); rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT); @@ -2284,16 +2214,34 @@ elf64_hppa_finalize_dlt (struct elf_link_hash_entry *eh, void *data) Elf_Internal_Rela rel; bfd_byte *loc; int dynindx; + asection *sec; + bfd_vma value, value2; + + if (eh->dynindx == -1) + { + value = (eh->root.u.def.value + + eh->root.u.def.section->output_section->vma + + eh->root.u.def.section->output_offset); - /* 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. */ - if (eh && eh->dynindx != -1) - dynindx = eh->dynindx; + if (eh->root.u.def.section->flags & SEC_READONLY) + { + sec = hppa_info->text_hash_entry->root.u.def.section; + value2 = sec->output_section->vma; + dynindx = hppa_info->text_hash_entry->dynindx; + } + else + { + sec = hppa_info->data_hash_entry->root.u.def.section; + value2 = sec->output_section->vma; + dynindx = hppa_info->data_hash_entry->dynindx; + } + rel.r_addend = value - value2; + } else - dynindx - = _bfd_elf_link_lookup_local_dynindx (info, hh->owner, - hh->sym_indx); + { + dynindx = eh->dynindx; + rel.r_addend = 0; + } /* Create a dynamic relocation for this entry. Do include the output offset of the DLT entry since we need an absolute address in the @@ -2304,7 +2252,6 @@ elf64_hppa_finalize_dlt (struct elf_link_hash_entry *eh, void *data) rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_FPTR64); else rel.r_info = ELF64_R_INFO (dynindx, R_PARISC_DIR64); - rel.r_addend = 0; loc = sdltrel->contents; loc += sdltrel->reloc_count++ * sizeof (Elf64_External_Rela); @@ -2342,16 +2289,6 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh, struct elf64_hppa_dyn_reloc_entry *rent; int dynindx; - /* 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. */ - if (eh->dynindx != -1) - dynindx = eh->dynindx; - else - dynindx - = _bfd_elf_link_lookup_local_dynindx (info, hh->owner, - hh->sym_indx); - for (rent = hh->reloc_entries; rent; rent = rent->next) { Elf_Internal_Rela rel; @@ -2393,6 +2330,7 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh, if (bfd_link_pic (info) && rent->type == R_PARISC_FPTR64 && hh->want_opd) { + asection *sec; bfd_vma value, value2; /* First compute the address of the opd entry for this symbol. */ @@ -2400,27 +2338,59 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh, + hppa_info->opd_sec->output_section->vma + hppa_info->opd_sec->output_offset); - /* Compute the value of the start of the section with - the relocation. */ - value2 = (rent->sec->output_section->vma - + rent->sec->output_offset); + if (hh->eh.dynindx != -1) + { + value2 = value; + dynindx = hh->eh.dynindx; + } + else if (rent->sec->flags & SEC_READONLY) + { + sec = hppa_info->text_hash_entry->root.u.def.section; + value2 = sec->output_section->vma; + dynindx = hppa_info->text_hash_entry->dynindx; + } + else + { + sec = hppa_info->data_hash_entry->root.u.def.section; + value2 = sec->output_section->vma; + dynindx = hppa_info->data_hash_entry->dynindx; + } /* Compute the difference between the start of the section with the relocation and the opd entry. */ value -= value2; /* The result becomes the addend of the relocation. */ - rel.r_addend = value; - - /* The section symbol becomes the symbol for the dynamic - relocation. */ - dynindx - = _bfd_elf_link_lookup_local_dynindx (info, - rent->sec->owner, - rent->sec_symndx); + rel.r_addend = value + rent->addend; + } + else if (eh->dynindx == -1) + { + asection *sec; + bfd_vma value, value2; + + value = (eh->root.u.def.value + + eh->root.u.def.section->output_section->vma + + eh->root.u.def.section->output_offset); + + if (eh->root.u.def.section->flags & SEC_READONLY) + { + sec = hppa_info->text_hash_entry->root.u.def.section; + value2 = sec->output_section->vma; + dynindx = hppa_info->text_hash_entry->dynindx; + } + else + { + sec = hppa_info->data_hash_entry->root.u.def.section; + value2 = sec->output_section->vma; + dynindx = hppa_info->data_hash_entry->dynindx; + } + rel.r_addend = value - value2 + rent->addend; } else - rel.r_addend = rent->addend; + { + dynindx = eh->dynindx; + rel.r_addend = rent->addend; + } BFD_ASSERT (dynindx != -1); rel.r_info = ELF64_R_INFO (dynindx, rent->type); @@ -3193,15 +3163,16 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, unsigned int r_type = howto->type; bfd_byte *hit_data = contents + offset; + /* Dynamic relocs are not propagated for SEC_DEBUGGING + sections because such sections are not SEC_ALLOC and + thus ld.so will not process them. */ + if (bfd_link_pic (info) + && (input_section->flags & SEC_DEBUGGING) != 0) + return bfd_reloc_ok; + if (hppa_info == NULL) return bfd_reloc_notsupported; - /* Initialize the segment base values. Needed for EPLT and SEGREL - relocations. */ - if (hppa_info->text_segment_base == (bfd_vma) -1) - bfd_map_over_sections (output_bfd, elf_hppa_record_segment_addrs, - hppa_info); - symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; local_offsets = elf_local_got_offsets (input_bfd); insn = bfd_get_32 (input_bfd, hit_data); @@ -3334,6 +3305,13 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, case R_PARISC_LTOFF16DF: { bfd_vma off; + bfd_vma relocation = value; + asection *sopd, *sopdrel; + bool need_dlt_reloc = false; + bool need_opd_reloc = false; + + sopd = hppa_info->opd_sec; + sopdrel = hppa_info->opd_rel_sec; /* If this relocation was against a local symbol, then we still have not set up the DLT entry (it's not convenient to do so @@ -3375,26 +3353,74 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, { local_opd_offsets[r_symndx] |= 1; + /* If we are generating a shared library, we need + a relocation for the local symbol. */ + if (bfd_link_pic (info)) + need_opd_reloc = true; + /* The first two words of an .opd entry are zero. */ - memset (hppa_info->opd_sec->contents + off, 0, 16); + memset (sopd->contents + off, 0, 16); /* The next word is the address of the function. */ - bfd_put_64 (hppa_info->opd_sec->owner, value + addend, - (hppa_info->opd_sec->contents + off + 16)); + bfd_put_64 (sopd->owner, value + addend, + sopd->contents + off + 16); /* The last word is our local __gp value. */ value = _bfd_get_gp_value (info->output_bfd); - bfd_put_64 (hppa_info->opd_sec->owner, value, - (hppa_info->opd_sec->contents + off + 24)); + bfd_put_64 (sopd->owner, value, + sopd->contents + off + 24); } - /* The DLT value is the address of the .opd entry. */ + /* The OPD value is the address of the .opd entry. */ value = (off - + hppa_info->opd_sec->output_offset - + hppa_info->opd_sec->output_section->vma); + + sopd->output_offset + + sopd->output_section->vma); addend = 0; } + if (need_opd_reloc) + { + Elf_Internal_Rela rela; + bfd_byte *loc; + int dynindx; + asection *sec; + + /* The offset of this relocation is the absolute address + of the .opd entry for this symbol. */ + rela.r_offset = (off + + sopd->output_offset + + sopd->output_section->vma); + + /* Select base segment. */ + if (sym_sec->flags & SEC_READONLY) + { + sec = hppa_info->text_hash_entry->root.u.def.section; + dynindx = hppa_info->text_hash_entry->dynindx; + } + else + { + sec = hppa_info->data_hash_entry->root.u.def.section; + dynindx = hppa_info->data_hash_entry->dynindx; + } + + /* Adjust the value with the difference between the + symbol's address and the base segment's address. */ + value += (relocation + addend + - sec->output_offset + - sec->output_section->vma); + + /* The result becomes the addend of the relocation. */ + rela.r_addend = value; + + dynindx = hppa_info->text_hash_entry->dynindx; + BFD_ASSERT (dynindx != -1); + rela.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT); + + loc = sopdrel->contents; + loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela); + bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc); + } + local_dlt_offsets = local_offsets; off = local_dlt_offsets[r_symndx]; @@ -3406,6 +3432,12 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, else { local_dlt_offsets[r_symndx] |= 1; + + /* If we are generating a shared library, we need + a relocation for the local symbol. */ + if (bfd_link_pic (info)) + need_dlt_reloc = true; + bfd_put_64 (hppa_info->dlt_sec->owner, value + addend, hppa_info->dlt_sec->contents + off); @@ -3445,6 +3477,50 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, value = hppa_field_adjust (value, 0, e_rsel); insn = elf_hppa_relocate_insn (insn, (int) value, r_type); + + if (need_dlt_reloc) + { + Elf_Internal_Rela rela; + bfd_byte *loc; + int dynindx; + asection *sec; + asection *sdlt, *sdltrel; + + sdlt = hppa_info->dlt_sec; + sdltrel = hppa_info->dlt_rel_sec; + + /* The offset of this relocation is the absolute address + of the .dlt entry. */ + rela.r_offset = (off + sdlt->output_offset + + sdlt->output_section->vma); + + if (sym_sec->flags & SEC_READONLY) + { + sec = hppa_info->text_hash_entry->root.u.def.section; + dynindx = hppa_info->text_hash_entry->dynindx; + } + else + { + sec = hppa_info->data_hash_entry->root.u.def.section; + dynindx = hppa_info->data_hash_entry->dynindx; + } + + /* Adjust value using the difference of the symbol's + location and the section symbol's address. */ + value += (relocation + addend + - sec->output_offset + - sec->output_section->vma); + + /* The result becomes the addend of the relocation. */ + rela.r_addend = value; + + BFD_ASSERT (dynindx != -1); + rela.r_info = ELF64_R_INFO (dynindx, R_PARISC_DIR64); + + loc = sdltrel->contents; + loc += sdltrel->reloc_count++ * sizeof (Elf64_External_Rela); + bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); + } break; } @@ -3691,6 +3767,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, bfd_vma relocation = value; asection *sopd; asection *sopdrel; + bool need_opd_reloc = false; sopd = hppa_info->opd_sec; sopdrel = hppa_info->opd_rel_sec; @@ -3701,7 +3778,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, { bfd_vma *local_opd_offsets; - if (local_offsets == NULL) + if (local_offsets == NULL || symtab_hdr->sh_info == 0) abort (); local_opd_offsets = local_offsets + 2 * symtab_hdr->sh_info; @@ -3716,6 +3793,13 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, } else { + local_opd_offsets[r_symndx] |= 1; + + /* If we are generating a shared library, we need + a relocation for the local symbol. */ + if (bfd_link_pic (info)) + need_opd_reloc = true; + /* The first two words of an .opd entry are zero. */ memset (hppa_info->opd_sec->contents + off, 0, 16); @@ -3740,12 +3824,10 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, bfd_put_64 (output_bfd, value, hit_data); - /* If we are generating a shared library, we must generate an - EPLT relocation for the symbol. */ - if (hh == NULL && bfd_link_pic (info)) + if (need_opd_reloc) { Elf_Internal_Rela rela; - bfd_byte *loc, *locend; + bfd_byte *loc; int dynindx; asection *sec; @@ -3754,28 +3836,27 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, rela.r_offset = (off + sopd->output_offset + sopd->output_section->vma); - /* Compute the difference between the symbol address - and the test segment base address. */ - sec = hppa_info->text_segment->root.u.def.section; - value = (relocation + addend - sec->output_section->vma); + /* Select base segment. */ + if (sym_sec->flags & SEC_READONLY) + { + sec = hppa_info->text_hash_entry->root.u.def.section; + dynindx = hppa_info->text_hash_entry->dynindx; + } + else + { + sec = hppa_info->data_hash_entry->root.u.def.section; + dynindx = hppa_info->data_hash_entry->dynindx; + } + + /* Compute the difference between the symbol's address + and the base segment's address. */ + value += (relocation + addend + - sec->output_offset + - sec->output_section->vma); /* The result becomes the addend of the relocation. */ rela.r_addend = value; - /* Ugh, the EPLT relocations must be unique! */ - locend = (sopdrel->contents - + sopdrel->reloc_count * sizeof (Elf64_External_Rela)); - for (loc = sopdrel->contents; loc < locend; - loc += sizeof (Elf64_External_Rela)) - { - Elf_Internal_Rela rela1; - - bfd_elf64_swap_reloca_in (info->output_bfd, loc, &rela1); - if (rela.r_addend == rela1.r_addend) - return bfd_reloc_ok; - } - - dynindx = hppa_info->text_segment->dynindx; BFD_ASSERT (dynindx != -1); rela.r_info = ELF64_R_INFO (dynindx, R_PARISC_EPLT); @@ -3796,6 +3877,11 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, case R_PARISC_SEGREL32: case R_PARISC_SEGREL64: { + /* Initialize the segment base values. */ + if (hppa_info->text_segment_base == (bfd_vma) -1) + bfd_map_over_sections (output_bfd, elf_hppa_record_segment_addrs, + hppa_info); + /* VALUE holds the absolute address. We want to include the addend, then turn it into a segment relative address.