re PR bootstrap/66521 (xgcc: cc1plus segfaults when compiling libstdc++-v3/src/c++11/ostream-inst.cc)

Fix PR 66521

libvtv/ChangeLog

2015-08-01  Caroline Tice  <cmtice@google.com>

        PR 66521
        * Makefile.am: Update to match latest tree.
        * Makefile.in: Regenerate.
        * testsuite/lib/libvtv: Brought up to date.
        * vtv_malloc.cc (VTV_DEBUG): Update function call to match renamed
        function (old bug!).
        * vtv_rts.cc (debug_functions, debug_init, debug_verify_vtable): Update
        initializations to work correctly with VTV_DEBUG defined.

gcc/ChangeLog:

2015-08-01  Caroline Tice  <cmtice@google.com>

        PR 66521
        * vtable-verify.c (vtbl_mangled_name_types, vtbl_mangled_name_ids): New
        global variables.
        (vtbl_find_mangled_name):  New function.
        (vtbl_register_mangled_name):  New function.
        (vtbl_map_get_node):  If DECL_ASSEMBLER_NAME is "<anon>", look up
        mangled name in mangled name vectors.
        (find_or_create_vtbl_map_node):  Ditto.
        (var_is_used_for_virtual_call_p):  Add recursion_depth parameter;
        update recursion_depth on function entry; pass it to every recursive
        call; automatically exit if depth > 25 (give up looking at that point).
        (verify_bb_vtables):  Initialize recursion_depth and pass it to
        var_is_used_for_virtual_call_p.
        * vtable-verify.h (vtbl_mangbled_name_types, vtbl_mangled_name_ids): New
        global variable decls.
        (vtbl_register_mangled_name): New extern function decl.

gcc/cp/ChangeLog:
2015-08-01  Caroline Tice  <cmtice@google.com>

        PR 66521
        * mangle.c : Add vtable-verify.h to include files.
        (get_mangled_vtable_map_var_name):  If the DECL_ASSEMBLER_NAME
        is "<anon>" get the real mangled name for the class instead, and
        also store the real mangled name in a vector for use later.

From-SVN: r226471
This commit is contained in:
Caroline Tice 2015-08-01 18:17:39 -07:00 committed by Caroline Tice
parent 68e3e6a259
commit b0cca5ecbb
11 changed files with 186 additions and 33 deletions

View File

@ -1,3 +1,22 @@
2015-08-01 Caroline Tice <cmtice@google.com>
PR 66521
* vtable-verify.c (vtbl_mangled_name_types, vtbl_mangled_name_ids): New
global variables.
(vtbl_find_mangled_name): New function.
(vtbl_register_mangled_name): New function.
(vtbl_map_get_node): If DECL_ASSEMBLER_NAME is "<anon>", look up
mangled name in mangled name vectors.
(find_or_create_vtbl_map_node): Ditto.
(var_is_used_for_virtual_call_p): Add recursion_depth parameter;
update recursion_depth on function entry; pass it to every recursive
call; automatically exit if depth > 25 (give up looking at that point).
(verify_bb_vtables): Initialize recursion_depth and pass it to
var_is_used_for_virtual_call_p.
* vtable-verify.h (vtbl_mangbled_name_types, vtbl_mangled_name_ids): New
global variable decls.
(vtbl_register_mangled_name): New extern function decl.
2015-08-01 Tom de Vries <tom@codesourcery.com> 2015-08-01 Tom de Vries <tom@codesourcery.com>
* tree.c (operation_can_overflow, operation_no_trapping_overflow): New * tree.c (operation_can_overflow, operation_no_trapping_overflow): New

View File

@ -1,3 +1,11 @@
2015-08-01 Caroline Tice <cmtice@google.com>
PR 66521
* mangle.c : Add vtable-verify.h to include files.
(get_mangled_vtable_map_var_name): If the DECL_ASSEMBLER_NAME
is "<anon>" get the real mangled name for the class instead, and
also store the real mangled name in a vector for use later.
2015-07-31 Marek Polacek <polacek@redhat.com> 2015-07-31 Marek Polacek <polacek@redhat.com>
PR sanitizer/66977 PR sanitizer/66977

