This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

Fix -fpic/-fno-pic PCH validity checking


This adds support for target-specific PCH validity checking, and a
default implementation that checks all target flags and -fpic and
-fpie, which is at least safe.  It fixes 10757.

Bootstrapped and tested on powerpc-darwin; the equivalent of 10757 on
Darwin involves -mdynamic-no-pic.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/gcc-pchtargetvalidity.patch===============
2003-10-24  Geoffrey Keating  <geoffk@apple.com>

	PR 10757
	* c-pch.c: Include target.h.  Improve comments.
	(struct c_pch_validity): Add target_data_length.
	(pch_init): Add target's validity data.
	(c_common_valid_pch): Check target's validity data.
	* target-def.h (TARGET_GET_PCH_VALIDITY): New.
	(TARGET_PCH_VALID_P): New.
	(TARGET_INITIALIZER): Add new fields.
	* target.h: Include tm.h.
	(struct gcc_target): Add get_pch_validity, pch_valid_p.
	* toplev.h (default_get_pch_validity): New prototype.
	(default_pch_valid_p): New prototype.
	* toplev.c (default_get_pch_validity): New routine.
	(default_pch_valid_p): New routine.
	* Makefile.in (TARGET_H): Add TM_H.  Replace all users of
	target.h with $(TARGET_H).
	(c-pch.o): Add TARGET_H.
	* doc/tm.texi (PCH Target): New node.
	(TARGET_GET_PCH_VALIDITY): Document.
	(TARGET_PCH_VALID_P): Document.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1182
diff -u -p -p -u -r1.1182 Makefile.in
--- Makefile.in	22 Oct 2003 11:58:02 -0000	1.1182
+++ Makefile.in	24 Oct 2003 20:21:22 -0000
@@ -629,7 +629,7 @@ TM_P_H    = tm_p.h    $(tm_p_file_list)
 GTM_H     = tm.h      $(tm_file_list)
 TM_H      = $(GTM_H) insn-constants.h insn-flags.h
 
-TARGET_H = target.h
+TARGET_H = $(TM_H) target.h
 HOOKS_H = hooks.h
 LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
 TARGET_DEF_H = target-def.h $(HOOKS_H)
@@ -1360,7 +1360,7 @@ c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM
 
 c-pch.o : c-pch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_H) $(TREE_H) \
 	$(C_COMMON_H) output.h toplev.h c-pragma.h $(GGC_H) debug.h \
-	langhooks.h flags.h hosthooks.h version.h
+	langhooks.h flags.h hosthooks.h version.h $(TARGET_H)
 	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 	  -DHOST_MACHINE=\"$(host)\" -DTARGET_MACHINE=\"$(target)\" \
 	  $< $(OUTPUT_OPTION)
