mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-16 04:20:26 +08:00
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
This commit is contained in:
parent
eebf21ef99
commit
7bb1ad9314
@ -1,3 +1,26 @@
|
||||
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.
|
||||
|
||||
2003-10-24 Kelley Cook <kcook@gcc.gnu.org>
|
||||
|
||||
* Makefile.in: Define a vpath for %.texi. Remove explicit $(docdir)
|
||||
|
@ -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
|
||||
|
38
gcc/c-pch.c
38
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. */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, \
|
||||
|
11
gcc/target.h
11
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. */
|
||||
|
109
gcc/toplev.c
109
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)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user