From 7bb1ad9314f7e671cf8c4b69da55dc0afe7cba01 Mon Sep 17 00:00:00 2001 From: Geoffrey Keating Date: Fri, 24 Oct 2003 21:28:13 +0000 Subject: [PATCH] re PR pch/10757 (Adding -fpic/-fPIC causes crash with PCH created without -fpic/-fPIC) 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. From-SVN: r72909 --- gcc/ChangeLog | 23 ++++++++++++ gcc/Makefile.in | 8 ++-- gcc/c-pch.c | 38 ++++++++++++++++--- gcc/doc/tm.texi | 25 +++++++++++++ gcc/target-def.h | 7 +++- gcc/target.h | 11 ++++++ gcc/toplev.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/toplev.h | 3 ++ 8 files changed, 214 insertions(+), 10 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a392a2a..2fcdbce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2003-10-24 Geoffrey Keating + + 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. + 2003-10-24 Kelley Cook * Makefile.in: Define a vpath for %.texi. Remove explicit $(docdir) diff --git a/gcc/Makefile.in b/gcc/Makefile.in index ef9ba4a..6097e1f 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -640,7 +640,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) @@ -1371,7 +1371,7 @@ c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ 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) @@ -1580,7 +1580,7 @@ explow.o : explow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_ 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 \ @@ -1822,7 +1822,7 @@ regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_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 diff --git a/gcc/c-pch.c b/gcc/c-pch.c index f7830b2..2a29075 100644 --- a/gcc/c-pch.c +++ b/gcc/c-pch.c @@ -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) @@ -299,6 +309,24 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd) 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. */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 8a0ff9b..09f8295 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -50,6 +50,7 @@ through the macros defined in the @file{.h} 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 @@ -8387,6 +8388,30 @@ alternate names of coprocessor registers. The format of each entry should be 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 @cindex parameters, miscellaneous diff --git a/gcc/target-def.h b/gcc/target-def.h index 3f35e2e..5c7fcb0 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -316,6 +316,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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, Boston, MA 02111-1307, USA. 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, Boston, MA 02111-1307, USA. 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, \ diff --git a/gcc/target.h b/gcc/target.h index 8d77dfd..0b19445 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -44,6 +44,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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. */ @@ -380,6 +382,15 @@ struct gcc_target 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. */ /* True if arbitrary sections are supported. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 41b27ed..3e350bf 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -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) diff --git a/gcc/toplev.h b/gcc/toplev.h index ae05f4b..5a8b581 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -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; -- 2.7.4