@@ -1569,7 +1569,7 @@ explow.o : explow.c $(CONFIG_H) $(SYSTEM
 optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
    flags.h insn-config.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(RECOG_H) reload.h \
    toplev.h $(GGC_H) real.h $(TM_P_H) except.h gt-optabs.h $(BASIC_BLOCK_H) \
-   target.h
+   $(TARGET_H)
 dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
    flags.h $(REGS_H) debug.h $(TM_P_H) $(TARGET_H) function.h langhooks.h \
    insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h \
@@ -1811,7 +1811,7 @@ regrename.o : regrename.c $(CONFIG_H) $(
    insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h $(RECOG_H) function.h \
    resource.h $(OBSTACK_H) flags.h $(TM_P_H)
 ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
-   $(REGS_H) toplev.h flags.h insn-config.h function.h $(RECOG_H) target.h \
+   $(REGS_H) toplev.h flags.h insn-config.h function.h $(RECOG_H) $(TARGET_H) \
    $(BASIC_BLOCK_H) $(EXPR_H) output.h except.h $(TM_P_H) real.h $(OPTABS_H) \
    cfgloop.h
 params.o : params.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(PARAMS_H) toplev.h
Index: c-pch.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-pch.c,v
retrieving revision 1.16
diff -u -p -p -u -r1.16 c-pch.c
--- c-pch.c	22 Oct 2003 15:44:44 -0000	1.16
+++ c-pch.c	24 Oct 2003 20:21:22 -0000
@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "langhooks.h"
 #include "hosthooks.h"
+#include "target.h"
 
 /* This structure is read very early when validating the PCH, and
    might be read for a PCH which is for a completely different compiler
@@ -40,7 +41,10 @@ Boston, MA 02111-1307, USA.  */
    'unsigned char' entries, at least in the initial entries.  
 
    If you add or change entries before version_length, you should increase
-   the version number in get_ident().  */
+   the version number in get_ident().  
+
+   There are a bunch of fields named *_length; those are lengths of data that
+   follows this structure in the same order as the fields in the structure.  */
 
 struct c_pch_validity
 {
@@ -49,6 +53,7 @@ struct c_pch_validity
   unsigned char version_length;
   unsigned char debug_info_type;
   void (*pch_init) (void);
+  size_t target_data_length;
 };
 
 struct c_pch_header 
@@ -96,6 +101,7 @@ pch_init (void)
 {
   FILE *f;
   struct c_pch_validity v;
+  void *target_validity;
   
   if (! pch_file)
     return;
@@ -112,14 +118,16 @@ pch_init (void)
   v.host_machine_length = strlen (host_machine);
   v.target_machine_length = strlen (target_machine);
   v.version_length = strlen (version_string);
-  
   v.debug_info_type = write_symbols;
   v.pch_init = &pch_init;
+  target_validity = targetm.get_pch_validity (&v.target_data_length);
+  
   if (fwrite (get_ident(), IDENT_LENGTH, 1, f) != 1
       || fwrite (&v, sizeof (v), 1, f) != 1
       || fwrite (host_machine, v.host_machine_length, 1, f) != 1
       || fwrite (target_machine, v.target_machine_length, 1, f) != 1
-      || fwrite (version_string, v.version_length, 1, f) != 1)
+      || fwrite (version_string, v.version_length, 1, f) != 1
+      || fwrite (target_validity, v.target_data_length, 1, f) != 1)
     fatal_error ("can't write to %s: %m", pch_file);
 
   /* We need to be able to re-read the output.  */
@@ -184,8 +192,10 @@ c_common_write_pch (void)
   fclose (pch_outfile);
 }
 
-/* Check the PCH file called NAME, open on FD, to see if it can be used
-   in this compilation.  */
+/* Check the PCH file called NAME, open on FD, to see if it can be
+   used in this compilation.  Return 1 if valid, 0 if the file can't
+   be used now but might be if it's seen later in the compilation, and
+   2 if this file could never be used in the compilation.  */
 
 int
 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
@@ -298,6 +308,24 @@ c_common_valid_pch (cpp_reader *pfile, c
 		   "%s: had text segment at different address", name);
       return 2;
     }
+
+  /* Check the target-specific validity data.  */
+  {
+    void *this_file_data = xmalloc (v.target_data_length);
+    const char *msg;
+    
+    if ((size_t) read (fd, this_file_data, v.target_data_length)
+	!= v.target_data_length)
+      fatal_error ("can't read %s: %m", name);
+    msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
+    free (this_file_data);
+    if (msg != NULL)
+      {
+	if (cpp_get_options (pfile)->warn_invalid_pch)
+	  cpp_error (pfile, DL_WARNING, "%s: %s", name, msg);
+	return 2;
+      }
+  }
 
   /* Check the preprocessor macros are the same as when the PCH was
      generated.  */
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.58
diff -u -p -p -u -r1.58 target-def.h
--- target-def.h	9 Oct 2003 09:08:32 -0000	1.58
+++ target-def.h	24 Oct 2003 20:21:22 -0000
@@ -316,6 +316,9 @@ Foundation, 59 Temple Place - Suite 330,
 
 #define TARGET_MACHINE_DEPENDENT_REORG 0
 
+#define TARGET_GET_PCH_VALIDITY default_get_pch_validity
+#define TARGET_PCH_VALID_P default_pch_valid_p
+
 #define TARGET_PROMOTE_FUNCTION_ARGS default_promote_function_args
 #define TARGET_PROMOTE_FUNCTION_RETURN default_promote_function_return
 #define TARGET_PROMOTE_PROTOTYPES default_promote_prototypes
@@ -358,7 +361,7 @@ Foundation, 59 Temple Place - Suite 330,
   TARGET_INIT_LIBFUNCS,				\
   TARGET_SECTION_TYPE_FLAGS,			\
   TARGET_CANNOT_MODIFY_JUMPS_P,			\
