diff options
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 8 | ||||
-rw-r--r-- | gcc/vtable-verify.c | 92 | ||||
-rw-r--r-- | gcc/vtable-verify.h | 5 | ||||
-rw-r--r-- | libvtv/ChangeLog | 11 | ||||
-rw-r--r-- | libvtv/testsuite/Makefile.am | 16 | ||||
-rw-r--r-- | libvtv/testsuite/Makefile.in | 14 | ||||
-rw-r--r-- | libvtv/testsuite/lib/libvtv.exp | 37 | ||||
-rw-r--r-- | libvtv/vtv_malloc.cc | 2 | ||||
-rw-r--r-- | libvtv/vtv_rts.cc | 7 |
11 files changed, 186 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53b44c1..ea9dbe1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> * tree.c (operation_can_overflow, operation_no_trapping_overflow): New diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8d286a6..db7d616 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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> PR sanitizer/66977 diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index b4d4c0e..d471f4f 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "cgraph.h" #include "attribs.h" +#include "vtable-verify.h" /* Debugging support. */ @@ -4036,6 +4037,13 @@ get_mangled_vtable_map_var_name (tree class_type) gcc_assert (TREE_CODE (class_type) == RECORD_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)) + strlen (prefix) + strlen (postfix) + 1; diff --git a/gcc/vtable-verify.c b/gcc/vtable-verify.c index 46506af..a834588 100644 --- a/gcc/vtable-verify.c +++ b/gcc/vtable-verify.c @@ -310,6 +310,70 @@ static vtbl_map_table_type *vtbl_map_hash; /* Vtable map variable nodes stored in a vector. */ 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. */ 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)); 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; slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, NO_INSERT); 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)); 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); if (*slot) @@ -482,7 +553,8 @@ extract_object_class_type (tree rhs) the use chain. */ 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; 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) 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 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 @@ -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 (gimple_phi_result (stmt2), - mem_ref_depth); + mem_ref_depth, + recursion_depth); } 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) found_vcall = var_is_used_for_virtual_call_p (gimple_assign_lhs (stmt2), - mem_ref_depth); + mem_ref_depth, + recursion_depth); } else @@ -595,9 +677,11 @@ verify_bb_vtables (basic_block bb) tree tmp0; bool found; int mem_ref_depth = 0; + int recursion_depth = 0; /* 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; /* Now we have found the virtual method dispatch and diff --git a/gcc/vtable-verify.h b/gcc/vtable-verify.h index dda6f06..178ba36 100644 --- a/gcc/vtable-verify.h +++ b/gcc/vtable-verify.h @@ -127,6 +127,11 @@ extern bool vtv_debug; /* The global vector of vtbl_map_nodes. */ 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 *find_or_create_vtbl_map_node (tree); extern void vtbl_map_node_class_insert (struct vtbl_map_node *, unsigned); diff --git a/libvtv/ChangeLog b/libvtv/ChangeLog index d7fd975..612c660 100644 --- a/libvtv/ChangeLog +++ b/libvtv/ChangeLog @@ -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> * Makefile.in: Regenerated with automake-1.11.6. diff --git a/libvtv/testsuite/Makefile.am b/libvtv/testsuite/Makefile.am index a2c1e9f..561b7e2 100644 --- a/libvtv/testsuite/Makefile.am +++ b/libvtv/testsuite/Makefile.am @@ -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 -EXPECT = `if [ -f ../../expect/expect ] ; then \ - echo ../../expect/expect ; \ - else echo expect ; fi` +# May be used by various substitution variables. +gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) -RUNTEST = `if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \ - echo ${srcdir}/../../dejagnu/runtest ; \ - 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)" diff --git a/libvtv/testsuite/Makefile.in b/libvtv/testsuite/Makefile.in index 49f8f71..e19e13e 100644 --- a/libvtv/testsuite/Makefile.in +++ b/libvtv/testsuite/Makefile.in @@ -217,14 +217,16 @@ top_srcdir = @top_srcdir@ toplevel_builddir = @toplevel_builddir@ toplevel_srcdir = @toplevel_srcdir@ AUTOMAKE_OPTIONS = foreign dejagnu -EXPECT = `if [ -f ../../expect/expect ] ; then \ - echo ../../expect/expect ; \ - else echo expect ; fi` -RUNTEST = `if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \ - echo ${srcdir}/../../dejagnu/runtest ; \ - else echo runtest ; fi` +# May be used by various substitution variables. +gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) +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 .SUFFIXES: diff --git a/libvtv/testsuite/lib/libvtv.exp b/libvtv/testsuite/lib/libvtv.exp index c473b0a..aefcbd2 100644 --- a/libvtv/testsuite/lib/libvtv.exp +++ b/libvtv/testsuite/lib/libvtv.exp @@ -23,24 +23,28 @@ proc load_gcc_lib { filename } { } 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-dg.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 scandump.exp load_gcc_lib scanrtl.exp load_gcc_lib scantree.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 torture-options.exp load_gcc_lib fortran-modules.exp -load_gcc_lib gcc-dg.exp set dg-do-what-default run @@ -143,10 +147,20 @@ proc libvtv_init { args } { } 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*] { lappend ALWAYS_CFLAGS "additional_flags=-shared-libgcc" } + if [istarget sparc*-*-*] { + lappend ALWAYS_CFLAGS "additional_flags=-mcpu=v9" + } + if [info exists TOOL_OPTIONS] { lappend ALWAYS_CFLAGS "additional_flags=$TOOL_OPTIONS" } @@ -155,9 +169,8 @@ proc libvtv_init { args } { # error-message parsing machinery. lappend ALWAYS_CFLAGS "additional_flags=-fmessage-length=0" - # Turn on vtable verification - lappend ALWAYS_CFLAGS "-fvtable-verify=std" - # lappend ALWAYS_CFLAGS "ldflags=-lvtv" + # Turn on vtable verification. + lappend ALWAYS_CFLAGS "additional_flags=-fvtable-verify=std" } # diff --git a/libvtv/vtv_malloc.cc b/libvtv/vtv_malloc.cc index 4b675f4..5249248 100644 --- a/libvtv/vtv_malloc.cc +++ b/libvtv/vtv_malloc.cc @@ -145,7 +145,7 @@ change_protections_on_data_chunks (int protection_flag) } #ifdef VTV_DEBUG - VTV_malloc_dump_stats (); + __vtv_malloc_dump_stats (); #endif } diff --git a/libvtv/vtv_rts.cc b/libvtv/vtv_rts.cc index f5344a0..7bde2f4 100644 --- a/libvtv/vtv_rts.cc +++ b/libvtv/vtv_rts.cc @@ -201,14 +201,15 @@ unsigned long long verify_vtable_cycles = 0; debugging/tracing will not be ON on production environments */ 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 static const int debug_functions = 1; static const int debug_init = 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 /* Global file descriptor variables for logging, tracing and debugging. */ |