+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
+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
#include "function.h"
#include "cgraph.h"
#include "attribs.h"
+#include "vtable-verify.h"
/* Debugging support. */
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;
/* 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 *
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)
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)
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;
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
{
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))
{
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
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
/* 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);
+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.
-## 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)"
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:
}
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
}
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"
}
# 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"
}
#
}
#ifdef VTV_DEBUG
- VTV_malloc_dump_stats ();
+ __vtv_malloc_dump_stats ();
#endif
}
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. */