-  TARGET_BRANCH_TARGET_REGISTER_CLASS,	\
+  TARGET_BRANCH_TARGET_REGISTER_CLASS,		\
   TARGET_BRANCH_TARGET_REGISTER_CALLEE_SAVED,	\
   TARGET_CANNOT_FORCE_CONST_MEM,		\
   TARGET_CANNOT_COPY_INSN_P,			\
@@ -374,6 +377,8 @@ Foundation, 59 Temple Place - Suite 330,
   TARGET_ADDRESS_COST,				\
   TARGET_DWARF_REGISTER_SPAN,                   \
   TARGET_MACHINE_DEPENDENT_REORG,		\
+  TARGET_GET_PCH_VALIDITY,			\
+  TARGET_PCH_VALID_P,				\
   TARGET_HAVE_NAMED_SECTIONS,			\
   TARGET_HAVE_CTORS_DTORS,			\
   TARGET_HAVE_TLS,				\
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.66
diff -u -p -p -u -r1.66 target.h
--- target.h	9 Oct 2003 09:08:33 -0000	1.66
+++ target.h	24 Oct 2003 20:21:22 -0000
@@ -44,6 +44,8 @@ Foundation, 59 Temple Place - Suite 330,
    to gradually reduce the amount of conditional compilation that is
    scattered throughout GCC.  */
 
+#include "tm.h"
+
 struct gcc_target
 {
   /* Functions that output assembler for the target.  */
@@ -379,6 +381,15 @@ struct gcc_target
   /* Do machine-dependent code transformations.  Called just before
      delayed-branch scheduling.  */
   void (* machine_dependent_reorg) (void);
+
+  /* Validity-checking routines for PCH files, target-specific.
+     get_pch_validity returns a pointer to the data to be stored,
+     and stores the size in its argument.  pch_valid_p gets the same
+     information back and returns NULL if the PCH is valid,
+     or an error message if not.
+  */
+  void * (* get_pch_validity) (size_t *);
+  const char * (* pch_valid_p) (const void *, size_t);
 
   /* Leave the boolean fields at the end.  */
 
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.838
diff -u -p -p -u -r1.838 toplev.c
--- toplev.c	23 Oct 2003 14:18:12 -0000	1.838
+++ toplev.c	24 Oct 2003 20:21:23 -0000
@@ -4099,6 +4099,115 @@ init_asm_output (const char *name)
     }
 }
 
