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]

A MIPS --emit-relocs fix


The generic --emit-relocs support is geared towards targets that
(a) use _bfd_elf_rela_local_sym and (b) set elf_backend_rela_normal to 1.
MIPS does neither of these things.  I assume this is partly because MIPS
needs to deal with compound relocs and partly because it needs to support
both REL and RELA.

The upshot is that if an input file contains a relocation against a
section symbol, the --emit-relocs version will keep the original addend.
It won't be updated to account for the offset of the input section from
the output section, or for the effects of merging.

We already get this right in relocatable output.  We just need to
apply the same logic to relocations in a final link, and in addition
handle the effects of merging (which doesn't take place for relocatable
links).

Tested on mips64-elf, mips64-linux-gnu, mips-elf, mipsisa32-elf,
mipsisa64-elf and mips-linux-gnu.  I also ran a full toolchain test
on VxWorks, which uses --emit-relocs extensively.  (I'm going
to submit the binutils support soon.)  OK to install?

Richard


bfd/
	* elf32-mips.c (mips_elf_adjust_addend): New function, mostly split
	out from...
	(_bfd_mips_elf_relocate_section): ...here.  Use it to adjust r_addend
	for final links too.

ld/testsuite/
	* ld-mips/emit-relocs-1a.s, ld-mips/emit-relocs-1b.s,
	* ld-mips/emit-relocs-1.ld, ld-mips/emit-relocs-1.d: New test.
	* ld-mips/mips-elf.exp: Run it.

diff -uprN ../src.2/bfd/elfxx-mips.c ./bfd/elfxx-mips.c
--- ./bfd/elfxx-mips.c	2006-03-13 19:22:02.000000000 +0000
+++ ./bfd/elfxx-mips.c	2006-03-13 19:23:39.000000000 +0000
@@ -6934,6 +6934,48 @@ _bfd_mips_elf_size_dynamic_sections (bfd
   return TRUE;
 }
 
+/* REL is a relocation in INPUT_BFD that is being copied to OUTPUT_BFD.
+   Adjust its R_ADDEND field so that it is correct for the output file.
+   LOCAL_SYMS and LOCAL_SECTIONS are arrays of INPUT_BFD's local symbols
+   and sections respectively; both use symbol indexes.  */
+
+static void
+mips_elf_adjust_addend (bfd *output_bfd, struct bfd_link_info *info,
+			bfd *input_bfd, Elf_Internal_Sym *local_syms,
+			asection **local_sections, Elf_Internal_Rela *rel)
+{
+  unsigned int r_type, r_symndx;
+  Elf_Internal_Sym *sym;
+  asection *sec;
+
+  if (mips_elf_local_relocation_p (input_bfd, rel, local_sections, FALSE))
+    {
+      r_type = ELF_R_TYPE (output_bfd, rel->r_info);
+      if (r_type == R_MIPS16_GPREL
+	  || r_type == R_MIPS_GPREL16
+	  || r_type == R_MIPS_GPREL32
+	  || r_type == R_MIPS_LITERAL)
+	{
+	  rel->r_addend += _bfd_get_gp_value (input_bfd);
+	  rel->r_addend -= _bfd_get_gp_value (output_bfd);
+	}
+
+      r_symndx = ELF_R_SYM (output_bfd, rel->r_info);
+      sym = local_syms + r_symndx;
+
+      /* Adjust REL's addend to account for section merging.  */
+      if (!info->relocatable)
+	{
+	  sec = local_sections[r_symndx];
+	  _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+	}
+
+      /* This would normally be done by the rela_normal code in elflink.c.  */
+      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+	rel->r_addend += local_sections[r_symndx]->output_offset;
+    }
+}
+
 /* Relocate a MIPS ELF section.  */
 
 bfd_boolean
@@ -7084,47 +7126,19 @@ _bfd_mips_elf_relocate_section (bfd *out
 	    }
 	  else
 	    addend = rel->r_addend;
+	  mips_elf_adjust_addend (output_bfd, info, input_bfd,
+				  local_syms, local_sections, rel);
 	}
 
       if (info->relocatable)
 	{
-	  Elf_Internal_Sym *sym;
-	  unsigned long r_symndx;
-
 	  if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd)
 	      && bfd_big_endian (input_bfd))
 	    rel->r_offset -= 4;
 
