MIPS: Fix the encoding of immediates with microMIPS JALX

The microMIPS JALX instruction shares the R_MICROMIPS_26_S1 relocation
with microMIPS J/JAL/JALS instructions, however unlike the latters its
encoded immediate argument is unusually shifted left by 2 rather than 1
in calculating the value used for the operation requested.

We already handle this exception in `mips_elf_calculate_relocation' in
LD, in a scenario where JALX is produced as a result of relaxing JAL for
the purpose of making a cross-mode jump.  We also get it right in the
disassembler in `decode_micromips_operand'.

What we don't correctly do however is processing microMIPS JALX produced
by GAS from an assembly source, where a non-zero constant argument or a
symbol reference with a non-zero in-place addend has been used.  In this
case the same calculation is made as for microMIPS J/JAL/JALS, causing
the wrong encoding to be produced by GAS on making an object file, and
then again by LD in the final link.  The latter in particular causes the
calculation, where the addend fits in the relocatable field, to produce
different final addresses for the same source code depending on whether
REL or RELA relocations are used.

Correct these issues by special-casing microMIPS JALX in the places that
have been previously missed.

	bfd/
	* elfxx-mips.c (mips_elf_read_rel_addend): Adjust the addend for
	microMIPS JALX.

	gas/
	* config/tc-mips.c (append_insn): Correct the encoding of a
	constant argument for microMIPS JALX.
	(tc_gen_reloc): Correct the encoding of an in-place addend for
	microMIPS JALX.
	* testsuite/gas/mips/jalx-addend.d: New test.
	* testsuite/gas/mips/jalx-addend-n32.d: New test.
	* testsuite/gas/mips/jalx-addend-n64.d: New test.
	* testsuite/gas/mips/jalx-imm.d: New test.
	* testsuite/gas/mips/jalx-imm-n32.d: New test.
	* testsuite/gas/mips/jalx-imm-n64.d: New test.
	* testsuite/gas/mips/jalx-addend.s: New test source.
	* testsuite/gas/mips/jalx-imm.s: New test source.
	* testsuite/gas/mips/mips.exp: Run the new tests.

	ld/
	* testsuite/ld-mips-elf/jalx-addend.d: New test.
	* testsuite/ld-mips-elf/jalx-addend-n32.d: New test.
	* testsuite/ld-mips-elf/jalx-addend-n64.d: New test.
	* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
This commit is contained in:
Maciej W. Rozycki 2016-05-20 13:32:19 +01:00
parent 134c0c8bf4
commit 17c6c9d9f3
18 changed files with 300 additions and 3 deletions

View File

@ -1,3 +1,8 @@
2016-05-20 Maciej W. Rozycki <macro@imgtec.com>
* elfxx-mips.c (mips_elf_read_rel_addend): Adjust the addend for
microMIPS JALX.
2016-05-19 H.J. Lu <hongjiu.lu@intel.com>
PR ld/20117

View File

@ -7780,16 +7780,24 @@ mips_elf_read_rel_addend (bfd *abfd, const Elf_Internal_Rela *rel,
bfd_byte *location;
unsigned int r_type;
bfd_vma addend;
bfd_vma bytes;
r_type = ELF_R_TYPE (abfd, rel->r_info);
location = contents + rel->r_offset;
/* Get the addend, which is stored in the input file. */
_bfd_mips_elf_reloc_unshuffle (abfd, r_type, FALSE, location);
addend = mips_elf_obtain_contents (howto, rel, abfd, contents);
bytes = mips_elf_obtain_contents (howto, rel, abfd, contents);
_bfd_mips_elf_reloc_shuffle (abfd, r_type, FALSE, location);
return addend & howto->src_mask;
addend = bytes & howto->src_mask;
/* Shift is 2, unusually, for microMIPS JALX. Adjust the addend
accordingly. */
if (r_type == R_MICROMIPS_26_S1 && (bytes >> 26) == 0x3c)
addend <<= 1;
return addend;
}
/* REL is a relocation in ABFD that needs a partnering LO16 relocation

View File

@ -1,3 +1,19 @@
2016-05-20 Maciej W. Rozycki <macro@imgtec.com>
* config/tc-mips.c (append_insn): Correct the encoding of a
constant argument for microMIPS JALX.
(tc_gen_reloc): Correct the encoding of an in-place addend for
microMIPS JALX.
* testsuite/gas/mips/jalx-addend.d: New test.
* testsuite/gas/mips/jalx-addend-n32.d: New test.
* testsuite/gas/mips/jalx-addend-n64.d: New test.
* testsuite/gas/mips/jalx-imm.d: New test.
* testsuite/gas/mips/jalx-imm-n32.d: New test.
* testsuite/gas/mips/jalx-imm-n64.d: New test.
* testsuite/gas/mips/jalx-addend.s: New test source.
* testsuite/gas/mips/jalx-imm.s: New test source.
* testsuite/gas/mips/mips.exp: Run the new tests.
2016-05-20 Maciej W. Rozycki <macro@imgtec.com>
* config/tc-mips.c: Correct tab-after-space formatting mistakes

View File

@ -7044,7 +7044,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
{
int shift;
shift = mips_opts.micromips ? 1 : 2;
/* Shift is 2, unusually, for microMIPS JALX. */
shift = (mips_opts.micromips
&& strcmp (ip->insn_mo->name, "jalx") != 0) ? 1 : 2;
if ((address_expr->X_add_number & ((1 << shift) - 1)) != 0)
as_bad (_("jump to misaligned address (0x%lx)"),
(unsigned long) address_expr->X_add_number);
@ -17225,6 +17227,15 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
Relocations want only the symbol offset. */
reloc->addend = fixp->fx_addnumber + reloc->address;
}
else if (HAVE_IN_PLACE_ADDENDS
&& fixp->fx_r_type == BFD_RELOC_MICROMIPS_JMP
&& (read_compressed_insn (fixp->fx_frag->fr_literal
+ fixp->fx_where, 4) >> 26) == 0x3c)
{
/* Shift is 2, unusually, for microMIPS JALX. Adjust the in-place
addend accordingly. */
reloc->addend = fixp->fx_addnumber >> 1;
}
else
reloc->addend = fixp->fx_addnumber;

