MIPS/BFD: Fix ELF link orphan REL HI16 relocation addend processing

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.
This commit is contained in:
Maciej W. Rozycki
2026-01-14 22:28:44 +00:00
parent 3f467fba80
commit a85a420984

View 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;
}