-	  /* Since we're just relocating, all we need to do is copy
-	     the relocations back out to the object file, unless
-	     they're against a section symbol, in which case we need
-	     to adjust by the section offset, or unless they're GP
-	     relative in which case we need to adjust by the amount
-	     that we're adjusting GP in this relocatable object.  */
-
-	  if (! mips_elf_local_relocation_p (input_bfd, rel, local_sections,
-					     FALSE))
-	    /* There's nothing to do for non-local relocations.  */
-	    continue;
-
-	  if (r_type == R_MIPS16_GPREL
-	      || r_type == R_MIPS_GPREL16
-	      || r_type == R_MIPS_GPREL32
-	      || r_type == R_MIPS_LITERAL)
-	    addend -= (_bfd_get_gp_value (output_bfd)
-		       - _bfd_get_gp_value (input_bfd));
-
-	  r_symndx = ELF_R_SYM (output_bfd, rel->r_info);
-	  sym = local_syms + r_symndx;
-	  if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-	    /* Adjust the addend appropriately.  */
-	    addend += local_sections[r_symndx]->output_offset;
-
-	  if (rela_relocation_p)
-	    /* If this is a RELA relocation, just update the addend.  */
-	    rel->r_addend = addend;
-	  else
+	  if (!rela_relocation_p && rel->r_addend)
 	    {
+	      addend += rel->r_addend;
 	      if (r_type == R_MIPS_HI16
 		  || r_type == R_MIPS_GOT16)
 		addend = mips_elf_high (addend);
diff -uprN ../src.2/ld/testsuite/ld-mips-elf/emit-relocs-1a.s ./ld/testsuite/ld-mips-elf/emit-relocs-1a.s
--- ./ld/testsuite/ld-mips-elf/emit-relocs-1a.s	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/emit-relocs-1a.s	2006-03-13 19:23:39.000000000 +0000
@@ -0,0 +1,22 @@
+	.text
+	.globl	_start
+_start:
+	jr	$31
+
+	.section .merge1,"aMS",@progbits,1
+A:	.string	"utter"
+
+	.section .merge2,"aMS",@progbits,1
+B:	.string "tasting"
+
+	.section .merge3,"aM",@progbits,4
+C:	.4byte	0x100
+D:	.4byte	0x200
+
+	.data
+E:	.4byte	E
+	.4byte	E + 0x1000
+	.4byte	A
+	.4byte	B
+	.4byte	C
+	.4byte	D
diff -uprN ../src.2/ld/testsuite/ld-mips-elf/emit-relocs-1b.s ./ld/testsuite/ld-mips-elf/emit-relocs-1b.s
--- ./ld/testsuite/ld-mips-elf/emit-relocs-1b.s	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/emit-relocs-1b.s	2006-03-13 19:23:39.000000000 +0000
@@ -0,0 +1,17 @@
+	.section .merge1,"aMS",@progbits,1
+A:	.string	"flutter"
+
+	.section .merge2,"aMS",@progbits,1
+B:	.string "sting"
+
+	.section .merge3,"aM",@progbits,4
+C:	.4byte	0x300
+D:	.4byte	0x200
+
+	.data
+E:	.4byte	E
+	.4byte	E + 0x1000
+	.4byte	A
+	.4byte	B
+	.4byte	C
+	.4byte	D
diff -uprN ../src.2/ld/testsuite/ld-mips-elf/emit-relocs-1.d ./ld/testsuite/ld-mips-elf/emit-relocs-1.d
--- ./ld/testsuite/ld-mips-elf/emit-relocs-1.d	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/emit-relocs-1.d	2006-03-13 19:23:39.000000000 +0000
@@ -0,0 +1,37 @@
+#name: Emit relocs 1
+#source: emit-relocs-1a.s -mabi=n32
+#source: emit-relocs-1b.s -mabi=n32
+#ld: -q -T emit-relocs-1.ld
+#objdump: -sr
+
+.*:     file format .*
+
+RELOCATION RECORDS FOR \[\.data\]:
+OFFSET   TYPE              VALUE *
+00000000 R_MIPS_32         \.data
+00000004 R_MIPS_32         \.data\+0x00001000
+00000008 R_MIPS_32         \.merge1\+0x00000002
+0000000c R_MIPS_32         \.merge2
+00000010 R_MIPS_32         \.merge3
+00000014 R_MIPS_32         \.merge3\+0x00000004
+00000020 R_MIPS_32         \.data\+0x00000020
+00000024 R_MIPS_32         \.data\+0x00001020
+00000028 R_MIPS_32         \.merge1
+0000002c R_MIPS_32         \.merge2\+0x00000002
+00000030 R_MIPS_32         \.merge3\+0x00000008
+00000034 R_MIPS_32         \.merge3\+0x00000004
+
+
+Contents of section \.text:
+ 80000 03e00008 00000000 00000000 00000000  .*
+Contents of section \.merge1:
+ 80400 666c7574 74657200                    flutter.*
+Contents of section \.merge2:
+ 80800 74617374 696e6700                    tasting.*
+Contents of section \.merge3:
+ 80c00 00000100 00000200 00000300           .*
+Contents of section \.data:
+ 81000 00081000 00082000 00080402 00080800  .*
+ 81010 00080c00 00080c04 00000000 00000000  .*
+ 81020 00081020 00082020 00080400 00080802  .*
+ 81030 00080c08 00080c04 .*
diff -uprN ../src.2/ld/testsuite/ld-mips-elf/emit-relocs-1.ld ./ld/testsuite/ld-mips-elf/emit-relocs-1.ld
--- ./ld/testsuite/ld-mips-elf/emit-relocs-1.ld	1970-01-01 01:00:00.000000000 +0100
+++ ./ld/testsuite/ld-mips-elf/emit-relocs-1.ld	2006-03-13 19:23:39.000000000 +0000
@@ -0,0 +1,20 @@
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x80000;
+  .text : { *(.text) }
+
+  . = ALIGN (0x400);
+  .merge1 : { *(.merge1) }
+
+  . = ALIGN (0x400);
+  .merge2 : { *(.merge2) }
+
+  . = ALIGN (0x400);
+  .merge3 : { *(.merge3) }
+
+  . = ALIGN (0x400);
+  .data : { *(.data) }
+
+  /DISCARD/ : { *(*) }
+}
diff -uprN ../src.2/ld/testsuite/ld-mips-elf/mips-elf.exp ./ld/testsuite/ld-mips-elf/mips-elf.exp
--- ./ld/testsuite/ld-mips-elf/mips-elf.exp	2006-03-13 19:22:02.000000000 +0000
+++ ./ld/testsuite/ld-mips-elf/mips-elf.exp	2006-03-13 19:23:39.000000000 +0000
@@ -105,6 +105,10 @@ if { $linux_gnu } {
     run_dump_test "textrel-1"
 }
 
+if $has_newabi {
+    run_dump_test "emit-relocs-1"
+}
+
 # For tests which may involve multiple files, use run_ld_link_tests.
 
 # List contains test-items with 3 items followed by 2 lists:


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