View File

@ -0,0 +1,29 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS JAL/JALX addend encoding (n32)
#as: -n32 -march=from-abi
#source: jalx-addend.s
.*: +file format .*mips.*
Disassembly of section \.text:
\.\.\.
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f400 0000 jal 00000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MICROMIPS_26_S1 foo-0x3fffffe
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f000 0000 jalx 00000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MICROMIPS_26_S1 bar-0x7fffffc
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 0000 0000 nop
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 74000000 jalx 00000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MIPS_26 foo-0x7fffffc
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 0c000000 jal 00000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MIPS_26 bar-0x7fffffc
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
\.\.\.

View File

@ -0,0 +1,37 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS JAL/JALX addend encoding (n64)
#as: -64 -march=from-abi
#source: jalx-addend.s
.*: +file format .*mips.*
Disassembly of section \.text:
\.\.\.
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f400 0000 jal 0000000000000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MICROMIPS_26_S1 foo-0x3fffffe
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x3fffffe
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x3fffffe
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f000 0000 jalx 0000000000000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MICROMIPS_26_S1 bar-0x7fffffc
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x7fffffc
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x7fffffc
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 0000 0000 nop
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 74000000 jalx 0000000000000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MIPS_26 foo-0x7fffffc
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x7fffffc
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x7fffffc
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 0c000000 jal 0000000000000000 <foo-0x1000>
[ ]*[0-9a-f]+: R_MIPS_26 bar-0x7fffffc
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x7fffffc
[ ]*[0-9a-f]+: R_MIPS_NONE \*ABS\*-0x7fffffc
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
\.\.\.

View File

@ -0,0 +1,28 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS JAL/JALX addend encoding
#as: -32
.*: +file format .*mips.*
Disassembly of section \.text:
\.\.\.
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f600 0001 jal 04000002 <bar\+0x3ffefe2>
[ ]*[0-9a-f]+: R_MICROMIPS_26_S1 foo
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f200 0001 jalx 08000004 <bar\+0x7ffefe4>
[ ]*[0-9a-f]+: R_MICROMIPS_26_S1 bar
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 0000 0000 nop
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 76000001 jalx 08000004 <bar\+0x7ffefe4>
[ ]*[0-9a-f]+: R_MIPS_26 foo
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 0e000001 jal 08000004 <bar\+0x7ffefe4>
[ ]*[0-9a-f]+: R_MIPS_26 bar
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
\.\.\.

View File

@ -0,0 +1,35 @@
.text
.set noreorder
.space 0x1000
.align 4
.set micromips
.globl foo
.ent foo
foo:
nor $0, $0
jal foo - 0x3fffffe
nor $0, $0
jalx bar - 0x7fffffc
nor $0, $0
jalr $0, $ra
nor $0, $0
.end foo
.align 4
.set nomicromips
.globl bar
.ent bar
bar:
nor $0, $0
jalx foo - 0x7fffffc
nor $0, $0
jal bar - 0x7fffffc
nor $0, $0
jalr $0, $ra
nor $0, $0
.end bar
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16

View File

@ -0,0 +1,5 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS JAL/JALX immediate operand encoding (n32)
#as: -n32 -march=from-abi
#source: jalx-imm.s
#dump: jalx-imm.d

