[binutils-gdb] i386-darwin regression

Alan Modra via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c90055a270f60b126a04630d2db43e9d200c374c

commit c90055a270f60b126a04630d2db43e9d200c374c
Author: Alan Modra <[email protected]>
Date:   Mon Jun 1 18:28:01 2026 +0930

    i386-darwin regression
    
    Commit cc28c46227cd caused testsuite regressions on i386-darwin:
    i386-darwin  +FAIL: i386 intel-ok (directive)
    i386-darwin  +FAIL: i386 intel-ok (cmdline option)
    
    Reduced testcase:
            .intel_syntax noprefix
            mov eax, [offset x] - [1]
    This triggers an obj_mach_o_check_before_writing error, because x
    is indeed undefined.  However, the error is nonsense because fx_subsy
    is the absolute value 1, and that should just result in a relocation
    against x with an addend of -1.
    
    What's more, obj_mach_o_check_before_writing runs before symbols
    are resolved.  At that point undefined symbols may be wrapped in an
    expression symbol.  Expression symbols are S_IS_DEFINED, which is
    why the error did not trigger until commit cc28c46227cd simplified
    away the expression symbol wrapper.  So obj_mach_o_check_before_writing
    is ineffective in some cases and overly restrictive in others.  If
    something like it is necessary the correct place to do so is after
    fixups have been simplified.  In fact there is a sufficient check in
    write.c:fixup_segment but the macho support disables it by defining
    TC_VALIDATE_FIX_SUB to 1.
    
    This patch reverts commit 16a87420985f (see
    https://sourceware.org/pipermail/binutils/2012-February/075591.html),
    and removes the define of TC_VALIDATE_FIX_SUB for macho.  I'm sure it
    is wrong to whitewash fixups by using TC_VALIDATE_FIX_SUB in this way.
    Any fx_subsy that is left at that point will be ignored by the x86
    md_apply_fix and tc_gen_reloc functions, except for a few special
    cases.  That will result in incorrect relocations.
    
    The patch also corrects obj_mach_o_force_reloc_sub_local.  Since this
    is a predicate testing whether fx_subsy can be eliminated (and the
    fixup made pc-relative) it ought to be testing for fx_subsy in the
    same subsection as the fixup frag.  This cures "FAIL: i386 sub".
    
            * config/obj-macho.c (obj_mach_o_check_before_writing): Delete.
            (obj_mach_o_pre_output_hook): Delete.
            (obj_mach_o_in_different_subsection): Make static.  Return bool.
            (obj_mach_o_force_reloc_sub_same): Return bool.
            (obj_mach_o_force_reloc_sub_local): Rewrite to check fx_subsy.
            (obj_mach_o_force_reloc): Return bool.
            * config/obj-macho.h (md_pre_output_hook): Don't define.
            (obj_mach_o_in_different_subsection): Delete.
            (obj_mach_o_force_reloc, obj_mach_o_force_reloc_sub_same),
            (obj_mach_o_force_reloc_sub_local): Update.
            * config/tc-i386.h (TC_VALIDATE_FIX_SUB <OBJ_MACH_O>): Likewise.

Diff:
---
 gas/config/obj-macho.c | 89 +++++++++-----------------------------------------
 gas/config/obj-macho.h | 10 ++----
 gas/config/tc-i386.h   |  2 --
 3 files changed, 18 insertions(+), 83 deletions(-)

diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c
index 5b16e7512b4..6de2410e1a7 100644
--- a/gas/config/obj-macho.c
+++ b/gas/config/obj-macho.c
@@ -1554,68 +1554,6 @@ obj_mach_o_process_stab (int what, const char *string,
   s->symbol.udata.i = SYM_MACHO_FIELDS_NOT_VALIDATED;
 }
 
-/* This is a place to check for any errors that we can't detect until we know
-   what remains undefined at the end of assembly.  */
-
-static void
-obj_mach_o_check_before_writing (bfd *abfd ATTRIBUTE_UNUSED,
-				 asection *sec,
-				 void *unused ATTRIBUTE_UNUSED)
-{
-  fixS *fixP;
-  struct frchain *frchp;
-  segment_info_type *seginfo = seg_info (sec);
-
-  if (seginfo == NULL)
-    return;
-
-  /* We are not allowed subtractions where either of the operands is
-     undefined.  So look through the frags for any fixes to check.  */
-  for (frchp = seginfo->frchainP; frchp != NULL; frchp = frchp->frch_next)
-   for (fixP = frchp->fix_root; fixP != NULL; fixP = fixP->fx_next)
-    {
-      if (fixP->fx_addsy != NULL
-	  && fixP->fx_subsy != NULL
-	  && (! S_IS_DEFINED (fixP->fx_addsy)
-	      || ! S_IS_DEFINED (fixP->fx_subsy)))
-	{
-	  segT add_symbol_segment = S_GET_SEGMENT (fixP->fx_addsy);
-	  segT sub_symbol_segment = S_GET_SEGMENT (fixP->fx_subsy);
-
-	  if (! S_IS_DEFINED (fixP->fx_addsy)
-	      && S_IS_DEFINED (fixP->fx_subsy))
-	    {
-	      as_bad_where (fixP->fx_file, fixP->fx_line,
-		_("`%s' can't be undefined in `%s' - `%s' {%s section}"),
-		S_GET_NAME (fixP->fx_addsy), S_GET_NAME (fixP->fx_addsy),
-		S_GET_NAME (fixP->fx_subsy), segment_name (sub_symbol_segment));
-	    }
-	  else if (! S_IS_DEFINED (fixP->fx_subsy)
-		   && S_IS_DEFINED (fixP->fx_addsy))
-	    {
-	      as_bad_where (fixP->fx_file, fixP->fx_line,
-		_("`%s' can't be undefined in `%s' {%s section} - `%s'"),
-		S_GET_NAME (fixP->fx_subsy), S_GET_NAME (fixP->fx_addsy),
-		segment_name (add_symbol_segment), S_GET_NAME (fixP->fx_subsy));
-	    }
-	  else
-	    {
-	      as_bad_where (fixP->fx_file, fixP->fx_line,
-		_("`%s' and `%s' can't be undefined in `%s' - `%s'"),
-		S_GET_NAME (fixP->fx_addsy), S_GET_NAME (fixP->fx_subsy),
-		S_GET_NAME (fixP->fx_addsy), S_GET_NAME (fixP->fx_subsy));
-	    }
-	}
-    }
-}
-
-/* Do any checks that we can't complete without knowing what's undefined.  */
-void
-obj_mach_o_pre_output_hook (void)
-{
-  bfd_map_over_sections (stdoutput, obj_mach_o_check_before_writing, NULL);
-}
-
 /* Here we count up frags in each subsection (where a sub-section is defined
    as starting with a non-local symbol).
    Note that, if there are no non-local symbols in a section, all the frags will
@@ -1925,7 +1863,7 @@ obj_mach_o_allow_local_subtract (expressionS * left ATTRIBUTE_UNUSED,
   return obj_mach_o_is_frame_section (seg);
 }
 
-int
+static bool
 obj_mach_o_in_different_subsection (symbolS *a, symbolS *b)
 {
   fragS *fa;
@@ -1936,7 +1874,7 @@ obj_mach_o_in_different_subsection (symbolS *a, symbolS *b)
       || !S_IS_DEFINED (b))
     {
       /* Not in the same segment, or undefined symbol.  */
-      return 1;
+      return true;
     }
 
   fa = symbol_get_frag (a);
