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]

sh-linux patch for 32-bit relative relocation


Hello,

Here is a patch for sh-linux to handle the substraction of two
symbols in different sections correctly. This is essentially same
with the old patch
  http://sources.redhat.com/ml/binutils/2001-01/msg00071.html
which had a possible ABI problem in non linux targets, but is now
organized as a linux specific patch which doesn't affect non linux
targets. Formally the change for gas/tc-sh.c affects all sh targets,
but the effect of this change is ignored by non linux targets since
src_mask of HOWTO (R_SH_REL32,... is set to 0 in such targets.
I think that almost all sh-linux developpers are using this patch
successfully and enough test is done. Without this, we can't get
working shared libraries for stdc++, X and many other packages.

Regards,
	kaz
--
2001-09-11  Kaz Kojima  <kkojima@rr.iij4u.or.jp>

	* bfd/elf32-sh-lin.c (LINUX_ABI): Defined.
	* bfd/elf32-sh.c (sh_elf_howto_table): Don't mask source
	R_SH_REL32 relocation in linux case.
	(sh_elf_relocate_section): Use in-place value in computing
	addend for R_SH_REL32 relocation in linux case.

Index: bfd/elf32-sh-lin.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh-lin.c,v
retrieving revision 1.1
diff -u -r1.1 elf32-sh-lin.c
--- elf32-sh-lin.c	2000/09/07 04:23:43	1.1
+++ elf32-sh-lin.c	2001/08/22 01:26:50
@@ -25,5 +25,6 @@
 #define ELF_MACHINE_CODE EM_SH
 #define ELF_MAXPAGESIZE 0x10000
 #define elf_symbol_leading_char 0
+#define LINUX_ABI 1
 
 #include "elf32-sh.c"
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.29
diff -u -r1.29 elf32-sh.c
--- elf32-sh.c	2001/05/23 16:38:36	1.29
+++ elf32-sh.c	2001/08/22 01:27:09
@@ -112,6 +112,7 @@
 	 false),		/* pcrel_offset */
 
   /* 32 bit PC relative relocation.  */
+#if defined(LINUX_ABI)
   HOWTO (R_SH_REL32,		/* type */
 	 0,			/* rightshift */
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
@@ -121,10 +122,25 @@
 	 complain_overflow_signed, /* complain_on_overflow */
 	 sh_elf_ignore_reloc,	/* special_function */
 	 "R_SH_REL32",		/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+#else
+  HOWTO (R_SH_REL32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 sh_elf_ignore_reloc,	/* special_function */
+	 "R_SH_REL32",		/* name */
 	 false,			/* partial_inplace */
 	 0,			/* src_mask */
 	 0xffffffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
+#endif
 
   /* 8 bit PC relative branch divided by 2.  */
   HOWTO (R_SH_DIR8WPN,		/* type */
@@ -3048,7 +3064,11 @@
 		 section symbol winds up in the output section.  */
 	      sym = local_syms + r_symndx;
 	      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-		goto final_link_relocate;
+		{
+		  r = _bfd_relocate_contents (howto, input_bfd, relocation,
+					      contents + rel->r_offset);
+		  goto relocation_done;
+		}
 
 	      continue;
 	    }
@@ -3251,9 +3271,15 @@
 	      else if (r_type == R_SH_REL32)
 		{
 		  BFD_ASSERT (h != NULL && h->dynindx != -1);
+#if defined(LINUX_ABI)
+		  addend = bfd_get_32 (input_bfd,
+				       (bfd_byte *) contents + rel->r_offset);
+#else
+		  addend = rel->r_addend;
+#endif
 		  relocate = false;
 		  outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_REL32);
-		  outrel.r_addend = rel->r_addend;
+		  outrel.r_addend = addend;
 		}
 	      else
 		{
@@ -3266,14 +3292,25 @@
 		    {
 		      relocate = true;
 		      outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
+#if defined(LINUX_ABI)
+		      outrel.r_addend = 0;
+#else
 		      outrel.r_addend = relocation + rel->r_addend;
+#endif
 		    }
 		  else
 		    {
 		      BFD_ASSERT (h->dynindx != -1);
+#if defined(LINUX_ABI)
+		      addend = bfd_get_32 (input_bfd,
+					   ((bfd_byte *) contents
+					    + rel->r_offset));
+#else
+		      addend = rel->r_addend;
+#endif
 		      relocate = false;
 		      outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_DIR32);
-		      outrel.r_addend = relocation + rel->r_addend;
+		      outrel.r_addend = relocation + addend;
 		    }
 		}
 
@@ -3371,7 +3408,11 @@
 					 + sgot->output_offset
 					 + off);
 		      outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
+#if defined(LINUX_ABI)
+		      outrel.r_addend = 0;
+#else
 		      outrel.r_addend = relocation;
+#endif
 		      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
 						(((Elf32_External_Rela *)
 						  srelgot->contents)
@@ -3471,6 +3512,7 @@
 	  }
 	}
 
+    relocation_done:
       if (r != bfd_reloc_ok)
 	{
 	  switch (r)
@@ -4237,9 +4279,13 @@
 	  && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
 	{
 	  rel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
+#if defined(LINUX_ABI)
+	  rel.r_addend = 0;
+#else
 	  rel.r_addend = (h->root.u.def.value
 			  + h->root.u.def.section->output_section->vma
 			  + h->root.u.def.section->output_offset);
+#endif
 	}
       else
 	{
Index: tc-sh.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.c,v
retrieving revision 1.40
diff -u -r1.40 tc-sh.c
--- tc-sh.c	2001/07/03 15:22:19	1.40
+++ tc-sh.c	2001/09/11 00:39:37
@@ -2834,6 +2834,11 @@
       && fixP->fx_addsy != NULL
       && S_IS_WEAK (fixP->fx_addsy))
     val -= S_GET_VALUE  (fixP->fx_addsy);
+
+  if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+      && fixP->fx_r_type == BFD_RELOC_32_PCREL
+      && fixP->fx_addsy != NULL)
+    val += fixP->fx_where + fixP->fx_frag->fr_address;
 #endif
 
 #ifndef BFD_ASSEMBLER


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