aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-mips.c
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-08-04 16:32:34 +0000
committerMark Mitchell <mark@codesourcery.com>1999-08-04 16:32:34 +0000
commite7c4421855a609e38b9398280c543dc9a9ef54f8 (patch)
treec93fe6b4b42105a9a6f02c7c504b12104c83713f /bfd/elf32-mips.c
parenteecb386cd7d2df28baf22c22ba3b0a3a4e94fcd5 (diff)
downloadgdb-e7c4421855a609e38b9398280c543dc9a9ef54f8.zip
gdb-e7c4421855a609e38b9398280c543dc9a9ef54f8.tar.gz
gdb-e7c4421855a609e38b9398280c543dc9a9ef54f8.tar.bz2
* elf32-mips.c (_bfd_mips_elf_relocate_section): Tweak HI16/LO16
handling for REL relocations. And only left-shift R_MIPS26 relocation addends where necessary.
Diffstat (limited to 'bfd/elf32-mips.c')
-rw-r--r--bfd/elf32-mips.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 9d963cc..9b6e710 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -6528,7 +6528,13 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
const Elf_Internal_Rela *lo16_relocation;
reloc_howto_type *lo16_howto;
- /* Scan ahead to find a matching R_MIPS_LO16
+ /* 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.)
+
+ Scan ahead to find a matching R_MIPS_LO16
relocation. */
lo16_relocation
= mips_elf_next_lo16_relocation (rel, relend);
@@ -6541,6 +6547,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
lo16_relocation,
input_bfd, contents);
l &= lo16_howto->src_mask;
+ l = mips_elf_sign_extend (l, 16);
/* Save the high-order bit for later. When we
encounter the R_MIPS_LO16 relocation we will need
@@ -6550,7 +6557,7 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
last_hi16_addend_valid_p = true;
/* Compute the combined addend. */
- addend |= l;
+ addend += l;
}
else if (r_type == R_MIPS_LO16)
{
@@ -6571,11 +6578,6 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
| ((addend & 0x7e00000) >> 16)
| (addend & 0x1f));
}
- else if (r_type == R_MIPS16_26
- || r_type == R_MIPS16_26)
- /* The addend is stored without its two least
- significant bits (which are always zero.) */
- addend <<= 2;
}
else
addend = rel->r_addend;
@@ -6608,6 +6610,12 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|| r_type == R_MIPS_GPREL32)
addend -= (_bfd_get_gp_value (output_bfd)
- _bfd_get_gp_value (input_bfd));
+ else if (r_type == R_MIPS16_26 || r_type == R_MIPS16_26)
+ /* The addend is stored without its two least
+ significant bits (which are always zero.) In a
+ non-relocateable link, calculate_relocation will do
+ this shift; here, we must do it ourselves. */
+ addend <<= 2;
/* If the relocation is for a R_MIPS_HI16 or R_MIPS_GOT16,
then we only want to write out the high-order 16 bits.