[Patch gas/mach-o] pre-output error check hook.

Iain Sandoe developer@sandoe-acoustics.co.uk
Fri Feb 17 20:24:00 GMT 2012
For mach-o there are a couple of errors that we can't really diagnose  
until we finish parsing (i.e. ones that depend on whether symbols are  
defined or not).

It would be nicer if these errors could be enumerated before the  
object file is output - so that they could appear in the summary and  
the output aborted at that point (otherwise they will just hit when we  
try to validate relocs).

In a way, I'm surprised that no-one else wants to do this - which  
makes me wonder if I've missed an alternate implementation?

Anyway, the implementation here adds a hook which is activated right  
before the final error count tally in write_object_file()

This is used, initially, to bail out if we have certain invalid relocs.
OK?
Iain

gas:

	* write.c (write_object_file): Add md_pre_output_hook.
	* config/obj-macho.c (obj_mach_o_check_before_writing): New.
	(obj_mach_o_pre_output_hook): New.
	* config/obj-macho.h (md_pre_output_hook): Define.
	(obj_mach_o_pre_output_hook): Declare.

  gas/config/obj-macho.c |   66 +++++++++++++++++++++++++++++++++++++++ 
+++++++++
  gas/config/obj-macho.h |    3 ++
  gas/write.c            |    4 +++
  3 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c
index 632eafa..f1b4e70 100644
--- a/gas/config/obj-macho.c
+++ b/gas/config/obj-macho.c
@@ -1541,6 +1541,72 @@ obj_mach_o_process_stab (int what, const char  
*string,
+
+/* 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,  
(char *) 0);
  }

  /* Here we count up frags in each subsection (where a sub-section is  
defined
diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h
index b49038c..f76b66d 100644
--- a/gas/config/obj-macho.h
+++ b/gas/config/obj-macho.h
@@ -84,6 +84,9 @@ 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);

diff --git a/gas/write.c b/gas/write.c
index f640c61..23d4334 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -1767,6 +1767,10 @@ write_object_file (void)
    fragS *fragP;			/* Track along all frags.  */
  #endif

+#ifdef md_pre_output_hook
+  md_pre_output_hook;
+#endif
+
    /* Do we really want to write it?  */
    {
      int n_warns, n_errs;



More information about the Binutils mailing list