This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] 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.
---

 I have applied this change.

  Maciej

binutils-umips-jalx-shift.diff
Index: binutils/bfd/elfxx-mips.c
===================================================================
--- binutils.orig/bfd/elfxx-mips.c	2016-05-20 08:46:40.394252168 +0100
+++ binutils/bfd/elfxx-mips.c	2016-05-20 09:08:55.689448103 +0100
@@ -7780,16 +7780,24 @@ mips_elf_read_rel_addend (bfd *abfd, con
   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
Index: binutils/gas/config/tc-mips.c
===================================================================
--- binutils.orig/gas/config/tc-mips.c	2016-05-20 08:46:40.483717016 +0100
+++ binutils/gas/config/tc-mips.c	2016-05-20 09:08:55.839984515 +0100
@@ -7044,7 +7044,9 @@ append_insn (struct mips_cl_insn *ip, ex
 	  {
 	    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 ATTRIBUT
 	 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;
 
Index: binutils/gas/testsuite/gas/mips/jalx-addend-n32.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-addend-n32.d	2016-05-20 12:28:40.603697689 +0100
@@ -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
+	\.\.\.
Index: binutils/gas/testsuite/gas/mips/jalx-addend-n64.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-addend-n64.d	2016-05-20 12:28:40.630296076 +0100
@@ -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
+	\.\.\.
Index: binutils/gas/testsuite/gas/mips/jalx-addend.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-addend.d	2016-05-20 12:28:40.640518487 +0100
@@ -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
+	\.\.\.
Index: binutils/gas/testsuite/gas/mips/jalx-addend.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-addend.s	2016-05-20 12:28:40.648803371 +0100
@@ -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
Index: binutils/gas/testsuite/gas/mips/jalx-imm-n32.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-imm-n32.d	2016-05-20 12:28:40.654954150 +0100
@@ -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
Index: binutils/gas/testsuite/gas/mips/jalx-imm-n64.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-imm-n64.d	2016-05-20 12:28:40.666399331 +0100
@@ -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
Index: binutils/gas/testsuite/gas/mips/jalx-imm.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-imm.d	2016-05-20 12:28:40.693207133 +0100
@@ -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
+	\.\.\.
Index: binutils/gas/testsuite/gas/mips/jalx-imm.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/gas/testsuite/gas/mips/jalx-imm.s	2016-05-20 12:28:40.705666037 +0100
@@ -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
Index: binutils/gas/testsuite/gas/mips/mips.exp
===================================================================
--- binutils.orig/gas/testsuite/gas/mips/mips.exp	2016-05-20 12:28:30.531609820 +0100
+++ binutils/gas/testsuite/gas/mips/mips.exp	2016-05-20 12:28:40.718148756 +0100
@@ -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 {
Index: binutils/ld/testsuite/ld-mips-elf/jalx-addend-n32.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-mips-elf/jalx-addend-n32.d	2016-05-20 12:28:40.782387671 +0100
@@ -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
Index: binutils/ld/testsuite/ld-mips-elf/jalx-addend-n64.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-mips-elf/jalx-addend-n64.d	2016-05-20 12:28:40.790660181 +0100
@@ -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
Index: binutils/ld/testsuite/ld-mips-elf/jalx-addend.d
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-mips-elf/jalx-addend.d	2016-05-20 12:28:40.827997956 +0100
@@ -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
+	\.\.\.
Index: binutils/ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
--- binutils.orig/ld/testsuite/ld-mips-elf/mips-elf.exp	2016-05-20 12:28:30.661958229 +0100
+++ binutils/ld/testsuite/ld-mips-elf/mips-elf.exp	2016-05-20 12:28:40.839501374 +0100
@@ -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 } {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]