From: John David Anglin Date: Mon, 27 Oct 2025 20:13:37 +0000 (-0400) Subject: hppa64: Handle R_PARISC_EPLT relocations for local symbols X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fe283008513f610bc2fa3ca4536904b87a1f5d8a;p=thirdparty%2Fbinutils-gdb.git hppa64: Handle R_PARISC_EPLT relocations for local symbols 2025-10-27 John David Anglin bfd/ChangeLog: * elf64-hppa.c (elf_hppa_final_link_relocate): Handle R_PARISC_EPLT relocations for local symbols. --- diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 5bfa0d58883..094289a7f0b 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -3740,6 +3740,12 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, case R_PARISC_FPTR64: { bfd_vma off; + bfd_vma relocation = value; + asection *sopd; + asection *sopdrel; + + sopd = hppa_info->opd_sec; + sopdrel = hppa_info->opd_rel_sec; /* We may still need to create the FPTR itself if it was for a local symbol. */ @@ -3766,13 +3772,12 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, memset (hppa_info->opd_sec->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); } } else @@ -3780,14 +3785,55 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel, if (hh == NULL || hh->want_opd) /* We want the value of the OPD offset for this symbol. */ - value = (off - + hppa_info->opd_sec->output_offset - + hppa_info->opd_sec->output_section->vma); + value = off + sopd->output_offset + sopd->output_section->vma; else /* We want the address of the symbol. */ value += addend; 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)) + { + Elf_Internal_Rela rela; + bfd_byte *loc, *locend; + int dynindx; + + /* 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); + + /* Compute the difference between the symbol address + and the test segment base address. */ + value = relocation + addend - hppa_info->text_segment_base; + + /* 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); + + loc = sopdrel->contents; + loc += sopdrel->reloc_count++ * sizeof (Elf64_External_Rela); + bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc); + } + return bfd_reloc_ok; }