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]

Re: On resolving the MIPS gas branch reloc issue


On Mar  9, 2003, Thiemo Seufer <ica2_ts at csv dot ica dot uni-stuttgart dot de> wrote:

> http://sources.redhat.com/ml/binutils/2003-02/msg00179.html worked for me,
> but I'm not sure about it's correctness.

Here's my take on it.  I wrote this before realizing your patch, that
I believe to be broken, had already gone in, so I post it mostly for
reference.  I'll see if I can dig out some testcases to show the
problems I had in mind.

Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva at redhat dot com>

	* config/tc-mips.c (mips_validate_fix): New function.
	* config/tc-mips.h (TC_VALIDATE_FIX): Define.
	(mips_validate_fix): Declare.

Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/uberbaum/gas/config/tc-mips.c,v
retrieving revision 1.193
diff -u -p -r1.193 tc-mips.c
--- gas/config/tc-mips.c 21 Feb 2003 10:28:27 -0000 1.193
+++ gas/config/tc-mips.c 10 Mar 2003 18:52:46 -0000
@@ -11026,6 +11026,85 @@ mips_force_relocation (fixp)
 	      || fixp->fx_r_type == BFD_RELOC_PCREL_LO16));
 }
 
+/* This hook is called before a fix is simplified.  We don't really
+   decide whether to skip a fix here.  Rather, we turn global symbols
+   used as branch targets into local symbols, such that they undergo
+   simplification.  We can only do this if the symbol is defined and
+   it is in the same section as the branch.  If this doesn't hold, we
+   emit a better error message than just saying the relocation is not
+   valid for the selected object format.
+
+   FIXP is the fix-up we're going to try to simplify, SEG is the
+   segment in which the fix up occurs.  The return value should be
+   non-zero to indicate the fix-up is valid for further
+   simplifications.  */
+
+int
+mips_validate_fix (fixP, seg)
+     struct fix *fixP;
+     asection *seg;
+{
+  /* There's a lot of discussion on whether it should be possible to
+     use R_MIPS_PC16 to represent branch relocations.  The outcome
+     seems to be that it can, but gas/bfd are very broken in creating
+     RELA relocations for this, so for now we only accept branches to
+     symbols in the same section.  Anything else is of dubious value,
+     since there's no guarantee that at link time the symbol would be
+     in range.  Even for branches to local symbols this is arguably
+     wrong, since it we assume the symbol is not going to be
+     overridden, which should be possible per ELF library semantics,
+     but then, there isn't a dynamic relocation that could be used to
+     this effect, and the target would likely be out of range as well.
+
+     Unfortunately, it seems that there is too much code out there
+     that relies on branches to symbols that are global to be resolved
+     as if they were local, like the IRIX tools do, so we do it as
+     well, but with a warning so that people are reminded to fix their
+     code.  If we ever get back to using R_MIPS_PC16 for branch
+     targets, this entire block should go away (and probably the
+     whole function).  */
+
+  if (fixP->fx_r_type == BFD_RELOC_16_PCREL_S2
+      && (((OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+	    || OUTPUT_FLAVOR == bfd_target_elf_flavour)
+	   && mips_pic != EMBEDDED_PIC)
+	  || bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16_PCREL_S2) == NULL)
+      && fixP->fx_addsy)
+    {
+      if (! S_IS_DEFINED (fixP->fx_addsy))
+	{
+	  as_bad_where (fixP->fx_file, fixP->fx_line,
+			_("Cannot branch to undefined symbol."));
+	  /* Avoid any further errors about this fixup.  */
+	  fixP->fx_done = 1;
+	}
+      else if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
+	{
+	  as_bad_where (fixP->fx_file, fixP->fx_line,
+			_("Cannot branch to symbol in another section."));
+	  fixP->fx_done = 1;
+	}
+      else if (S_IS_EXTERNAL (fixP->fx_addsy))
+	{
+	  symbolS *sym = fixP->fx_addsy;
+
+	  as_warn_where (fixP->fx_file, fixP->fx_line,
+			 _("Pretending global symbol used as branch target is local."));
+
+	  fixP->fx_addsy = symbol_create (S_GET_NAME (sym),
+					  S_GET_SEGMENT (sym),
+					  S_GET_VALUE (sym),
+					  symbol_get_frag (sym));
+	  copy_symbol_attributes (fixP->fx_addsy, sym);
+	  S_CLEAR_EXTERNAL (fixP->fx_addsy);
+	  assert (symbol_resolved_p (sym));
+	  symbol_mark_resolved (fixP->fx_addsy);
+	}
+    }
+
+  return 1;
+}
+
 #ifdef OBJ_ELF
 static int
 mips_need_elf_addend_fixup (fixP)
