This is the mail archive of the binutils@sources.redhat.com 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]

[patch] RFD: Incorrect R_MIPS_26 handling for RELA


On Tue, 4 Jun 2002, Maciej W. Rozycki wrote:

>  How about R_MIPS_26 relocs?  I discovered they are broken for the 64 ABI
> (likely a RELA problem) and I am currently working on a fix.  As a result
> of the bug a kernel executable is useless. 

 OK, I've tracked the bug down.  The problem is for RELA R_MIPS_26
relocations the addend isn't shifted right.  I get a broken executable for
the following simple program:

$ cat r_mips_26.s
	.file	1 "r_mips_26.c"
	.section	.text
	.version	"01.01"
gcc2_compiled.:
	.text
	.align	2
	.globl	dummy
	.ent	dummy
dummy:
	.frame	$sp,0,$31		# vars= 0, regs= 0/0, args= 0, extra= 0
	.mask	0x00000000,0
	.fmask	0x00000000,0
	j	$31
	.end	dummy
	.align	2
	.ent	test
test:
	.frame	$sp,0,$31		# vars= 0, regs= 0/0, args= 0, extra= 0
	.mask	0x00000000,0
	.fmask	0x00000000,0
	j	$31
	.end	test
	.align	2
	.globl	__start
	.ent	__start
__start:
	.frame	$sp,16,$31		# vars= 0, regs= 1/0, args= 0, extra= 0
	.mask	0x80000000,-16
	.fmask	0x00000000,0
	dsubu	$sp,$sp,16
	sd	$31,0($sp)
	jal	test
	ld	$31,0($sp)
	#nop
	.set	noreorder
	.set	nomacro
	j	$31
	daddu	$sp,$sp,16
	.set	macro
	.set	reorder

	.end	__start
$ mips64el-linux-as -mips3 -64 -o r_mips_26.o r_mips_26.s
$ mips64el-linux-objdump -Sr r_mips_26.o

r_mips_26.o:     file format elf64-tradlittlemips

Disassembly of section .text:

0000000000000000 <dummy>:
   0:	03e00008 	jr	ra
   4:	00000000 	nop

0000000000000008 <test>:
   8:	03e00008 	jr	ra
   c:	00000000 	nop

0000000000000010 <__start>:
  10:	67bdfff0 	daddiu	sp,sp,-16
  14:	ffbf0000 	sd	ra,0(sp)
  18:	0c000000 	jal	0 <dummy>
			18: R_MIPS_26	.text+0x8
  1c:	00000000 	nop
  20:	dfbf0000 	ld	ra,0(sp)
  24:	03e00008 	jr	ra
  28:	67bd0010 	daddiu	sp,sp,16
  2c:	00000000 	nop

So far, so good.  Or at least it looks so.

$ mips64el-linux-ld -o r_mips_26 r_mips_26.o
$ mips64el-linux-objdump -S r_mips_26

r_mips_26:     file format elf64-tradlittlemips

Disassembly of section .text:

00000001200000e0 <dummy>:
   1200000e0:	03e00008 	jr	ra
   1200000e4:	00000000 	nop

00000001200000e8 <test>:
   1200000e8:	03e00008 	jr	ra
   1200000ec:	00000000 	nop

00000001200000f0 <__start>:
   1200000f0:	67bdfff0 	daddiu	sp,sp,-16
   1200000f4:	ffbf0000 	sd	ra,0(sp)
   1200000f8:	0c000040 	jal	120000100 <__start+0x10>
   1200000fc:	00000000 	nop
   120000100:	dfbf0000 	ld	ra,0(sp)
   120000104:	03e00008 	jr	ra
   120000108:	67bd0010 	daddiu	sp,sp,16
   12000010c:	00000000 	nop

Now it doesn't even look good anymore.

 Here is a patch I created that makes binutils produce good executables. 
It right-shifts R_MIPS_26 addends for writing to RELA sections like it
does for REL.  I'm unsure if that's the optimal solution.  The alternative
could be not to left-shift R_MIPS_26 addends when reading from RELA
sections.

 I chose this approach is there is nowhere stated R_MIPS_26 addends should
be calculated differently depending on whether REL or RELA is used. 
Specifically, "64-bit ELF Object File Specification" from SGI (basically
the MIPS supplement for the 64-bit ABI) specifies this calculation
uniformly for both relocation formats (table 32 in section 2.9.2), even
though it contains explicit statements about REL and RELA specifics with
respect to other relocation types.  Also "System V Application Binary
Interface" (aka the General ABI) doesn't provide any specific comments
about addends in RELA relocations. 

 From the technical point of view, there is no advantage with either