@@ -1944,31 +1882,34 @@ obj_mach_o_in_different_subsection (symbolS *a, symbolS *b)
   if (fa == NULL || fb == NULL)
     {
       /* One of the symbols is not in a subsection.  */
-      return 1;
+      return true;
     }
 
   return fa->obj_frag_data.subsection != fb->obj_frag_data.subsection;
 }
 
-int
+bool
 obj_mach_o_force_reloc_sub_same (fixS *fix, segT seg)
 {
   if (! SEG_NORMAL (seg))
-    return 1;
+    return true;
   return obj_mach_o_in_different_subsection (fix->fx_addsy, fix->fx_subsy);
 }
 
-int
+bool
 obj_mach_o_force_reloc_sub_local (fixS *fix, segT seg ATTRIBUTE_UNUSED)
 {
-  return obj_mach_o_in_different_subsection (fix->fx_addsy, fix->fx_subsy);
+  symbolS *fragsym = fix->fx_frag->obj_frag_data.subsection;
+  if (fragsym == NULL)
+    return false;
+  return obj_mach_o_in_different_subsection (fix->fx_subsy, fragsym);
 }
 
-int
+bool
 obj_mach_o_force_reloc (fixS *fix)
 {
   if (generic_force_reloc (fix))
-    return 1;
+    return true;
 
   /* Force a reloc if the target is not in the same subsection.
      FIXME: handle (a - b) where a and b belongs to the same subsection ?  */
@@ -1979,12 +1920,12 @@ obj_mach_o_force_reloc (fixS *fix)
 
       /* There might be no subsections at all.  */
       if (subsec == NULL)
-        return 0;
+	return false;
 
       if (S_GET_SEGMENT (targ) == absolute_section)
-        return 0;
+	return false;
 
       return obj_mach_o_in_different_subsection (targ, subsec);
     }
-  return 0;
+  return false;
 }
diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h
index 6e4b7b6d178..eac0afdf407 100644
--- a/gas/config/obj-macho.h
+++ b/gas/config/obj-macho.h
@@ -87,9 +87,6 @@ struct obj_mach_o_frag_data
 
 #define OBJ_FRAG_TYPE struct obj_mach_o_frag_data
 
-#define md_pre_output_hook obj_mach_o_pre_output_hook()
-extern void obj_mach_o_pre_output_hook(void);
-
 #define md_pre_relax_hook obj_mach_o_pre_relax_hook()
 extern void obj_mach_o_pre_relax_hook (void);
 
@@ -111,9 +108,8 @@ extern int obj_mach_o_allow_local_subtract (expressionS *, expressionS *,
 					    segT);
 
 struct fix;
-extern int obj_mach_o_in_different_subsection (symbolS *a, symbolS *b);
-extern int obj_mach_o_force_reloc (struct fix *fix);
-extern int obj_mach_o_force_reloc_sub_same (struct fix *fix, segT seg);
-extern int obj_mach_o_force_reloc_sub_local (struct fix *fix, segT seg);
+extern bool obj_mach_o_force_reloc (struct fix *);
+extern bool obj_mach_o_force_reloc_sub_same (struct fix *, segT);
+extern bool obj_mach_o_force_reloc_sub_local (struct fix *, segT);
 
 #endif /* _OBJ_MACH_O_H */
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index bd3f4b5b59e..20e5334d14e 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -506,8 +506,6 @@ void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int);
 #define TC_FORCE_RELOCATION_SUB_LOCAL(FIX,SEG) \
 	(obj_mach_o_force_reloc_sub_local (FIX, SEG))
 
-#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
-
 #endif /* OBJ_MACH_O */
 
 #endif /* TC_I386 */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.