Index: gas/config/tc-mips.h
===================================================================
RCS file: /cvs/uberbaum/gas/config/tc-mips.h,v
retrieving revision 1.23
diff -u -p -r1.23 tc-mips.h
--- gas/config/tc-mips.h 24 Jan 2003 01:12:30 -0000 1.23
+++ gas/config/tc-mips.h 10 Mar 2003 18:52:46 -0000
@@ -140,6 +140,15 @@ extern int mips_fix_adjustable PARAMS ((
 #define TC_FORCE_RELOCATION(FIX) mips_force_relocation (FIX)
 extern int mips_force_relocation PARAMS ((struct fix *));
 
+/* We use this to turn branches to global symbols into branches to
+   local symbols, so that they can be simplified.  */
+#define TC_VALIDATE_FIX(fixp, this_segment, skip_label) \
+  do \
+    if (! mips_validate_fix ((fixp), (this_segment))) \
+      goto skip_label; \
+  while (0)
+extern int mips_validate_fix PARAMS ((struct fix *, asection *));
+
 /* Register mask variables.  These are set by the MIPS assembly code
    and used by ECOFF and possibly other object file formats.  */
 extern unsigned long mips_gprmask;
Index: gas/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva at redhat dot com>

	* gas/mips/branch-misc-2.s: Add branch to symbol in another
	section.
	* gas/mips/branch-misc-2.l: Update error messages and warnings.

Index: gas/testsuite/gas/mips/branch-misc-2.l
===================================================================
RCS file: /cvs/uberbaum/gas/testsuite/gas/mips/Attic/branch-misc-2.l,v
retrieving revision 1.1
diff -u -p -r1.1 branch-misc-2.l
--- gas/testsuite/gas/mips/branch-misc-2.l 12 Dec 2002 04:40:22 -0000 1.1
+++ gas/testsuite/gas/mips/branch-misc-2.l 10 Mar 2003 18:52:50 -0000
@@ -1,9 +1,10 @@
 .*: Assembler messages:
-.*:21: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
-.*:22: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
-.*:23: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
-.*:24: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
-.*:25: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
-.*:26: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
-.*:35: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
-.*:36: Error: Can not represent BFD_RELOC_16_PCREL_S2 relocation in this object file format
+.*:21: Warning: Pretending global symbol used as branch target is local.
+.*:22: Warning: Pretending global symbol used as branch target is local.
+.*:23: Warning: Pretending global symbol used as branch target is local.
+.*:24: Warning: Pretending global symbol used as branch target is local.
+.*:25: Warning: Pretending global symbol used as branch target is local.
+.*:26: Warning: Pretending global symbol used as branch target is local.
+.*:35: Error: Cannot branch to undefined symbol.
+.*:36: Error: Cannot branch to undefined symbol.
+.*:37: Error: Cannot branch to symbol in another section.
Index: gas/testsuite/gas/mips/branch-misc-2.s
===================================================================
RCS file: /cvs/uberbaum/gas/testsuite/gas/mips/branch-misc-2.s,v
retrieving revision 1.2
diff -u -p -r1.2 branch-misc-2.s
--- gas/testsuite/gas/mips/branch-misc-2.s 12 Dec 2002 04:40:22 -0000 1.2
+++ gas/testsuite/gas/mips/branch-misc-2.s 10 Mar 2003 18:52:50 -0000
@@ -34,6 +34,10 @@ g6:
 
 	b	x1
 	b	x2
+	b	.Ldata
 
 # Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
 	.space	8
+
+	.data
+.Ldata:
-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva at {redhat dot com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva at {lsd dot ic dot unicamp dot br, gnu.org}
Free Software Evangelist                Professional serial bug killer

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