Hi, Current in LTO static const bounds are created as external symbol. It doesn't work in case original symbols were removed and privatized. This patch introduces a separate comdat symbol to be used in LTO. Bootstrapped and tested on x86_64-unknown-linux-gnu. Does this approach look OK?
Thanks, Ilya -- gcc/ 2015-04-02 Ilya Enkovich <ilya.enkov...@intel.com> * tree-chkp.c (CHKP_LTO_SYMBOL_SUFFIX): New. (chkp_make_static_const_bounds): Use another symbol in LTO. gcc/testsuite/ 2015-04-02 Ilya Enkovich <ilya.enkov...@intel.com> * gcc.dg/lto/chkp-static-bounds_0.c: New. diff --git a/gcc/testsuite/gcc.dg/lto/chkp-static-bounds_0.c b/gcc/testsuite/gcc.dg/lto/chkp-static-bounds_0.c new file mode 100644 index 0000000..e896eb1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/chkp-static-bounds_0.c @@ -0,0 +1,26 @@ +/* { dg-lto-do link } */ +/* { dg-require-effective-target mpx } */ +/* { dg-lto-options { { -flto -flto-partition=max -fcheck-pointer-bounds -mmpx } } } */ + +char *cc; + +int test1 (const char *c) +{ + c = __builtin___bnd_init_ptr_bounds (c); + cc = c; + return c[0] * 2; +} + +struct S +{ + int (*fnptr) (const char *); +} S; + +struct S s1 = {test1}; +struct S s2 = {test1}; +struct S s3 = {test1}; + +int main (int argc, const char **argv) +{ + return s1.fnptr (argv[0]) + s2.fnptr (argv[1]); +} diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index d2df4ba..0578936 100644 --- a/gcc/tree-chkp.c +++ b/gcc/tree-chkp.c @@ -421,6 +421,7 @@ static bool in_chkp_pass; #define CHKP_VAR_BOUNDS_PREFIX "__chkp_var_bounds_" #define CHKP_ZERO_BOUNDS_VAR_NAME "__chkp_zero_bounds" #define CHKP_NONE_BOUNDS_VAR_NAME "__chkp_none_bounds" +#define CHKP_LTO_SYMBOL_SUFFIX ".lto" /* Static checker constructors may become very large and their compilation with optimization may take too much time. @@ -1906,7 +1907,8 @@ chkp_make_static_const_bounds (HOST_WIDE_INT lb, HOST_WIDE_INT ub, const char *name) { - tree var; + tree var, id; + varpool_node *node; /* With LTO we may have constant bounds already in varpool. Try to find it. */ @@ -1915,8 +1917,22 @@ chkp_make_static_const_bounds (HOST_WIDE_INT lb, if (var) return var; - var = build_decl (UNKNOWN_LOCATION, VAR_DECL, - get_identifier (name), pointer_bounds_type_node); + /* In LTO we may have symbol with changed visibility, comdat + group etc. Therefore we shouldn't recreate the same symbol. + Use LTO version instead. */ + if (in_lto_p) + { + int len = strlen (name) + strlen (CHKP_LTO_SYMBOL_SUFFIX) + 1; + char *new_name = XALLOCAVEC (char, len); + strcpy (new_name, name); + strcat (new_name, CHKP_LTO_SYMBOL_SUFFIX); + id = get_identifier (new_name); + } + else + id = get_identifier (name); + + var = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, + pointer_bounds_type_node); TREE_PUBLIC (var) = 1; TREE_USED (var) = 1; @@ -1925,18 +1941,17 @@ chkp_make_static_const_bounds (HOST_WIDE_INT lb, TREE_ADDRESSABLE (var) = 0; DECL_ARTIFICIAL (var) = 1; DECL_READ_P (var) = 1; + DECL_INITIAL (var) = targetm.chkp_make_bounds_constant (lb, ub); + DECL_COMDAT (var) = 1; + DECL_WEAK (var) = 1; /* We may use this symbol during ctors generation in chkp_finish_file when all symbols are emitted. Force output to avoid undefined symbols in ctors. */ - if (!in_lto_p) - { - DECL_INITIAL (var) = targetm.chkp_make_bounds_constant (lb, ub); - DECL_COMDAT (var) = 1; - varpool_node::get_create (var)->set_comdat_group (DECL_ASSEMBLER_NAME (var)); - varpool_node::get_create (var)->force_output = 1; - } - else - DECL_EXTERNAL (var) = 1; + node = varpool_node::get_create (var); + node->set_comdat_group (DECL_ASSEMBLER_NAME (var)); + node->force_output = 1; + node->externally_visible = 1; + varpool_node::finalize_decl (var); return var;