]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
hppa64: Fix some issues handling dynamic relocaltions
authorJohn David Anglin <danglin@gcc.gnu.org>
Tue, 4 Nov 2025 21:00:04 +0000 (16:00 -0500)
committerJohn David Anglin <danglin@gcc.gnu.org>
Tue, 4 Nov 2025 21:00:04 +0000 (16:00 -0500)
This change fixes the allocation logic in allocate_dynrel_entries and
elf64_hppa_finalize_dynreloc.  It also fixes addend calculation for
segment based relocations.

Some applications now link successfully on HP-UX but there are still
issues with external weak symbols.  This breaks linking with libgcc.
It looks like we need support for .rela.data.rel.ro, ...

2025-11-04  John David Anglin  <danglin@gcc.gnu.org>

bfd/ChangeLog:

* elf64-hppa.c (allocate_dynrel_entries): Correct hh->want_opd
if condition.
(elf64_hppa_finalize_dynreloc): Likewise.  Use symbol address
instead of OPD address.  Include sec->output_offset in value2
calculation.
(elf64_hppa_finalize_opd): Likewise.
(elf64_hppa_finalize_dlt): Likewise.
(elf_hppa_final_link_relocate): Fix symbol address calculation.

bfd/elf64-hppa.c

index 682f1cbd11d0c5e1e5ddfc624f28a0a628bd22a0..42434b3a2ef93e0790b86f2847963cde3abf99dc 100644 (file)
@@ -1358,8 +1358,8 @@ allocate_dynrel_entries (struct elf_link_hash_entry *eh, void *data)
   for (rent = hh->reloc_entries; rent; rent = rent->next)
     {
       /* Allocate one iff we are building a shared library, the relocation
-        isn't a R_PARISC_FPTR64, or we don't want an opd entry.  */
-      if (!shared && rent->type == R_PARISC_FPTR64 && hh->want_opd)
+        isn't a R_PARISC_FPTR64, and we want an opd entry.  */
+      if (!shared && rent->type == R_PARISC_FPTR64 && !hh->want_opd)
        continue;
 
       if (!discarded_section (hppa_info->other_rel_sec))
@@ -2132,7 +2132,7 @@ elf64_hppa_finalize_opd (struct elf_link_hash_entry *eh, void *data)
 
       /* Compute the base address of the segment with this symbol.  */
       sec = hppa_info->text_hash_entry->root.u.def.section;
-      value2 = sec->output_section->vma;
+      value2 = sec->output_offset + sec->output_section->vma;
 
       /* Compute the difference between the symbol and the text segment
         base address.  */
@@ -2226,13 +2226,13 @@ elf64_hppa_finalize_dlt (struct elf_link_hash_entry *eh, void *data)
          if (eh->root.u.def.section->flags & SEC_READONLY)
            {
              sec = hppa_info->text_hash_entry->root.u.def.section;
-             value2 = sec->output_section->vma;
+             value2 = sec->output_offset + 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;
+             value2 = sec->output_offset + sec->output_section->vma;
              dynindx = hppa_info->data_hash_entry->dynindx;
            }
          rel.r_addend = value - value2;
@@ -2295,9 +2295,9 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
          bfd_byte *loc;
 
          /* Allocate one iff we are building a shared library, the relocation
-            isn't a R_PARISC_FPTR64, or we don't want an opd entry.  */
+            isn't a R_PARISC_FPTR64, or we want an opd entry.  */
          if (!bfd_link_pic (info)
-             && rent->type == R_PARISC_FPTR64 && hh->want_opd)
+             && rent->type == R_PARISC_FPTR64 && !hh->want_opd)
            continue;
 
          /* Create a dynamic relocation for this entry.
@@ -2333,10 +2333,10 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
              asection *sec;
              bfd_vma value, value2;
 
-             /* First compute the address of the opd entry for this symbol.  */
-             value = (hh->opd_offset
-                      + hppa_info->opd_sec->output_section->vma
-                      + hppa_info->opd_sec->output_offset);
+             /* Compute the address of the symbol.  */
+             value = (eh->root.u.def.value
+                      + eh->root.u.def.section->output_section->vma
+                      + eh->root.u.def.section->output_offset);
 
              if (hh->eh.dynindx != -1)
                {
@@ -2346,13 +2346,13 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
              else if (rent->sec->flags & SEC_READONLY)
                {
                  sec = hppa_info->text_hash_entry->root.u.def.section;
-                 value2 = sec->output_section->vma;
+                 value2 = sec->output_offset + 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;
+                 value2 = sec->output_offset + sec->output_section->vma;
                  dynindx = hppa_info->data_hash_entry->dynindx;
                }
 
@@ -2375,13 +2375,13 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
              if (eh->root.u.def.section->flags & SEC_READONLY)
                {
                  sec = hppa_info->text_hash_entry->root.u.def.section;
-                 value2 = sec->output_section->vma;
+                 value2 = sec->output_offset + 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;
+                 value2 = sec->output_offset + sec->output_section->vma;
                  dynindx = hppa_info->data_hash_entry->dynindx;
                }
              rel.r_addend = value - value2 + rent->addend;
@@ -3403,11 +3403,11 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
                    dynindx = hppa_info->data_hash_entry->dynindx;
                  }
 
-               /* Adjust the value with the difference between the
+               /* Adjust the addend with the difference between the
                   symbol's address and the base segment's address.  */
-               value += (relocation + addend
-                         - sec->output_offset
-                         - sec->output_section->vma);
+               value = (relocation + addend
+                        - sec->output_offset
+                        - sec->output_section->vma);
 
                /* The result becomes the addend of the relocation.  */
                rela.r_addend = value;
@@ -3505,11 +3505,11 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
                dynindx = hppa_info->data_hash_entry->dynindx;
              }
 
-           /* Adjust value using the difference of the symbol's
+           /* Adjust addend using the difference of the symbol's
               location and the section symbol's address.  */
-           value += (relocation + addend
-                     - sec->output_offset
-                     - sec->output_section->vma);
+           value = (relocation + addend
+                    - sec->output_offset
+                    - sec->output_section->vma);
 
            /* The result becomes the addend of the relocation.  */
            rela.r_addend = value;
@@ -3850,9 +3850,9 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
 
            /* Compute the difference between the symbol's address
               and the base segment's address.  */
-           value += (relocation + addend
-                     - sec->output_offset
-                     - sec->output_section->vma);
+           value = (relocation + addend
+                    - sec->output_offset
+                    - sec->output_section->vma);
 
            /* The result becomes the addend of the relocation.  */
            rela.r_addend = value;