[committed] hppa64: Handle R_PARISC_EPLT relocations for local symbols

John David Anglin dave.anglin@bell.net
Mon Oct 27 20:23:20 GMT 2025


This is first step in adding relocation support for local symbols.

Committed to trunk.

Dave
---

hppa64: Handle R_PARISC_EPLT relocations for local symbols

2025-10-27  John David Anglin  <danglin@gcc.gnu.org>

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..5d7f19b4373 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -3740,6 +3753,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 +3785,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 +3798,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;
       }
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20251027/97fbbf55/attachment.sig>


More information about the Binutils mailing list