+/* Default version of get_pch_validity.
+   By default, every flag difference is fatal; that will be mostly right for
+   most targets, but completely right for very few.  */
+
+void *
+default_get_pch_validity (size_t *len)
+{
+  size_t i;
+  char *result, *r;
+  
+  *len = sizeof (target_flags) + 2;
+  for (i = 0; i < ARRAY_SIZE (target_options); i++)
+    {
+      *len += 1;
+      if (*target_options[i].variable)
+	*len += strlen (*target_options[i].variable);
+    }
+
+  result = r = xmalloc (*len);
+  r[0] = flag_pic;
+  r[1] = flag_pie;
+  r += 2;
+  memcpy (r, &target_flags, sizeof (target_flags));
+  r += sizeof (target_flags);
+  
+  for (i = 0; i < ARRAY_SIZE (target_options); i++)
+    {
+      const char *str = *target_options[i].variable;
+      size_t l;
+      if (! str)
+	str = "";
+      l = strlen (str) + 1;
+      memcpy (r, str, l);
+      r += l;
+    }
+
+  return result;
+}
+
+/* Default version of pch_valid_p.  */
+
+const char *
+default_pch_valid_p (const void *data_p, size_t len)
+{
+  const char *data = (const char *)data_p;
+  const char *flag_that_differs = NULL;
+  size_t i;
+  
+  /* -fpic and -fpie also usually make a PCH invalid.  */
+  if (data[0] != flag_pic)
+    return _("created and used with different settings of -fpic");
+  if (data[1] != flag_pie)
+    return _("created and used with different settings of -fpie");
+  data += 2;
+
+  /* Check target_flags.  */
+  if (memcmp (data, &target_flags, sizeof (target_flags)) != 0)
+    {
+      for (i = 0; i < ARRAY_SIZE (target_switches); i++)
+	{
+	  int bits;
+	  int tf;
+
+	  memcpy (&tf, data, sizeof (target_flags));
+
+	  bits = target_switches[i].value;
+	  if (bits < 0)
+	    bits = -bits;
+	  if ((target_flags & bits) != (tf & bits))
+	    {
+	      flag_that_differs = target_switches[i].name;
+	      goto make_message;
+	    }
+	}
+      abort ();
+    }
+  data += sizeof (target_flags);
+  len -= sizeof (target_flags);
+  
+  /* Check string options.  */
+  for (i = 0; i < ARRAY_SIZE (target_options); i++)
+    {
+      const char *str = *target_options[i].variable;
+      size_t l;
+      if (! str)
+	str = "";
+      l = strlen (str) + 1;
+      if (len < l || memcmp (data, str, l) != 0)
+	{
+	  flag_that_differs = target_options[i].prefix;
+	  goto make_message;
+	}
+      data += l;
+      len -= l;
+    }
+
+  return NULL;
+  
+ make_message:
+  {
+    char *r;
+    asprintf (&r, _("created and used with differing settings of `-m%s'"),
+		  flag_that_differs);
+    if (r == NULL)
+      r = _("out of memory");
+    return r;
+  }
+}
+
 /* Default tree printer.   Handles declarations only.  */
 static bool
 default_tree_printer (pretty_printer * pp, text_info *text)
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.h,v
retrieving revision 1.114
diff -u -p -p -u -r1.114 toplev.h
--- toplev.h	8 Sep 2003 15:56:18 -0000	1.114
+++ toplev.h	24 Oct 2003 20:21:23 -0000
@@ -124,9 +124,12 @@ extern int flag_ssa_dce;
 extern int time_report;
 extern int flag_new_regalloc;
 
+/* Things to do with target switches.  */
 extern void display_target_options (void);
 extern void print_version (FILE *, const char *);
 extern void set_target_switch (const char *);
+extern void * default_get_pch_validity (size_t *);
+extern const char * default_pch_valid_p (const void *, size_t);
 
 /* The hashtable, so that the C front ends can pass it to cpplib.  */
 extern struct ht *ident_hash;
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.263
diff -u -p -p -u -r1.263 tm.texi
--- doc/tm.texi	17 Oct 2003 11:27:13 -0000	1.263
+++ doc/tm.texi	24 Oct 2003 20:21:24 -0000
@@ -50,6 +50,7 @@ through the macros defined in the @file{
 * Mode Switching::      Insertion of mode-switching instructions.
 * Target Attributes::   Defining target-specific uses of @code{__attribute__}.
 * MIPS Coprocessors::   MIPS coprocessor support and how to customize it.
+* PCH Target::          Validity checking for precompiled headers.
 * Misc::                Everything else.
 @end menu
 
@@ -8386,6 +8387,30 @@ alternate names of coprocessor registers
 @end smallexample
 Default: empty.
 @end defmac
+
+@node PCH Target
+@section Parameters for Precompiled Header Validity Checking
+@cindex parameters, precompiled headers
+
+@deftypefn {Target Hook} void * TARGET_GET_PCH_VALIDITY (size_t * @var{sz})
+Define this hook if your target needs to check a different collection
+of flags than the default, which is every flag defined by
+@code{TARGET_SWITCHES} and @code{TARGET_OPTIONS}.  It should return
+some data which will be saved in the PCH file and presented to
+@code{TARGET_PCH_VALID_P} later; it should set @code{SZ} to the size
+of the data.
+@end deftypefn
+
+@deftypefn {Target Hook} const char * TARGET_PCH_VALID_P (const void * @var{data}, size_t @var{sz})
+Define this hook if your target needs to check a different collection of
+flags than the default, which is every flag defined by @code{TARGET_SWITCHES}
+and @code{TARGET_OPTIONS}.  It is given data which came from
+@code{TARGET_GET_PCH_VALIDITY} (in this version of this compiler, so there
+is no need for extensive validity checking).  It returns @code{NULL} if
+it is safe to load a PCH file with this data, or a suitable error message
+if not.  The error message will be presented to the user, so it should
+be localised.
+@end deftypefn
 
 @node Misc
 @section Miscellaneous Parameters
============================================================


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