This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch gas/mach-o] pre-output error check hook.
- From: Iain Sandoe <developer at sandoe-acoustics dot co dot uk>
- To: binutils Development <binutils at sourceware dot org>
- Cc: Tristan Gingold <gingold at adacore dot com>
- Date: Fri, 17 Feb 2012 20:24:27 +0000
- Subject: [Patch gas/mach-o] pre-output error check hook.
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;