View File

@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "function.h" #include "function.h"
#include "cgraph.h" #include "cgraph.h"
#include "attribs.h" #include "attribs.h"
#include "vtable-verify.h"
/* Debugging support. */ /* Debugging support. */
@ -4036,6 +4037,13 @@ get_mangled_vtable_map_var_name (tree class_type)
gcc_assert (TREE_CODE (class_type) == RECORD_TYPE); gcc_assert (TREE_CODE (class_type) == RECORD_TYPE);
tree class_id = DECL_ASSEMBLER_NAME (TYPE_NAME (class_type)); tree class_id = DECL_ASSEMBLER_NAME (TYPE_NAME (class_type));
if (strstr (IDENTIFIER_POINTER (class_id), "<anon>") != NULL)
{
class_id = get_mangled_id (TYPE_NAME (class_type));
vtbl_register_mangled_name (TYPE_NAME (class_type), class_id);
}
unsigned int len = strlen (IDENTIFIER_POINTER (class_id)) + unsigned int len = strlen (IDENTIFIER_POINTER (class_id)) +
strlen (prefix) + strlen (prefix) +
strlen (postfix) + 1; strlen (postfix) + 1;

View File

@ -310,6 +310,70 @@ static vtbl_map_table_type *vtbl_map_hash;
/* Vtable map variable nodes stored in a vector. */ /* Vtable map variable nodes stored in a vector. */
vec<struct vtbl_map_node *> vtbl_map_nodes_vec; vec<struct vtbl_map_node *> vtbl_map_nodes_vec;
/* Vector of mangled names for anonymous classes. */
extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_types;
extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_ids;
vec<tree, va_gc> *vtbl_mangled_name_types;
vec<tree, va_gc> *vtbl_mangled_name_ids;
/* Look up class_type (a type decl for record types) in the vtbl_mangled_names_*
vectors. This is a linear lookup. Return the associated mangled name for
the class type. This is for handling types from anonymous namespaces, whose
DECL_ASSEMBLER_NAME ends up being "<anon>", which is useless for our
purposes.
We use two vectors of trees to keep track of the mangled names: One is a
vector of class types and the other is a vector of the mangled names. The
assumption is that these two vectors are kept in perfect lock-step so that
vtbl_mangled_name_ids[i] is the mangled name for
vtbl_mangled_name_types[i]. */
static tree
vtbl_find_mangled_name (tree class_type)
{
tree result = NULL_TREE;
unsigned i;
if (!vtbl_mangled_name_types or !vtbl_mangled_name_ids)
return result;
if (vtbl_mangled_name_types->length() != vtbl_mangled_name_ids->length())
return result;
for (i = 0; i < vtbl_mangled_name_types->length(); ++i)
if ((*vtbl_mangled_name_types)[i] == class_type)
{
result = (*vtbl_mangled_name_ids)[i];
break;
}
return result;
}
/* Store a class type decl and its mangled name, for an anonymous RECORD_TYPE,
in the vtbl_mangled_names vector. Make sure there is not already an
entry for the class type before adding it. */
void
vtbl_register_mangled_name (tree class_type, tree mangled_name)
{
if (!vtbl_mangled_name_types)
vec_alloc (vtbl_mangled_name_types, 10);
if (!vtbl_mangled_name_ids)
vec_alloc (vtbl_mangled_name_ids, 10);
gcc_assert (vtbl_mangled_name_types->length() ==
vtbl_mangled_name_ids->length());
if (vtbl_find_mangled_name (class_type) == NULL_TREE)
{
vec_safe_push (vtbl_mangled_name_types, class_type);
vec_safe_push (vtbl_mangled_name_ids, mangled_name);
}
}
/* Return vtbl_map node for CLASS_NAME without creating a new one. */ /* Return vtbl_map node for CLASS_NAME without creating a new one. */
struct vtbl_map_node * struct vtbl_map_node *
@ -339,6 +403,9 @@ vtbl_map_get_node (tree class_type)
gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl)); gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl));
class_name = DECL_ASSEMBLER_NAME (class_type_decl); class_name = DECL_ASSEMBLER_NAME (class_type_decl);
if (strstr (IDENTIFIER_POINTER (class_name), "<anon>") != NULL)
class_name = vtbl_find_mangled_name (class_type_decl);
key.class_name = class_name; key.class_name = class_name;
slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, NO_INSERT); slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, NO_INSERT);
if (!slot) if (!slot)
@ -370,6 +437,10 @@ find_or_create_vtbl_map_node (tree base_class_type)
gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl)); gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl));
key.class_name = DECL_ASSEMBLER_NAME (class_type_decl); key.class_name = DECL_ASSEMBLER_NAME (class_type_decl);
if (strstr (IDENTIFIER_POINTER (key.class_name), "<anon>") != NULL)
key.class_name = vtbl_find_mangled_name (class_type_decl);
slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, INSERT); slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, INSERT);
if (*slot) if (*slot)
@ -482,7 +553,8 @@ extract_object_class_type (tree rhs)
the use chain. */ the use chain. */
static bool static bool
var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth) var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth,
int *recursion_depth)
{ {
imm_use_iterator imm_iter; imm_use_iterator imm_iter;
bool found_vcall = false; bool found_vcall = false;
@ -494,6 +566,14 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
if (*mem_ref_depth > 2) if (*mem_ref_depth > 2)
return false; return false;
if (*recursion_depth > 25)
/* If we've recursed this far the chances are pretty good that
we're not going to find what we're looking for, and that we've
gone down a recursion black hole. Time to stop. */
return false;
*recursion_depth = *recursion_depth + 1;
/* Iterate through the immediate uses of the current variable. If /* Iterate through the immediate uses of the current variable. If
it's a virtual function call, we're done. Otherwise, if there's it's a virtual function call, we're done. Otherwise, if there's
an LHS for the use stmt, add the ssa var to the work list an LHS for the use stmt, add the ssa var to the work list
@ -516,7 +596,8 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
{ {
found_vcall = var_is_used_for_virtual_call_p found_vcall = var_is_used_for_virtual_call_p
(gimple_phi_result (stmt2), (gimple_phi_result (stmt2),
mem_ref_depth); mem_ref_depth,
recursion_depth);
} }
else if (is_gimple_assign (stmt2)) else if (is_gimple_assign (stmt2))
{ {
@ -538,7 +619,8 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
if (*mem_ref_depth < 3) if (*mem_ref_depth < 3)
found_vcall = var_is_used_for_virtual_call_p found_vcall = var_is_used_for_virtual_call_p
(gimple_assign_lhs (stmt2), (gimple_assign_lhs (stmt2),
mem_ref_depth); mem_ref_depth,
recursion_depth);
} }
else else
@ -595,9 +677,11 @@ verify_bb_vtables (basic_block bb)
tree tmp0; tree tmp0;
bool found; bool found;
int mem_ref_depth = 0; int mem_ref_depth = 0;
int recursion_depth = 0;
/* Make sure this vptr field access is for a virtual call. */ /* Make sure this vptr field access is for a virtual call. */
if (!var_is_used_for_virtual_call_p (lhs, &mem_ref_depth)) if (!var_is_used_for_virtual_call_p (lhs, &mem_ref_depth,
&recursion_depth))
continue; continue;
/* Now we have found the virtual method dispatch and /* Now we have found the virtual method dispatch and

View File

@ -127,6 +127,11 @@ extern bool vtv_debug;
/* The global vector of vtbl_map_nodes. */ /* The global vector of vtbl_map_nodes. */
extern vec<struct vtbl_map_node *> vtbl_map_nodes_vec; extern vec<struct vtbl_map_node *> vtbl_map_nodes_vec;
/* The global vectors for mangled class names for anonymous classes. */
extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_types;
extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_ids;
extern void vtbl_register_mangled_name (tree, tree);
extern struct vtbl_map_node *vtbl_map_get_node (tree); extern struct vtbl_map_node *vtbl_map_get_node (tree);
extern struct vtbl_map_node *find_or_create_vtbl_map_node (tree); extern struct vtbl_map_node *find_or_create_vtbl_map_node (tree);
extern void vtbl_map_node_class_insert (struct vtbl_map_node *, unsigned); extern void vtbl_map_node_class_insert (struct vtbl_map_node *, unsigned);

View File

@ -1,3 +1,14 @@
2015-08-01 Caroline Tice <cmtice@google.com>
PR 66521
* Makefile.am: Update to match latest tree.
* Makefile.in: Regenerate.
* testsuite/lib/libvtv: Brought up to date.
* vtv_malloc.cc (VTV_DEBUG): Update function call to match renamed
function (old bug!).
* vtv_rts.cc (debug_functions, debug_init, debug_verify_vtable): Update
initializations to work correctly with VTV_DEBUG defined.
2015-05-13 Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com> 2015-05-13 Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
* Makefile.in: Regenerated with automake-1.11.6. * Makefile.in: Regenerated with automake-1.11.6.

View File

@ -1,11 +1,13 @@
## Process this with automake to create Makefile.in ## Process this file with automake to produce Makefile.in.
AUTOMAKE_OPTIONS = foreign dejagnu AUTOMAKE_OPTIONS = foreign dejagnu
EXPECT = `if [ -f ../../expect/expect ] ; then \ # May be used by various substitution variables.
echo ../../expect/expect ; \ gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
else echo expect ; fi`
RUNTEST = `if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \ EXPECT = $(shell if test -f $(top_builddir)/../expect/expect; then \
echo ${srcdir}/../../dejagnu/runtest ; \ echo $(top_builddir)/../expect/expect; else echo expect; fi)
else echo runtest ; fi`
_RUNTEST = $(shell if test -f $(top_srcdir)/../dejagnu/runtest; then \
echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi)
RUNTEST = "$(_RUNTEST) $(AM_RUNTESTFLAGS)"

View File

@ -217,14 +217,16 @@ top_srcdir = @top_srcdir@
toplevel_builddir = @toplevel_builddir@ toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@ toplevel_srcdir = @toplevel_srcdir@
AUTOMAKE_OPTIONS = foreign dejagnu AUTOMAKE_OPTIONS = foreign dejagnu
EXPECT = `if [ -f ../../expect/expect ] ; then \
echo ../../expect/expect ; \
else echo expect ; fi`
RUNTEST = `if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \ # May be used by various substitution variables.
echo ${srcdir}/../../dejagnu/runtest ; \ gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
else echo runtest ; fi` EXPECT = $(shell if test -f $(top_builddir)/../expect/expect; then \
echo $(top_builddir)/../expect/expect; else echo expect; fi)
_RUNTEST = $(shell if test -f $(top_srcdir)/../dejagnu/runtest; then \
echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi)
RUNTEST = "$(_RUNTEST) $(AM_RUNTESTFLAGS)"
all: all-am all: all-am
.SUFFIXES: .SUFFIXES:

View File

@ -23,24 +23,28 @@ proc load_gcc_lib { filename } {
} }
load_lib dg.exp load_lib dg.exp
load_gcc_lib file-format.exp
# Required to use gcc-dg.exp - however, the latter should NOT be
# loaded until ${tool}_target_compile is defined since it uses that
# to determine default LTO options.
load_gcc_lib prune.exp
load_gcc_lib target-libpath.exp
load_gcc_lib wrapper.exp
load_gcc_lib target-supports.exp load_gcc_lib target-supports.exp
load_gcc_lib target-supports-dg.exp
load_gcc_lib target-utils.exp load_gcc_lib target-utils.exp
load_gcc_lib gcc-defs.exp
load_gcc_lib timeout.exp
load_gcc_lib file-format.exp
load_gcc_lib target-supports-dg.exp
load_gcc_lib scanasm.exp load_gcc_lib scanasm.exp
load_gcc_lib scandump.exp load_gcc_lib scandump.exp
load_gcc_lib scanrtl.exp load_gcc_lib scanrtl.exp
load_gcc_lib scantree.exp load_gcc_lib scantree.exp
load_gcc_lib scanipa.exp load_gcc_lib scanipa.exp
load_gcc_lib prune.exp
load_gcc_lib target-libpath.exp
load_gcc_lib wrapper.exp
load_gcc_lib gcc-defs.exp
load_gcc_lib torture-options.exp
load_gcc_lib timeout.exp
load_gcc_lib timeout-dg.exp load_gcc_lib timeout-dg.exp
load_gcc_lib torture-options.exp
load_gcc_lib fortran-modules.exp load_gcc_lib fortran-modules.exp
load_gcc_lib gcc-dg.exp
set dg-do-what-default run set dg-do-what-default run
@ -143,10 +147,20 @@ proc libvtv_init { args } {
} }
lappend ALWAYS_CFLAGS "additional_flags=-I${srcdir}/.." lappend ALWAYS_CFLAGS "additional_flags=-I${srcdir}/.."
# We use atomic operations in the testcases to validate results.
if { ([istarget i?86-*-*] || [istarget x86_64-*-*])
&& [check_effective_target_ia32] } {
lappend ALWAYS_CFLAGS "additional_flags=-march=i486"
}
if [istarget *-*-darwin*] { if [istarget *-*-darwin*] {
lappend ALWAYS_CFLAGS "additional_flags=-shared-libgcc" lappend ALWAYS_CFLAGS "additional_flags=-shared-libgcc"
} }
if [istarget sparc*-*-*] {
lappend ALWAYS_CFLAGS "additional_flags=-mcpu=v9"
}
if [info exists TOOL_OPTIONS] { if [info exists TOOL_OPTIONS] {
lappend ALWAYS_CFLAGS "additional_flags=$TOOL_OPTIONS" lappend ALWAYS_CFLAGS "additional_flags=$TOOL_OPTIONS"
} }
@ -155,9 +169,8 @@ proc libvtv_init { args } {
# error-message parsing machinery. # error-message parsing machinery.
lappend ALWAYS_CFLAGS "additional_flags=-fmessage-length=0" lappend ALWAYS_CFLAGS "additional_flags=-fmessage-length=0"
# Turn on vtable verification # Turn on vtable verification.
lappend ALWAYS_CFLAGS "-fvtable-verify=std" lappend ALWAYS_CFLAGS "additional_flags=-fvtable-verify=std"
# lappend ALWAYS_CFLAGS "ldflags=-lvtv"
} }
# #

View File

@ -145,7 +145,7 @@ change_protections_on_data_chunks (int protection_flag)
} }
#ifdef VTV_DEBUG #ifdef VTV_DEBUG
VTV_malloc_dump_stats (); __vtv_malloc_dump_stats ();
#endif #endif
} }

View File

@ -201,14 +201,15 @@ unsigned long long verify_vtable_cycles = 0;
debugging/tracing will not be ON on production environments */ debugging/tracing will not be ON on production environments */
static const bool debug_hash = HASHTABLE_STATS; static const bool debug_hash = HASHTABLE_STATS;
static const int debug_functions = 0;
static const int debug_init = 0;
static const int debug_verify_vtable = 0;
#ifdef VTV_DEBUG #ifdef VTV_DEBUG
static const int debug_functions = 1; static const int debug_functions = 1;
static const int debug_init = 1; static const int debug_init = 1;
static const int debug_verify_vtable = 1; static const int debug_verify_vtable = 1;
#else
static const int debug_functions = 0;
static const int debug_init = 0;
static const int debug_verify_vtable = 0;
#endif #endif
/* Global file descriptor variables for logging, tracing and debugging. */ /* Global file descriptor variables for logging, tracing and debugging. */