View File

@ -0,0 +1,5 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS JAL/JALX immediate operand encoding (n64)
#as: -64 -march=from-abi
#source: jalx-imm.s
#dump: jalx-imm.d

View File

@ -0,0 +1,24 @@
#objdump: -dr --prefix-addresses --show-raw-insn
#name: MIPS JAL/JALX immediate operand encoding
#as: -32
.*: +file format .*mips.*
Disassembly of section \.text:
\.\.\.
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f600 0001 jal 0+4000002 <bar\+0x3ffefe2>
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f200 0001 jalx 0+8000004 <bar\+0x7ffefe4>
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 0000 0000 nop
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 76000001 jalx 0+8000004 <bar\+0x7ffefe4>
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 0e000001 jal 0+8000004 <bar\+0x7ffefe4>
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
\.\.\.

View File

@ -0,0 +1,35 @@
.text
.set noreorder
.space 0x1000
.align 4
.set micromips
.globl foo
.ent foo
foo:
nor $0, $0
jal 0x4000002
nor $0, $0
jalx 0x8000004
nor $0, $0
jalr $0, $ra
nor $0, $0
.end foo
.align 4
.set nomicromips
.globl bar
.ent bar
bar:
nor $0, $0
jalx 0x8000004
nor $0, $0
jal 0x8000004
nor $0, $0
jalr $0, $ra
nor $0, $0
.end bar
# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
.align 4, 0
.space 16

View File

@ -794,6 +794,14 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "mips16-jalx"
run_dump_test "mips-jalx"
run_dump_test "mips-jalx-2"
run_dump_test "jalx-imm"
run_dump_test "jalx-addend"
if $has_newabi {
run_dump_test "jalx-imm-n32"
run_dump_test "jalx-addend-n32"
run_dump_test "jalx-imm-n64"
run_dump_test "jalx-addend-n64"
}
# Check MIPS16 HI16/LO16 relocations
run_dump_test "mips16-hilo"
if $has_newabi {

View File

@ -1,3 +1,10 @@
2016-05-20 Maciej W. Rozycki <macro@imgtec.com>
* testsuite/ld-mips-elf/jalx-addend.d: New test.
* testsuite/ld-mips-elf/jalx-addend-n32.d: New test.
* testsuite/ld-mips-elf/jalx-addend-n64.d: New test.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
2016-05-19 H.J. Lu <hongjiu.lu@intel.com>
PR ld/20117

View File

@ -0,0 +1,6 @@
#name: MIPS JAL/JALX addend calculation (n32)
#source: ../../../gas/testsuite/gas/mips/jalx-addend.s
#as: -EB -n32 -march=from-abi
#ld: -EB -Ttext 0x1c000000 -e 0x1c000000
#objdump: -dr --prefix-addresses --show-raw-insn
#dump: jalx-addend.d

View File

@ -0,0 +1,6 @@
#name: MIPS JAL/JALX addend calculation (n64)
#source: ../../../gas/testsuite/gas/mips/jalx-addend.s
#as: -EB -64 -march=from-abi
#ld: -EB -Ttext 0x1c000000 -e 0x1c000000
#objdump: -dr --prefix-addresses --show-raw-insn
#dump: jalx-addend.d

View File

@ -0,0 +1,26 @@
#name: MIPS JAL/JALX addend calculation
#source: ../../../gas/testsuite/gas/mips/jalx-addend.s
#as: -EB -32
#ld: -EB -Ttext 0x1c000000 -e 0x1c000000
#objdump: -dr --prefix-addresses --show-raw-insn
.*: +file format .*mips.*
Disassembly of section \.text:
\.\.\.
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f400 0801 jal 0*18001002 <.*>
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> f100 0409 jalx 0*14001024 <.*>
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 001f 0f3c jr ra
[0-9a-f]+ <[^>]*> 0000 02d0 not zero,zero
[0-9a-f]+ <[^>]*> 0000 0000 nop
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 75000401 jalx 0*14001004 <.*>
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 0d000409 jal 0*14001024 <.*>
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
[0-9a-f]+ <[^>]*> 03e00009 jalr zero,ra
[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
\.\.\.

View File

@ -168,6 +168,12 @@ if { $linux_gnu } {
"jalx-2"]]
}
run_dump_test "jalx-addend" [list [list ld $abi_ldflags(o32)]]
if $has_newabi {
run_dump_test "jalx-addend-n32" [list [list ld $abi_ldflags(n32)]]
run_dump_test "jalx-addend-n64" [list [list ld $abi_ldflags(n64)]]
}
# Test multi-got link. We only do this on GNU/Linux because it requires
# the "traditional" emulations.
if { $linux_gnu } {