]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
MIPS/BFD: Fix ELF link orphan REL HI16 relocation addend processing
authorMaciej W. Rozycki <macro@orcam.me.uk>
Wed, 14 Jan 2026 22:28:44 +0000 (22:28 +0000)
committerMaciej W. Rozycki <macro@orcam.me.uk>
Wed, 14 Jan 2026 22:28:44 +0000 (22:28 +0000)
Correct the addend being ignored for orphan REL HI16 relocations.

For ELF links `_bfd_mips_elf_relocate_section' handles relocation and
uses `mips_elf_add_lo16_rel_addend' to shift the incoming HI16 in-place
addend into its intended [31:16] bit positions and combine it with the
LO16 part.  If no matching LO16 reloc has been found, then the function
returns early and consequently the incoming HI16 addend is not shifted
and remains in bits [0:15].  For final links any value of the symbol
referred is then added.  Then the final value is shifted back into bits
[0:15] for installation into the field relocated.  It is obviously wrong
as the original HI16 in-place addend has now been lost.

Fix the issue by shifting the incoming HI16 in-place addend before using
`mips_elf_next_relocation' to find the matching LO16 relocation.  Then
upon early return from `mips_elf_add_lo16_rel_addend' the addend is in
the intended [31:16] bit positions already.

Test cases will be added with a separate change.

bfd/elfxx-mips.c

index f4424aca5042fa1821003305c2471e5fa76dc755..d3d989eae82a1472a1b3f48ec945194375bf61d4 100644 (file)
@@ -8370,9 +8370,10 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
   /* The combined value is the sum of the HI16 addend, left-shifted by
      sixteen bits, and the LO16 addend, sign extended.  (Usually, the
      code does a `lui' of the HI16 value, and then an `addiu' of the
-     LO16 value.)
+     LO16 value.)  */
+  *addend <<= 16;
 
-     Scan ahead to find a matching LO16 relocation.
+  /* Scan ahead to find a matching LO16 relocation.
 
      According to the MIPS ELF ABI, the R_MIPS_LO16 relocation must
      be immediately following.  However, for the IRIX6 ABI, the next
@@ -8400,7 +8401,6 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
     l = (l - (lo16_relocation->r_offset - rel->r_offset)) & 0xffff;
   l = _bfd_mips_elf_sign_extend (l, 16);
 
-  *addend <<= 16;
   *addend += l;
   return true;
 }