approach, apart from, possibly a better aesthetical consistency with the
one I chose.  Therefore I think the decision should be taken based upon
how original MIPS and/or SGI tools handle this case.  Can anyone please
check what they do?

 A patch follows.  With the patch I get:

$ mips64el-linux-objdump -Sr r_mips_26-1.o
r_mips_26-1.o:     file format elf64-tradlittlemips

Disassembly of section .text:

0000000000000000 <dummy>:
   0:	03e00008 	jr	ra
   4:	00000000 	nop

0000000000000008 <test>:
   8:	03e00008 	jr	ra
   c:	00000000 	nop

0000000000000010 <__start>:
  10:	67bdfff0 	daddiu	sp,sp,-16
  14:	ffbf0000 	sd	ra,0(sp)
  18:	0c000000 	jal	0 <dummy>
			18: R_MIPS_26	.text+0x2
  1c:	00000000 	nop
  20:	dfbf0000 	ld	ra,0(sp)
  24:	03e00008 	jr	ra
  28:	67bd0010 	daddiu	sp,sp,16
  2c:	00000000 	nop

The output will have to be fixed for this approach for the final patch.

$ mips64el-linux-objdump -S r_mips_26-1

r_mips_26-1:     file format elf64-tradlittlemips

Disassembly of section .text:

00000001200000e0 <dummy>:
   1200000e0:	03e00008 	jr	ra
   1200000e4:	00000000 	nop

00000001200000e8 <test>:
   1200000e8:	03e00008 	jr	ra
   1200000ec:	00000000 	nop

00000001200000f0 <__start>:
   1200000f0:	67bdfff0 	daddiu	sp,sp,-16
   1200000f4:	ffbf0000 	sd	ra,0(sp)
   1200000f8:	0c00003a 	jal	1200000e8 <test>
   1200000fc:	00000000 	nop
   120000100:	dfbf0000 	ld	ra,0(sp)
   120000104:	03e00008 	jr	ra
   120000108:	67bd0010 	daddiu	sp,sp,16
   12000010c:	00000000 	nop

The executable is correct.

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: macro@ds2.pg.gda.pl, PGP key available        +

binutils-2.12.90-20020603-mips64_26.patch
diff -up --recursive --new-file binutils.macro/bfd/elf64-mips.c binutils/bfd/elf64-mips.c
--- binutils.macro/bfd/elf64-mips.c	2002-04-05 03:25:28.000000000 +0000
+++ binutils/bfd/elf64-mips.c	2002-06-05 08:32:38.000000000 +0000
@@ -106,6 +106,8 @@ static bfd_reloc_status_type mips_elf64_
   PARAMS ((bfd *, arelent *, asymbol *,	PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf64_highest_reloc
   PARAMS ((bfd *, arelent *, asymbol *,	PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type mips_elf64_26_reloca
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf64_gprel16_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static bfd_reloc_status_type mips_elf64_gprel16_reloca
@@ -745,7 +747,7 @@ static reloc_howto_type mips_elf64_howto
 				/* This needs complex overflow
 				   detection, because the upper 36
 				   bits must match the PC + 4.  */
-	 bfd_elf_generic_reloc,	/* special_function */
+	 mips_elf64_26_reloca,	/* special_function */
 	 "R_MIPS_26",		/* name */
 	 false,			/* partial_inplace */
 	 0,			/* src_mask */
@@ -1614,6 +1616,35 @@ mips_elf64_final_gp (output_bfd, symbol,
   return bfd_reloc_ok;
 }
 
+/* Do a R_MIPS_26 RELA relocation.  */
+
+bfd_reloc_status_type
+mips_elf64_26_reloca (abfd, reloc_entry, symbol, data, input_section,
+			   output_bfd, error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message;
+{
+  /* If we're relocating, and this is an external symbol with no
+     addend, we don't want to change anything.  We will only have an
+     addend if this is a newly created reloc, not read from an ELF
+     file.  */
+  if (output_bfd != (bfd *) NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && reloc_entry->addend == 0)
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  reloc_entry->addend >>= 2;
+  return bfd_reloc_continue;
+}
+
 /* Do a R_MIPS_GPREL16 relocation.  This is a 16 bit value which must
    become the offset from the gp register.  */
 


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