Index: configure
===================================================================
--- configure	(revision 196516)
+++ configure	(working copy)
@@ -13741,7 +13741,7 @@ else
   esac
   if test $ok = yes; then
     # An in-tree tool is available and we can use it
-    CXX_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/xg++ -B$$r/$(HOST_SUBDIR)/gcc/ -nostdinc++ `if test -f $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags; then $(SHELL) $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags --build-includes; else echo -funconfigured-libstdc++-v3 ; fi` -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs'
+    CXX_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/xg++ -B$$r/$(HOST_SUBDIR)/gcc/ -nostdinc++ `if test -f $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags; then $(SHELL) $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags --build-includes; else echo -funconfigured-libstdc++-v3 ; fi` -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/libsupc++/.libs'
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
 $as_echo "just compiled" >&6; }
   elif expr "x$CXX_FOR_TARGET" : "x/" > /dev/null; then
@@ -13786,7 +13786,7 @@ else
   esac
   if test $ok = yes; then
     # An in-tree tool is available and we can use it
-    RAW_CXX_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/xgcc -shared-libgcc -B$$r/$(HOST_SUBDIR)/gcc -nostdinc++ -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs'
+    RAW_CXX_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/xgcc -shared-libgcc -B$$r/$(HOST_SUBDIR)/gcc -nostdinc++ -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/libsupc++/.libs'
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
 $as_echo "just compiled" >&6; }
   elif expr "x$RAW_CXX_FOR_TARGET" : "x/" > /dev/null; then
Index: libstdc++-v3/configure
===================================================================
--- libstdc++-v3/configure	(revision 196516)
+++ libstdc++-v3/configure	(working copy)
@@ -664,6 +664,8 @@ LIBICONV
 OPT_LDFLAGS
 SECTION_LDFLAGS
 GLIBCXX_LIBS
+ENABLE_VTABLE_VERIFY_FALSE
+ENABLE_VTABLE_VERIFY_TRUE
 ENABLE_WERROR_FALSE
 ENABLE_WERROR_TRUE
 ENABLE_PYTHONDIR_FALSE
@@ -866,6 +868,7 @@ enable_fully_dynamic_string
 enable_extern_template
 with_python_dir
 enable_werror
+enable_vtable_verify
 enable_libstdcxx_time
 enable_tls
 enable_rpath
@@ -1558,6 +1561,7 @@ Optional Features:
   --enable-extern-template
                           enable extern template [default=yes]
   --enable-werror         turns on -Werror [default=yes]
+  --enable-vtable-verify  enable vtable verify [default=no]
   --enable-libstdcxx-time[=KIND]
                           use KIND for check type [default=no]
   --enable-tls            Use thread-local storage [default=yes]
@@ -3530,11 +3534,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}ma
 
 # We need awk for the "check" target.  The system "awk" is bad on
 # some platforms.
-# Always define AMTAR for backward compatibility.  Yes, it's still used
-# in the wild :-(  We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
+# Always define AMTAR for backward compatibility.
 
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
 
 
 
@@ -11513,7 +11517,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11516 "configure"
+#line 11520 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11619,7 +11623,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11622 "configure"
+#line 11626 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14906,6 +14910,12 @@ esac
 
 
 
+if test "$enable_vtable_verify" = yes; then
+  predep_objects_CXX="${predep_objects_CXX} ${glibcxx_builddir}/../libgcc/vtv_start.o"
+  postdep_objects_CXX="${postdep_objects_CXX} ${glibcxx_builddir}/../libgcc/vtv_end.o"
+fi
+
+
 # libtool variables for C++ shared and position-independent compiles.
 #
 # Use glibcxx_lt_pic_flag to designate the automake variable
@@ -15033,7 +15043,7 @@ fi
     #
     # Fake what AC_TRY_COMPILE does.  XXX Look at redoing this new-style.
     cat > conftest.$ac_ext << EOF
-#line 15036 "configure"
+#line 15046 "configure"
 struct S { ~S(); };
 void bar();
 void foo()
@@ -15383,7 +15393,7 @@ $as_echo "$glibcxx_cv_atomic_long_long"
   # Fake what AC_TRY_COMPILE does.
 
     cat > conftest.$ac_ext << EOF
-#line 15386 "configure"
+#line 15396 "configure"
 int main()
 {
   typedef bool atomic_type;
@@ -15418,7 +15428,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6;
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15421 "configure"
+#line 15431 "configure"
 int main()
 {
   typedef short atomic_type;
@@ -15453,7 +15463,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6;
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15456 "configure"
+#line 15466 "configure"
 int main()
 {
   // NB: _Atomic_word not necessarily int.
@@ -15489,7 +15499,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15492 "configure"
+#line 15502 "configure"
 int main()
 {
   typedef long long atomic_type;
@@ -15568,7 +15578,7 @@ $as_echo "$as_me: WARNING: Performance o
   # unnecessary for this test.
 
     cat > conftest.$ac_ext << EOF
-#line 15571 "configure"
+#line 15581 "configure"
 int main()
 {
   _Decimal32 d1;
@@ -15610,7 +15620,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
   # unnecessary for this test.
 
     cat > conftest.$ac_ext << EOF
-#line 15613 "configure"
+#line 15623 "configure"
 template<typename T1, typename T2>
   struct same
   { typedef T2 type; };
@@ -15644,7 +15654,7 @@ $as_echo "$enable_int128" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15647 "configure"
+#line 15657 "configure"
 template<typename T1, typename T2>
   struct same
   { typedef T2 type; };
@@ -17379,6 +17389,29 @@ $as_echo "$enable_werror" >&6; }
 
 
 
+
+   # Check whether --enable-vtable-verify was given.
+if test "${enable_vtable_verify+set}" = set; then :
+  enableval=$enable_vtable_verify;
+      case "$enableval" in
+       yes|no) ;;
+       *) as_fn_error "Argument to enable/disable vtable-verify must be yes or no" "$LINENO" 5 ;;
+      esac
+
+else
+  enable_vtable_verify=no
+fi
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vtable verify support" >&5
+$as_echo_n "checking for vtable verify support... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_vtable_verify" >&5
+$as_echo "$enable_vtable_verify" >&6; }
+
+
+
+
 # Checks for operating systems support that doesn't require linking.
 
 
@@ -72803,6 +72836,15 @@ else
 fi
 
 
+    if test $enable_vtable_verify = yes; then
+  ENABLE_VTABLE_VERIFY_TRUE=
+  ENABLE_VTABLE_VERIFY_FALSE='#'
+else
+  ENABLE_VTABLE_VERIFY_TRUE='#'
+  ENABLE_VTABLE_VERIFY_FALSE=
+fi
+
+
     if test $enable_symvers != no; then
   ENABLE_SYMVERS_TRUE=
   ENABLE_SYMVERS_FALSE='#'
@@ -73246,6 +73288,10 @@ if test -z "${ENABLE_WERROR_TRUE}" && te
   as_fn_error "conditional \"ENABLE_WERROR\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${ENABLE_VTABLE_VERIFY_TRUE}" && test -z "${ENABLE_VTABLE_VERIFY_FALSE}"; then
+  as_fn_error "conditional \"ENABLE_VTABLE_VERIFY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${ENABLE_SYMVERS_TRUE}" && test -z "${ENABLE_SYMVERS_FALSE}"; then
   as_fn_error "conditional \"ENABLE_SYMVERS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
Index: libstdc++-v3/src/Makefile.in
===================================================================
--- libstdc++-v3/src/Makefile.in	(revision 196516)
+++ libstdc++-v3/src/Makefile.in	(working copy)
@@ -366,9 +366,22 @@ libstdc___la_DEPENDENCIES = \
 	$(top_builddir)/src/c++98/libc++98convenience.la \
 	$(top_builddir)/src/c++11/libc++11convenience.la
 
-libstdc___la_LDFLAGS = \
-	-version-info $(libtool_VERSION) ${version_arg} -lm
+@ENABLE_VTABLE_VERIFY_FALSE@libstdc___la_LDFLAGS = \
+@ENABLE_VTABLE_VERIFY_FALSE@	-version-info $(libtool_VERSION) ${version_arg} -lm
 
+@ENABLE_VTABLE_VERIFY_TRUE@libstdc___la_LDFLAGS = \
+@ENABLE_VTABLE_VERIFY_TRUE@	-version-info $(libtool_VERSION) ${version_arg} -lm -Wl,-u_vtable_map_vars_start,-u_vtable_map_vars_end
+
+@ENABLE_VTABLE_VERIFY_FALSE@libvtv___la_LIBADD = 
+@ENABLE_VTABLE_VERIFY_TRUE@libvtv___la_LIBADD = \
+@ENABLE_VTABLE_VERIFY_TRUE@	$(top_builddir)/libsupc++/.libs
+
+@ENABLE_VTABLE_VERIFY_FALSE@LIBVTV_FLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@LIBVTV_FLAGS = \
+@ENABLE_VTABLE_VERIFY_TRUE@	-L$(libvtv___la_LIBADD) --whole-archive -lvtv_init --no-whole-archive
+
+@ENABLE_VTABLE_VERIFY_FALSE@VTV_CXXFLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@VTV_CXXFLAGS = -fvtable-verify=std
 libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS)
 
 # A note on compatibility and static libraries.
@@ -400,7 +413,7 @@ libstdc___la_LINK = $(CXXLINK) $(libstdc
 # as the occasion calls for it.
 AM_CXXFLAGS = \
 	$(glibcxx_compiler_pic_flag) \
-	$(XTEMPLATE_FLAGS) \
+	$(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \
 	$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
 
 
@@ -448,6 +461,7 @@ CXXLINK = \
 	$(LIBTOOL) --tag CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=link $(CXX) \
+	$(LIBVTV_FLAGS) \
 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
 
 @ENABLE_SYMVERS_TRUE@CLEANFILES = libstdc++-symbols.ver $(version_dep)
Index: libstdc++-v3/src/c++98/Makefile.am
===================================================================
--- libstdc++-v3/src/c++98/Makefile.am	(revision 196516)
+++ libstdc++-v3/src/c++98/Makefile.am	(working copy)
@@ -142,6 +142,18 @@ vpath % $(top_srcdir)/src/c++98
 
 libc__98convenience_la_SOURCES = $(sources)
 
+if ENABLE_VTABLE_VERIFY
+EXTRA_VTV_LDFLAGS = \
+        -Wl,-u_vtable_map_vars_start,-u_vtable_map_vars_end
+LIBVTV_FLAGS = \
+        -L$(top_builddir)/libsupc++/.libs --whole-archive -lvtv_init --no-whole-archive
+VTV_CXXFLAGS = -fvtable-verify=std $(EXTRA_VTV_LDFLAGS)
+else
+EXTRA_VTV_LDFLAGS =
+LIBVTV_FLAGS =
+VTV_CXXFLAGS =
+endif
+
 # Use special rules for the deprecated source files so that they find
 # deprecated include files.
 GLIBCXX_INCLUDE_DIR=$(glibcxx_builddir)/include
@@ -172,7 +184,7 @@ parallel_settings.o: parallel_settings.c
 # as the occasion calls for it.
 AM_CXXFLAGS = \
 	$(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
-	$(XTEMPLATE_FLAGS) \
+	$(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \
 	$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
 
 AM_MAKEFLAGS = \
@@ -222,4 +234,5 @@ CXXLINK = \
 	$(LIBTOOL) --tag CXX --tag disable-shared \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=link $(CXX) \
+	$(LIBVTV_FLAGS) \
 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
Index: libstdc++-v3/src/c++98/Makefile.in
===================================================================
--- libstdc++-v3/src/c++98/Makefile.in	(revision 196516)
+++ libstdc++-v3/src/c++98/Makefile.in	(working copy)
@@ -397,6 +397,16 @@ sources = \
 	${host_sources_extra}
 
 libc__98convenience_la_SOURCES = $(sources)
+@ENABLE_VTABLE_VERIFY_FALSE@EXTRA_VTV_LDFLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@EXTRA_VTV_LDFLAGS = \
+@ENABLE_VTABLE_VERIFY_TRUE@        -Wl,-u_vtable_map_vars_start,-u_vtable_map_vars_end
+
+@ENABLE_VTABLE_VERIFY_FALSE@LIBVTV_FLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@LIBVTV_FLAGS = \
+@ENABLE_VTABLE_VERIFY_TRUE@        -L$(top_builddir)/libsupc++/.libs --whole-archive -lvtv_init --no-whole-archive
+
+@ENABLE_VTABLE_VERIFY_FALSE@VTV_CXXFLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@VTV_CXXFLAGS = -fvtable-verify=std $(EXTRA_VTV_LDFLAGS)
 
 # Use special rules for the deprecated source files so that they find
 # deprecated include files.
@@ -412,7 +422,7 @@ PARALLEL_FLAGS = -D_GLIBCXX_PARALLEL
 # as the occasion calls for it.
 AM_CXXFLAGS = \
 	$(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
-	$(XTEMPLATE_FLAGS) \
+	$(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \
 	$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
 
 AM_MAKEFLAGS = \
@@ -463,6 +473,7 @@ CXXLINK = \
 	$(LIBTOOL) --tag CXX --tag disable-shared \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=link $(CXX) \
+	$(LIBVTV_FLAGS) \
 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
 
 all: all-am
Index: libstdc++-v3/src/Makefile.am
===================================================================
--- libstdc++-v3/src/Makefile.am	(revision 196516)
+++ libstdc++-v3/src/Makefile.am	(working copy)
@@ -66,12 +66,25 @@ libstdc___la_DEPENDENCIES = \
 	$(top_builddir)/src/c++98/libc++98convenience.la \
 	$(top_builddir)/src/c++11/libc++11convenience.la
 
+if ENABLE_VTABLE_VERIFY
+libstdc___la_LDFLAGS = \
+	-version-info $(libtool_VERSION) ${version_arg} -lm -Wl,-u_vtable_map_vars_start,-u_vtable_map_vars_end
+
+libvtv___la_LIBADD = \
+	$(top_builddir)/libsupc++/.libs
+LIBVTV_FLAGS = \
+	-L$(libvtv___la_LIBADD) --whole-archive -lvtv_init --no-whole-archive
+VTV_CXXFLAGS = -fvtable-verify=std
+else
 libstdc___la_LDFLAGS = \
 	-version-info $(libtool_VERSION) ${version_arg} -lm
+libvtv___la_LIBADD = 
+LIBVTV_FLAGS =
+VTV_CXXFLAGS =
+endif
 
 libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS)
 
-
 # Use special rules for compatibility-ldbl.cc compilation, as we need to
 # pass -mlong-double-64.
 if GLIBCXX_LDBL_COMPAT
@@ -126,7 +139,7 @@ compatibility-thread-c++0x.o: compatibil
 # as the occasion calls for it.
 AM_CXXFLAGS = \
 	$(glibcxx_compiler_pic_flag) \
-	$(XTEMPLATE_FLAGS) \
+	$(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \
 	$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
 
 # Libtool notes
@@ -173,6 +186,7 @@ CXXLINK = \
 	$(LIBTOOL) --tag CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=link $(CXX) \
+	$(LIBVTV_FLAGS) \
 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
 
 
Index: libstdc++-v3/src/c++11/Makefile.am
===================================================================
--- libstdc++-v3/src/c++11/Makefile.am	(revision 196516)
+++ libstdc++-v3/src/c++11/Makefile.am	(working copy)
@@ -60,6 +60,18 @@ vpath % $(top_srcdir)/src/c++11
 
 libc__11convenience_la_SOURCES = $(sources)  $(inst_sources)
 
+if ENABLE_VTABLE_VERIFY
+EXTRA_VTV_LDFLAGS = \
+        -Wl,-u_vtable_map_vars_start,-u_vtable_map_vars_end
+LIBVTV_FLAGS = \
+        -L$(top_builddir)/libsupc++/.libs --whole-archive -lvtv_init --no-whole-archive
+VTV_CXXFLAGS = -fvtable-verify=std $(EXTRA_VTV_LDFLAGS)
+else
+EXTRA_VTV_LDFLAGS =
+LIBVTV_FLAGS =
+VTV_CXXFLAGS =
+endif
+
 # Use special rules for the hashtable.cc file so that all
 # the generated template functions are also instantiated. 
 hashtable_c++0x.lo: hashtable_c++0x.cc
@@ -75,7 +87,7 @@ hashtable_c++0x.o: hashtable_c++0x.cc
 AM_CXXFLAGS = \
 	-std=gnu++11 \
 	$(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
-	$(XTEMPLATE_FLAGS) \
+	$(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \
 	$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
 
 AM_MAKEFLAGS = \
@@ -125,4 +137,5 @@ CXXLINK = \
 	$(LIBTOOL) --tag CXX --tag disable-shared \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=link $(CXX) \
+	$(LIBVTV_FLAGS) \
 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
Index: libstdc++-v3/src/c++11/Makefile.in
===================================================================
--- libstdc++-v3/src/c++11/Makefile.in	(revision 196516)
+++ libstdc++-v3/src/c++11/Makefile.in	(working copy)
@@ -331,6 +331,16 @@ sources = \
 @ENABLE_EXTERN_TEMPLATE_TRUE@	wstring-inst.cc
 
 libc__11convenience_la_SOURCES = $(sources)  $(inst_sources)
+@ENABLE_VTABLE_VERIFY_FALSE@EXTRA_VTV_LDFLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@EXTRA_VTV_LDFLAGS = \
+@ENABLE_VTABLE_VERIFY_TRUE@        -Wl,-u_vtable_map_vars_start,-u_vtable_map_vars_end
+
+@ENABLE_VTABLE_VERIFY_FALSE@LIBVTV_FLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@LIBVTV_FLAGS = \
+@ENABLE_VTABLE_VERIFY_TRUE@        -L$(top_builddir)/libsupc++/.libs --whole-archive -lvtv_init --no-whole-archive
+
+@ENABLE_VTABLE_VERIFY_FALSE@VTV_CXXFLAGS = 
+@ENABLE_VTABLE_VERIFY_TRUE@VTV_CXXFLAGS = -fvtable-verify=std $(EXTRA_VTV_LDFLAGS)
 
 # AM_CXXFLAGS needs to be in each subdirectory so that it can be
 # modified in a per-library or per-sub-library way.  Need to manually
@@ -340,7 +350,7 @@ libc__11convenience_la_SOURCES = $(sourc
 AM_CXXFLAGS = \
 	-std=gnu++11 \
 	$(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
-	$(XTEMPLATE_FLAGS) \
+	$(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \
 	$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
 
 AM_MAKEFLAGS = \
@@ -391,6 +401,7 @@ CXXLINK = \
 	$(LIBTOOL) --tag CXX --tag disable-shared \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=link $(CXX) \
+	$(LIBVTV_FLAGS) \
 	$(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@
 
 all: all-am
Index: libstdc++-v3/configure.ac
===================================================================
--- libstdc++-v3/configure.ac	(revision 196516)
+++ libstdc++-v3/configure.ac	(working copy)
@@ -97,6 +97,12 @@ ACX_LT_HOST_FLAGS
 AC_SUBST(enable_shared)
 AC_SUBST(enable_static)
 
+if test "$enable_vtable_verify" = yes; then
+  predep_objects_CXX="${predep_objects_CXX} ${glibcxx_builddir}/../libgcc/vtv_start.o"
+  postdep_objects_CXX="${postdep_objects_CXX} ${glibcxx_builddir}/../libgcc/vtv_end.o"
+fi
+
+
 # libtool variables for C++ shared and position-independent compiles.
 #
 # Use glibcxx_lt_pic_flag to designate the automake variable
@@ -168,6 +174,7 @@ GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING([no]
 GLIBCXX_ENABLE_EXTERN_TEMPLATE([yes])
 GLIBCXX_ENABLE_PYTHON
 GLIBCXX_ENABLE_WERROR([yes])
+GLIBCXX_ENABLE_VTABLE_VERIFY([no])
 
 # Checks for operating systems support that doesn't require linking.
 GLIBCXX_CHECK_STDIO_PROTO
Index: libstdc++-v3/libsupc++/vtv_set.h
===================================================================
--- libstdc++-v3/libsupc++/vtv_set.h	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_set.h	(revision 0)
@@ -0,0 +1,653 @@
+/* Copyright (C) 2012-2013
+   Free Software Foundation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License
+   and a copy of the GCC Runtime Library Exception along with this
+   program; see the files COPYING3 and COPYING.RUNTIME respectively.
+   If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _VTV_SET_H
+#define _VTV_SET_H 1
+
+/* Code in this file manages a collection of insert-only sets.  We
+   have only tested the case where Key is uintptr_t, though it
+   theoretically should work for some other cases.  All odd keys are
+   reserved, and must not be inserted into any of the sets.  This code
+   is intended primarily for sets of pointers, and the code is
+   optimized for small sets (including size 0 and 1), but regardless
+   of the set size, insert() and contains() have close to O(1) speed
+   in practice.
+
+   TODO(gpike): fix this comment.
+
+   Recommended multithreaded use of a set:
+
+   For speed, we want to use a lock-free test for set membership.  The
+   code handles simultaneous reads and inserts, as long as at most one
+   insertion is in progress at a time.  After an insert, other threads
+   may not immediately "see" the inserted key if they perform a
+   lock-free read, so we recommend retrying, as explained below.
+
+   Also, to make data corruption less likely, we recommend using a
+   "normal" RW page as well as one or pages that are typically RO
+   but that can be switched to RW and back as needed.  The latter
+   pages should contain sets.  The former should contain a lock, L,
+   and an int or similar, num_writers.  Then, to insert, something
+   like this would be safe:
+    o Acquire L.
+    o Increment num_writers; if that made it 1, change pages to RW.
+    o Release L.
+    o while (there are insertions to do in some set, S) {
+        acquire L;
+        do some insertions in S;
+        release L;
+      }
+    o Acquire L.
+    o Decrement num_writers; if that made it 0, change pages to RO.
+    o Release L.
+
+   And to check if the set contains some key, one could use
+     set.contains(key) ||
+       ({ Acquire L; bool b = set.contains(key); Release L; b; })
+
+   In this scheme, the number of threads with reads in progress isn't
+   tracked, so old sets can never be deleted.  In addition, on some
+   architectures the intentionally racy reads might cause contains()
+   to return true when it should have returned false.  This should be
+   no problem on x86, and most other machines, where reading or
+   writing an aligned uintptr_t is atomic.  E.g., on those machines,
+   if *p is 0 and one thread does *p = x while another reads *p, the
+   read will see either 0 or x.
+
+   To make the above easier, the insert_only_hash_sets class provides
+   an interface to manipulate any number of hash sets.  One shouldn't
+   create objects of that class, as it has no member data and its
+   methods are static.
+
+   So the recommended model is to have a single lock, a single
+   num_writers variable, and some number of sets.  If lock contention
+   becomes a problem then the sets can be divided into k groups, each
+   of which has a lock and a num_writers variable; or each set can be
+   represented as a set of values that equal 0 mod m, a set of values
+   that equal 1 mod m, ..., plus a set of values that equal m-1 mod m.
+
+   However, we expect most or all uses of this code to call contains()
+   much more frequently than anything else, so lock contention is
+   likely to be low.  */
+
+#include <algorithm>
+
+#ifndef HASHTABLE_STATS
+#define HASHTABLE_STATS 0
+#endif
+
+#ifndef HASHTABLE_STATS_ATOMIC
+#define HASHTABLE_STATS_ATOMIC 0
+#endif
+
+#if HASHTABLE_STATS
+#if HASHTABLE_STATS_ATOMIC
+/* Stat counters, with atomics. */
+#include <bits/atomic_word.h>
+
+typedef _Atomic_word _AtomicStatCounter;
+
+void
+inc_by (_AtomicStatCounter &stat, int amount)
+{ 
+  __atomic_add_fetch (&stat, amount,  __ATOMIC_ACQ_REL);
+}
+
+#else
+
+/* Stat counters, but without atomics. */
+typedef int _AtomicStatCounter;
+
+void
+inc_by (_AtomicStatCounter& stat, int amount)
+{ 
+  stat += amount;
+}
+
+#endif
+
+
+/* Number of calls to contains(), insert(), etc. */
+extern _AtomicStatCounter stat_insert;
+extern _AtomicStatCounter stat_contains;
+extern _AtomicStatCounter stat_resize;
+extern _AtomicStatCounter stat_create;
+
+/* Sum of set size over all calls to contains().  */
+extern _AtomicStatCounter stat_contains_sizes;
+
+/* contains() calls in a set whose capacity is more than 1. */
+extern _AtomicStatCounter stat_contains_in_non_trivial_set;
+
+/* Probes in a set whose capacity is more than 1.  Ideally, this will
+   be pretty close to stat_contains_in_non_trivial_set.  That will
+   happen if our hash function is good and/or important keys were
+   inserted before unimportant keys.  */
+extern _AtomicStatCounter stat_probes_in_non_trivial_set;
+
+/* number of calls to contains() with size=0, 1, etc. */
+extern _AtomicStatCounter stat_contains_size0;
+extern _AtomicStatCounter stat_contains_size1;
+extern _AtomicStatCounter stat_contains_size2;
+extern _AtomicStatCounter stat_contains_size3;
+extern _AtomicStatCounter stat_contains_size4;
+extern _AtomicStatCounter stat_contains_size5;
+extern _AtomicStatCounter stat_contains_size6;
+extern _AtomicStatCounter stat_contains_size7;
+extern _AtomicStatCounter stat_contains_size8;
+extern _AtomicStatCounter stat_contains_size9;
+extern _AtomicStatCounter stat_contains_size10;
+extern _AtomicStatCounter stat_contains_size11;
+extern _AtomicStatCounter stat_contains_size12;
+extern _AtomicStatCounter stat_contains_size13_or_more;
+extern _AtomicStatCounter stat_grow_from_size0_to_1;
+extern _AtomicStatCounter stat_grow_from_size1_to_2;
+extern _AtomicStatCounter stat_double_the_number_of_buckets;
+extern _AtomicStatCounter stat_insert_key_that_was_already_present;
+
+/* Hash collisions detected during insert_no_resize().  Only counts
+   hasher(k) == hasher(k'); hasher(k) % tablesize == hasher(k') %
+   tablesize is not sufficient.  Will count collisions that are
+   detected during table resizes etc., so the same two keys may add to
+   this stat multiple times.  */
+extern _AtomicStatCounter stat_insert_found_hash_collision;
+
+#include <string>
+
+struct insert_only_hash_sets_logger
+{
+  static char *
+  log (char c, char *buf)
+  {
+    *buf++ = c;
+    return buf;
+  }
+
+  static char *
+  log (const char *s, char *buf)
+  { return strcpy (buf, s) + strlen (s); }
+
+  static char *
+  log (_AtomicStatCounter i, char *buf)
+  {
+    if (i < 10)
+      return log ((char) ('0' + i), buf);
+    else
+      return log ((char) ('0' + i % 10), log (i / 10, buf));
+  }
+
+  static char *
+  log (const char *label, _AtomicStatCounter i, char *buf)
+  {
+    buf = log (label, buf);
+    buf = log (": ", buf);
+    buf = log (i, buf);
+    return log ('\n', buf);
+  }
+};
+
+// Write stats to the given buffer, which should be at least 4000 bytes.
+static inline void
+insert_only_hash_tables_stats (char *buf)
+{
+  buf = insert_only_hash_sets_logger::log ("insert", stat_insert, buf);
+  buf = insert_only_hash_sets_logger::log ("contains", stat_contains, buf);
+  buf = insert_only_hash_sets_logger::log ("resize", stat_resize, buf);
+  buf = insert_only_hash_sets_logger::log ("create", stat_create, buf);
+  buf = insert_only_hash_sets_logger::log ("insert_key_that_was_already_"
+				      "present",
+				      stat_insert_key_that_was_already_present,
+				      buf);
+  buf = insert_only_hash_sets_logger::log ("contains_sizes",
+					   stat_contains_sizes, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_in_non_trivial_set",
+					   stat_contains_in_non_trivial_set,
+					   buf);
+  buf = insert_only_hash_sets_logger::log ("probes_in_non_trivial_set",
+					   stat_probes_in_non_trivial_set,
+					   buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size0",
+					   stat_contains_size0, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size1",
+					   stat_contains_size1, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size2",
+					   stat_contains_size2, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size3",
+					   stat_contains_size3, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size4",
+					   stat_contains_size4, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size5",
+					   stat_contains_size5, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size6",
+					   stat_contains_size6, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size7",
+					   stat_contains_size7, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size8",
+					   stat_contains_size8, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size9",
+					   stat_contains_size9, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size10",
+					   stat_contains_size10, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size11",
+					   stat_contains_size11, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size12",
+					   stat_contains_size12, buf);
+  buf = insert_only_hash_sets_logger::log ("contains_size13_or_more",
+					   stat_contains_size13_or_more, buf);
+  buf = insert_only_hash_sets_logger::log ("grow_from_size0_to_1",
+					   stat_grow_from_size0_to_1, buf);
+  buf = insert_only_hash_sets_logger::log ("grow_from_size1_to_2",
+					   stat_grow_from_size1_to_2, buf);
+  buf = insert_only_hash_sets_logger::log ("insert_found_hash_collision",
+					   stat_insert_found_hash_collision,
+					   buf);
+  buf = insert_only_hash_sets_logger::log ("double_the_number_of_buckets",
+					   stat_double_the_number_of_buckets,
+					   buf);
+  *buf = '\0';
+}
+
+#else
+
+/* No stats. */
+#define inc_by(statname, amount) do { } while (false && (amount))
+
+#endif
+
+#define inc(statname) inc_by (statname, 1)
+
+template <typename Key, class HashFcn, class Alloc>
+class insert_only_hash_sets
+{
+ public:
+  typedef Key key_type;
+  typedef size_t size_type;
+  typedef Alloc alloc_type;
+  enum { illegal_key = 1 };
+  enum { min_capacity = 4 };
+#if HASHTABLE_STATS
+  enum { stats = true };
+#else
+  enum { stats = false };
+#endif
+
+  /* Do not directly use insert_only_hash_set.  Instead, use the
+     static methods below to create and manipulate objects of the
+     following class.
+  
+     Implementation details: each set is represented by a pointer
+     plus, perhaps, out-of-line data, which would be an object of type
+     insert_only_hash_set.  For a pointer, s, the interpretation is: s
+     == NULL means empty set, lsb(s) == 1 means a set with one
+     element, which is (uintptr_t)s - 1, and otherwise s is a pointer
+     of type insert_only_hash_set*.  So, to increase the size of a set
+     we have to change s and/or *s.  To check if a set contains some
+     key we have to examine s and possibly *s.  */
+  class insert_only_hash_set
+  {
+   public:
+    /* Insert a key.  The key must not be a reserved key.  */
+    static inline insert_only_hash_set *insert (key_type key,
+						insert_only_hash_set *s);
+    
+
+    /* Create an empty set.  */
+    static inline insert_only_hash_set *create (size_type capacity);
+
+    /* Return whether the given key is present.  If key is illegal_key
+       then either true or false may be returned, but for all other
+       reserved keys false will be returned.  */
+    static bool
+    contains (key_type key, const insert_only_hash_set *s)
+    {
+      if (stats)
+	{
+	  inc (stat_contains);
+	  switch (size (s))
+	    {
+	      case 0: inc (stat_contains_size0); break;
+	      case 1: inc (stat_contains_size1); break;
+	      case 2: inc (stat_contains_size2); break;
+	      case 3: inc (stat_contains_size3); break;
+	      case 4: inc (stat_contains_size4); break;
+	      case 5: inc (stat_contains_size5); break;
+	      case 6: inc (stat_contains_size6); break;
+	      case 7: inc (stat_contains_size7); break;
+	      case 8: inc (stat_contains_size8); break;
+	      case 9: inc (stat_contains_size9); break;
+	      case 10: inc (stat_contains_size10); break;
+	      case 11: inc (stat_contains_size11); break;
+	      case 12: inc (stat_contains_size12); break;
+	      default: inc (stat_contains_size13_or_more); break;
+	    }
+          inc_by (stat_contains_sizes, size (s));
+	}
+
+      return (singleton (s) ?
+              singleton_key (key) == s :
+              ((s != NULL) && s->contains (key)));
+    }
+
+    /* Return a set's size.  */
+    static size_type
+    size (const insert_only_hash_set *s)
+    { return (s == NULL) ? 0 : (singleton (s) ? 1 : s->num_entries); }
+
+    static inline insert_only_hash_set *resize (size_type target_num_buckets,
+						insert_only_hash_set *s);
+    
+
+   private:
+    /* Return whether a set has size 1. */
+    static bool
+    singleton (const insert_only_hash_set *s)
+    { return (uintptr_t) s & 1; }
+
+    /* Return the representation of a singleton set containing the
+       given key.  */
+    static insert_only_hash_set *
+    singleton_key (key_type key)
+    { return (insert_only_hash_set *) ((uintptr_t) key + 1); }
+
+    /* Given a singleton set, what key does it contain?  */
+    static key_type
+    extract_singleton_key (const insert_only_hash_set *s)
+    {
+      VTV_DEBUG_ASSERT (singleton (s));
+      return (key_type) ((uintptr_t) s - 1);
+    }
+
+    volatile key_type &
+    key_at_index (size_type index)
+    { return buckets[index]; }
+
+    key_type
+    key_at_index (size_type index) const
+    { return buckets[index]; }
+
+    size_type
+    next_index (size_type index, size_type indices_examined) const
+    { return (index + indices_examined) & (num_buckets - 1); }
+
+    inline void insert_no_resize (key_type key);
+    
+    inline bool contains (key_type key) const;
+    
+    inline insert_only_hash_set *resize_if_necessary (void);
+    
+    size_type num_buckets;  /* Must be a power of 2 not less than
+			       min_capacity.  */
+    volatile size_type num_entries;
+    volatile key_type buckets[0];  /* Actual array size is num_buckets.  */
+  };
+
+  /* Create an empty set with the given capacity.  Requires that n be
+     0 or a power of 2.  If 1 < n < min_capacity then treat n as
+     min_capacity.  Sets *handle.  Returns true unless the allocator
+     fails.  Subsequent operations on this set should use the same
+     handle. */
+
+  static inline bool create (size_type n, insert_only_hash_set **handle);
+
+  /* Force the capacity of a set to be n, unless it was more than n
+     already.  Requires that n be 0 or a power of 2.  Sets *handle
+     unless the current capacity is n or more.  Returns true unless
+     the allocator fails.  */
+
+  static inline bool resize (size_type n, insert_only_hash_set **handle);
+
+  /* Insert a key.  *handle is unmodified unless (1) a resize occurs,
+     or (2) the set was initially empty. Returns true unless the
+     allocator fails during a resize.  If the allocator fails during a
+     resize then the set is reset to be the empty set.  The key must
+     not be a reserved key.  */
+
+  static inline bool insert (key_type key, insert_only_hash_set **handle);
+
+  /* Check for the presence of a key.  If key is illegal_key then
+     either true or false may be returned, but for all other reserved
+     keys false will be returned.  */
+
+  static inline bool
+  contains (key_type key, /* const */ insert_only_hash_set **handle)
+  { return insert_only_hash_set::contains (key, *handle); }
+
+  /* Return the size of the given set.  */
+  static size_type
+  size (const insert_only_hash_set **handle)
+  { return insert_only_hash_set::size (*handle); }
+
+  static bool
+  is_reserved_key (key_type key)
+  { return ((uintptr_t) key % 2) == 1; }
+};
+
+template <typename Key, class HashFcn, class Alloc>
+typename insert_only_hash_sets <Key, HashFcn, Alloc>::insert_only_hash_set *
+insert_only_hash_sets <Key, HashFcn, Alloc>::insert_only_hash_set::resize
+                                         (size_type n, insert_only_hash_set *s)
+{
+  if (s == NULL)
+    return create (n);
+
+  size_type capacity = singleton (s) ? 1 : s->num_buckets;
+
+  if (n <= capacity)
+    return s;
+
+  insert_only_hash_set *result =
+                                create (std::max<size_type> (n, min_capacity));
+  if (result != NULL)
+    {
+      if (singleton (s))
+        {
+          result->insert_no_resize (extract_singleton_key (s));
+        }
+      else
+        {
+          for (size_type i = 0; i < s->num_buckets; i++)
+            if (s->buckets[i] != (key_type) illegal_key)
+              result->insert_no_resize (s->buckets[i]);
+        }
+      VTV_DEBUG_ASSERT (size (result) == size (s));
+    }
+  return result;
+}
+
+template <typename Key, class HashFcn, class Alloc>
+typename insert_only_hash_sets <Key, HashFcn, Alloc>::insert_only_hash_set *
+insert_only_hash_sets <Key, HashFcn, Alloc>::insert_only_hash_set::insert 
+                                        (key_type key, insert_only_hash_set *s)
+{
+  VTV_DEBUG_ASSERT (!is_reserved_key (key));
+
+  inc_by (stat_grow_from_size0_to_1, s == NULL);
+
+  if (s == NULL)
+    return singleton_key (key);
+
+  if (singleton (s))
+    {
+      const key_type old_key = extract_singleton_key (s);
+      if (old_key == key)
+	return s;
+
+      /* Grow from size 1 to size 2.  */
+      inc (stat_grow_from_size1_to_2);
+      s = create (2);
+      if (s == NULL)
+	return NULL;
+
+      s->insert_no_resize (old_key);
+      s->insert_no_resize (key);
+      VTV_DEBUG_ASSERT (size (s) == 2);
+      return s;
+    }
+  s = s->resize_if_necessary();
+  if (s != NULL)
+    s->insert_no_resize (key);
+  return s;
+}
+
+template <typename Key, class HashFcn, class Alloc>
+typename insert_only_hash_sets <Key, HashFcn, Alloc>::insert_only_hash_set *
+insert_only_hash_sets <Key, HashFcn, Alloc>::insert_only_hash_set::create
+                                                           (size_type capacity)
+{
+  if (capacity <= 1)
+    return NULL;
+
+  VTV_DEBUG_ASSERT (capacity > 1 && (capacity & (capacity - 1)) == 0);
+  VTV_DEBUG_ASSERT (sizeof (insert_only_hash_set) == 2 * sizeof (size_type));
+  capacity = std::max <size_type> (capacity, min_capacity);
+  const size_t num_bytes = sizeof (insert_only_hash_set) +
+                                                  sizeof (key_type) * capacity;
+  alloc_type alloc;
+  insert_only_hash_set *result = (insert_only_hash_set *) alloc (num_bytes);
+  result->num_buckets = capacity;
+  result->num_entries = 0;
+  for (size_type i = 0; i < capacity; i++)
+    result->buckets[i] = (key_type) illegal_key;
+  return result;
+}
+
+template <typename Key, class HashFcn, class Alloc>
+void
+insert_only_hash_sets<Key, HashFcn,
+                                 Alloc>::insert_only_hash_set::insert_no_resize
+                                                                 (key_type key)
+{
+  HashFcn hasher;
+  const size_type capacity = num_buckets;
+  VTV_DEBUG_ASSERT (capacity >= min_capacity);
+  VTV_DEBUG_ASSERT (!is_reserved_key (key));
+  size_type index = hasher (key) & (capacity - 1);
+  key_type k = key_at_index (index);
+  size_type indices_examined = 0;
+  while (k != key)
+    {
+      ++indices_examined;
+      if (k == (key_type) illegal_key)
+        {
+          key_at_index (index) = key;
+          ++num_entries;
+          return;
+        }
+      else
+	{
+	  inc_by (stat_insert_found_hash_collision,
+		  hasher (k) == hasher (key));
+	}
+      VTV_DEBUG_ASSERT (indices_examined < capacity);
+      index = next_index (index, indices_examined);
+      k = key_at_index (index);
+    }
+}
+
+template<typename Key, class HashFcn, class Alloc>
+bool
+insert_only_hash_sets<Key, HashFcn, Alloc>::insert_only_hash_set::contains
+                                                           (key_type key) const
+{
+  inc (stat_contains_in_non_trivial_set);
+  HashFcn hasher;
+  const size_type capacity = num_buckets;
+  size_type index = hasher (key) & (capacity - 1);
+  key_type k = key_at_index (index);
+  size_type indices_examined = 0;
+  inc (stat_probes_in_non_trivial_set);
+  while (k != key)
+    {
+      ++indices_examined;
+      if (/*UNLIKELY*/(k == (key_type) illegal_key
+		       || indices_examined == capacity))
+	return false;
+
+      index = next_index (index, indices_examined);
+      k = key_at_index (index);
+      inc (stat_probes_in_non_trivial_set);
+    }
+  return true;
+}
+
+template <typename Key, class HashFcn, class Alloc>
+typename insert_only_hash_sets <Key, HashFcn, Alloc>::insert_only_hash_set *
+   insert_only_hash_sets<Key, HashFcn,
+                       Alloc>::insert_only_hash_set::resize_if_necessary (void)
+{
+  VTV_DEBUG_ASSERT (num_buckets >= min_capacity);
+  size_type unused = num_buckets - num_entries;
+  if (unused < (num_buckets >> 2))
+    {
+      inc (stat_double_the_number_of_buckets);
+      size_type new_num_buckets = num_buckets * 2;
+      insert_only_hash_set *s = create (new_num_buckets);
+      for (size_type i = 0; i < num_buckets; i++)
+        if (buckets[i] != (key_type) illegal_key)
+          s->insert_no_resize (buckets[i]);
+      VTV_DEBUG_ASSERT (size (this) == size (s));
+      return s;
+    }
+  else
+    return this;
+}
+
+template<typename Key, class HashFcn, class Alloc>
+bool
+insert_only_hash_sets<Key, HashFcn, Alloc>::create (size_type n,
+						 insert_only_hash_set **handle)
+  
+{
+  inc (stat_create);
+  *handle = insert_only_hash_set::create (n);
+  return (n <= 1) || (*handle != NULL);
+}
+
+template<typename Key, class HashFcn, class Alloc>
+bool
+insert_only_hash_sets<Key, HashFcn, Alloc>::resize (size_type n,
+					         insert_only_hash_set **handle)
+{
+  inc (stat_resize);
+  *handle = insert_only_hash_set::resize (n, *handle);
+  return (n <= 1) || (*handle != NULL);
+}
+
+template<typename Key, class HashFcn, class Alloc>
+bool
+insert_only_hash_sets<Key, HashFcn, Alloc>::insert (key_type key,
+                                                 insert_only_hash_set **handle)
+{
+  inc (stat_insert);
+  const size_type old_size = insert_only_hash_set::size (*handle);
+  *handle = insert_only_hash_set::insert (key, *handle);
+  if (*handle != NULL)
+    {
+      const size_type delta = insert_only_hash_set::size (*handle) - old_size;
+      inc_by (stat_insert_key_that_was_already_present, delta == 0);
+    }
+  return *handle != NULL;
+}
+
+#endif /* VTV_SET_H  */
Index: libstdc++-v3/libsupc++/vtv_stubs.cc
===================================================================
--- libstdc++-v3/libsupc++/vtv_stubs.cc	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_stubs.cc	(revision 0)
@@ -0,0 +1,91 @@
+/* Copyright (C) 2012-2013
+   Free Software Foundation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional  
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "vtv_rts.h"
+
+/* The is part of the vtable verification runtime library.  For more
+   information about this feature, see the comments in vtv_rts.cc.  */
+
+/* The functions in this file are used to create the libvtv_stubs
+   library, as part of the vtable verification feature.  When building
+   a binary without vtable verification, and linking it with a
+   (possibly pre-built third-party) library that was built with
+   verification, it is possible that vtable verification will fail due
+   to incomplete data (rather than due to corrupt vtable pointers).  In
+   this case we need to give programmers a way of turning off the
+   vtable verification in their libraries.  They can do so by linking
+   with the libvtv_stubs library, which (as you can see) will replace
+   the real verification functions with a set of functions that do
+   nothing (so no more verification failures/aborts).  */
+
+void
+__VLTChangePermission (int perm __attribute__((__unused__)))
+{
+}
+
+void __VLTInitSetSymbolDebug
+                      (void **set_handle_ptr __attribute__((__unused__)),
+		       const void *set_symbol_key __attribute__((__unused__)),
+		       std::size_t size_hint __attribute__((__unused__)))
+{
+}
+
+void
+__VLTRegisterPairDebug (void **set_handle_ptrr __attribute__((__unused__)),
+                      const void *vtable_ptr __attribute__((__unused__)),
+                      const char *set_symbol_name __attribute__((__unused__)),
+		      const char *vtable_name __attribute__((__unused__)))
+{
+}
+
+const void *
+__VLTVerifyVtablePointerDebug
+                     (void **set_handle_ptr  __attribute__((__unused__)),
+	       	      const void *vtable_ptr,
+		      const char *set_symbol_name __attribute__((__unused__)),
+		      const char *vtable_name __attribute__((__unused__)))
+
+{
+  return vtable_ptr;
+}
+
+void __VLTInitSetSymbol
+                      (void **set_handle_ptr __attribute__((__unused__)),
+                       const void *set_symbol_key __attribute__((__unused__)),
+		       std::size_t size_hint __attribute__((__unused__)))
+{
+}
+
+void
+__VLTRegisterPair (void **set_handle_ptr __attribute__((__unused__)),
+                   const void *vtable_ptr __attribute__((__unused__)))
+{
+}
+
+const void *
+__VLTVerifyVtablePointer (void **set_handle_ptr __attribute__((__unused__)),
+                          const void *vtable_ptr)
+{
+  return vtable_ptr;
+}
Index: libstdc++-v3/libsupc++/vtv_utils.cc
===================================================================
--- libstdc++-v3/libsupc++/vtv_utils.cc	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_utils.cc	(revision 0)
@@ -0,0 +1,107 @@
+/* Copyright (C) 2012-2013
+   Free Software Foundation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file is part of the vtable verication runtime library (see
+   comments in vtv_rts.cc for more information about vtable
+   verification).  This file contains log file utilities.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "vtv_utils.h"
+
+/* This is the directory into which all vtable verication log files
+   get written.  */
+static const char * const logs_dir = "/tmp/vtv_logs";
+
+
+/* This function takes the NAME of a log file to open, attempts to
+   open it in the logs_dir directory, and returns the resulting file
+   decriptor.  */
+
+int
+vtv_open_log (const char *name)
+{
+  char log_name[256];
+  snprintf (log_name, sizeof (log_name), "%s/%s", logs_dir, name);
+  mkdir (logs_dir, S_IRWXU);
+  int fd = open (log_name, O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
+  if (fd == -1)
+    vtv_add_to_log (2, "Cannot open log file %s %s\n", name,
+		    strerror (errno));
+  return fd;
+}
+
+/* This function takes a file descriptor (FD) and a string (STR) and
+   tries to write the string to the file.  */
+
+static int
+vtv_log_write (int fd, const char *str)
+{
+  if (write (fd, str, strlen (str)) != -1)
+    return 0;
+
+  if (fd != 2) /* Make sure we dont get in a loop.  */
+    vtv_add_to_log (2, "Error writing to log: %s\n", strerror (errno));
+  return -1;
+}
+
+
+/* This function takes a file decriptor (LOG_FILE) and an output
+ format string (FORMAT), followed by zero or more print format
+ arguments (the same as fprintf, for example).  It gets the current
+ process ID and PPID, pre-pends them to the formatted message, and
+ writes write it out to the log file referenced by LOG_FILE via calles
+ to vtv_log_write.  */
+
+int
+vtv_add_to_log (int log_file, const char * format, ...)
+{
+  /* We dont want to dynamically allocate this buffer. This should be
+     more than enough in most cases. It if isn't we are careful not to
+     do a buffer overflow.  */
+  char output[1024];
+
+  va_list ap;
+  va_start (ap, format);
+
+  snprintf (output, sizeof (output), "VTV: PID=%d PPID=%d ", getpid (),
+	    getppid ());
+  vtv_log_write (log_file, output);
+  vsnprintf (output, sizeof (output), format, ap);
+  vtv_log_write (log_file, output);
+  va_end (ap);
+
+  /* fdatasync is quite expensive. Only enable if you suspect you are
+     loosing log data in in a program crash?  */
+  /*  fdatasync(log_file);  */
+
+  return 0;
+}
Index: libstdc++-v3/libsupc++/vtv_utils.h
===================================================================
--- libstdc++-v3/libsupc++/vtv_utils.h	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_utils.h	(revision 0)
@@ -0,0 +1,52 @@
+/* Copyright (C) 2012-2013
+   Free Software Foundation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _VTV_UTILS_H
+#define _VTV_UTILS_H 1
+
+#include <stdlib.h>
+
+extern bool vtv_debug;
+
+/* Handler for verification runtime errors.  */
+#define VTV_error abort
+
+/* Assertion macros used in vtable verification runtime.  */
+#define VTV_ASSERT(EXPR) ((bool) (!(EXPR) ? VTV_error() : (void) 0))
+#define VTV_DEBUG_ASSERT(EXPR) \
+                      ((bool) (vtv_debug && !(EXPR)) ? VTV_error() : (void) 0)
+
+/* Name of the section where we put general VTV variables for protection */
+#define VTV_PROTECTED_VARS_SECTION ".vtable_map_vars"
+#define VTV_PROTECTED_VAR \
+                       __attribute__ ((section (VTV_PROTECTED_VARS_SECTION)))
+
+/* The following logging routines try to use low level file access
+   routines and avoid calling malloc. We need this so that we dont
+   disturb the order of calls to dlopen.  Changing the order of dlopen
+   calls may lead to deadlocks */
+int vtv_open_log (const char * name);
+int vtv_add_to_log (int log, const char * format, ...);
+
+#endif /* VTV_UTILS_H */
Index: libstdc++-v3/libsupc++/vtv_init.cc
===================================================================
--- libstdc++-v3/libsupc++/vtv_init.cc	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_init.cc	(revision 0)
@@ -0,0 +1,96 @@
+/* Copyright (C) 2012-2013
+   Free Software Foundation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+
+/* This file contains all the definitions that go into the libvtv_init
+   library, which is part of the vtable verification feature.  This
+   library should contain exactly two functions (__VLTunprotect and
+   __VLTprotect) and one global variable definition
+   (__vtv_defined_in_vtv_init_lib).  Any program that was compiled
+   with the option "-fvtable-verify=std" MUST also be linked with
+   libvtv_init, because the two functions defined here are used by the
+   vtable verification code.  The reason they are in a separate
+   library rather than in libstdc++ with all the rest of the vtable
+   verification runtime code is as follows.  Each .o file that was
+   compiled with vtable verification will contain calls into the
+   runtime (made from constructor initialization functions) to build
+   the data structures needed for verification.  At all times except
+   when they are being constructed, these data structures need to be
+   in protected memory, so that attackers cannot corrupt them.
+   __VLTunprotect sets the memory containing these data structures to
+   be writable, for updates.  __VLTprotect makes the memory read-only,
+   for all other times.  This memory protection and unprotection is
+   done via calls to mprotect, which are costly.  So instead of
+   calling __VLTunprotect and __VLTprotect once per object file we
+   want to call them once per executable.  Therefore instead of
+   putting calls to them directly into each object file, we put the
+   calls to them only in __VLTRegisterPair, in the libstdc++ library.
+   We give __VLTunprotect an initialization priority to make it run
+   before all of our data structure construction functions, and we
+   give __VLTprotect an initialization priority to make it run after
+   all of our data structure constructiion functions.  We put them
+   into a separate library and link that library with the
+   "--whole-archive" linker option, to make sure that both functions get
+   linked in (since the actual calls to them are in the libstdc++
+   runtime).  We can't put them into libstdc++ because linking
+   libstdc++ with "--whole-archive" is probably not a good idea.
+
+   The __vtv_defined_in_vtv_lib variable is referenced, but not
+   defined, in the constructor initialization functions where we have
+   the calls to build our data structures.  The purpose of this
+   variable is to cause a linker error to occur if the programmer
+   compiled with -fvtable-verify=std and did not link with the vtv_int
+   library (better a link-time error than a run-time error).  */
+
+
+/* Needs to build with C++ because the definition of
+   __VLTChangePermission is in C++.  */
+#ifndef __cplusplus
+#error "This file must be compiled with a C++ compiler"
+#endif
+
+#include "vtv_rts.h"
+
+/* #include <stdio.h> */
+
+/* Define this dummy symbol to detect at link time the cases where
+   user is compiling with -fvtable-verify=std and not linking with the
+   vtv_init library. Note that the visibility needs to be hidden. Each
+   object module is supposed to link with the vtv_init library and we
+   don't want this definition to come from a different library */
+unsigned int
+__vtv_defined_in_vtv_init_lib __attribute__ ((visibility ("hidden"))) = 0;
+
+
+__attribute__ ((constructor(98))) void
+__VLTunprotect (void)
+{
+  __VLTChangePermission (__VLTP_READ_WRITE);
+}
+
+__attribute__ ((constructor(100))) void
+__VLTprotect (void)
+{
+  __VLTChangePermission (__VLTP_READ_ONLY);
+}
Index: libstdc++-v3/libsupc++/vtv_malloc.cc
===================================================================
--- libstdc++-v3/libsupc++/vtv_malloc.cc	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_malloc.cc	(revision 0)
@@ -0,0 +1,209 @@
+/* Copyright (C) 2012-2013
+   Free Software Foundation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file is part of the vtable verification runtime library.  It
+   contains our memory allocation and deallocation routines, which we
+   use in order to keep track of the pages in memory in which our sets
+   of valid vtable pointes are stored.  (We need to know the pages so
+   we can set the protections on them appropriately).  For more
+   information about the vtable verification feature, see the comments
+   in vtv_rts.cc.  We use the existing obstack implementation in our
+   memory allocation scheme.  */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include "vtv_utils.h"
+#include "vtv_malloc.h"
+#include "obstack.h"
+
+/* Put the following variables in our ".vtable_map_vars" section so
+   that they are protected.  They are explicitly unprotected and
+   protected again by calls to VTV_unprotect and VTV_protect */
+
+static struct obstack VTV_obstack VTV_PROTECTED_VAR;
+static unsigned long page_size VTV_PROTECTED_VAR = 0;
+static void *current_chunk VTV_PROTECTED_VAR = 0;
+static size_t current_chunk_size VTV_PROTECTED_VAR = 0;
+static int malloc_initialized VTV_PROTECTED_VAR = 0;
+
+static bool debug_malloc = false;
+
+/* This function goes through all of the pages we have allocated so
+   far and calls mprotect to make each page read-only.  */
+
+void
+VTV_malloc_protect (void)
+{
+  struct _obstack_chunk *ci;
+  ci = (struct _obstack_chunk *) current_chunk;
+  while (ci)
+    {
+      VTV_DEBUG_ASSERT (((unsigned long) ci & (page_size - 1)) == 0);
+      if (mprotect (ci, (ci->limit - (char *) ci), PROT_READ) == -1)
+	VTV_error ();
+      ci = ci->prev;
+    }
+
+  if (debug_malloc)
+    VTV_malloc_dump_stats ();
+}
+
+/* This function goes through all of the pages we have allocated so
+   far and calls mrpotect to make each page read-write.  */
+
+void
+VTV_malloc_unprotect (void)
+{
+  struct _obstack_chunk * ci;
+  ci = (struct _obstack_chunk *) current_chunk;
+  while (ci)
+    {
+      VTV_DEBUG_ASSERT (((unsigned long) ci & (page_size - 1)) == 0);
+      if (mprotect (ci, (ci->limit - (char *) ci), PROT_READ | PROT_WRITE)
+                                                                         == -1)
+	VTV_error ();
+      ci = ci->prev;
+    }
+}
+
+/* Allocates a SIZE-sized chunk of memory that is aligned to a page
+   boundary.  The amount of memory requested (SIZE) must be a multiple
+   of the page size.  Note: We must use mmap to allocate the memory;
+   using malloc here will cause problems.  */
+
+static void *
+obstack_chunk_alloc (size_t size)
+{
+  /* Increase size to the next multiple of page_size.   */
+  size = (size + (page_size - 1)) & (~(page_size - 1));
+  VTV_DEBUG_ASSERT ((size & (page_size - 1)) == 0);
+  void *allocated;
+
+  if ((allocated = mmap (NULL, size, PROT_READ | PROT_WRITE,
+                         MAP_PRIVATE | MAP_ANONYMOUS,  -1, 0)) == 0)
+    VTV_error ();
+
+  VTV_DEBUG_ASSERT (((unsigned long) allocated & (page_size - 1)) == 0);
+
+  current_chunk = allocated;
+  current_chunk_size = size;
+  return allocated;
+}
+
+static void
+obstack_chunk_free (size_t size)
+{
+  /* Do nothing. For our purposes there should be very little
+     de-allocation. */
+}
+
+/* This function sets up and initializes the obstack pieces for our
+   memory allocation scheme.  */
+
+void
+VTV_malloc_init (void)
+{
+  /* Make sure we only execute the main body of this function ONCE.  */
+  if (malloc_initialized)
+    return;
+
+  page_size = sysconf (_SC_PAGE_SIZE);
+
+  obstack_chunk_size (&VTV_obstack) = page_size;
+  obstack_alignment_mask (&VTV_obstack) = sizeof (long) - 1;
+  /* We guarantee that the obstack alloc failed handler will never be
+     called because in case the allocation of the chunk fails, it will
+     never return */
+  obstack_alloc_failed_handler = NULL;
+
+  obstack_init (&VTV_obstack);
+  malloc_initialized = 1;
+}
+
+/* This is our external interface for the memory allocation.  SIZE is
+   the requested number of bytes to be allocated/  */
+
+void *
+VTV_malloc (size_t size)
+{
+  return obstack_alloc (&VTV_obstack, size);
+}
+
+
+/* This is our external interface for memory deallocation.  */
+
+void
+VTV_free (void *)
+{
+  /* Do nothing. We dont care about recovering unneded memory at this
+     time.  */
+}
+
+
+/* This is a debugging function tat collects statistics about our
+   memory allocation.  */
+void
+VTV_malloc_stats (void)
+{
+  int count = 0;
+  struct _obstack_chunk * ci = (struct _obstack_chunk *) current_chunk;
+  while (ci)
+    {
+      count++;
+      ci = ci->prev;
+    }
+  fprintf (stderr,
+	   "VTV_malloc_stats:\n  Page Size = %lu bytes\n  "
+	   "Number of pages = %d\n", page_size, count);
+}
+
+/* This is a debugging function.  It writes out our memory allocation
+   statistics to a log file.  */
+
+void
+VTV_malloc_dump_stats (void)
+{
+  static int fd = -1;
+
+  if (fd == -1)
+    fd = vtv_open_log ("/tmp/vtv_mem_protection.log");
+  if (fd == -1)
+    return;
+
+  int count = 0;
+  struct _obstack_chunk * ci = (struct _obstack_chunk *) current_chunk;
+  while (ci)
+    {
+      count++;
+      ci = ci->prev;
+    }
+
+  vtv_add_to_log (fd, "VTV_malloc_protect protected=%d pages\n", count);
+}
Index: libstdc++-v3/libsupc++/Makefile.am
===================================================================
--- libstdc++-v3/libsupc++/Makefile.am	(revision 196516)
+++ libstdc++-v3/libsupc++/Makefile.am	(working copy)
@@ -25,7 +25,7 @@ include $(top_srcdir)/fragment.am
 # Need this library to both be part of libstdc++.a, and installed
 # separately too.
 # 1) separate libsupc++.la
-toolexeclib_LTLIBRARIES = libsupc++.la
+toolexeclib_LTLIBRARIES = libsupc++.la libvtv_init.la libvtv_stubs.la
 # 2) integrated libsupc++convenience.la that is to be a part of libstdc++.a
 noinst_LTLIBRARIES = libsupc++convenience.la
 
@@ -92,10 +92,21 @@ sources = \
 	tinfo2.cc \
 	vec.cc \
 	vmi_class_type_info.cc \
-	vterminate.cc
+	vterminate.cc \
+	vtv_rts.cc \
+	vtv_malloc.cc \
+	vtv_utils.cc
+
+vtv_init_sources = \
+	vtv_init.cc
+
+vtv_stubs_sources = \
+	vtv_stubs.cc 
 
 libsupc___la_SOURCES = $(sources) $(c_sources)
 libsupc__convenience_la_SOURCES = $(sources) $(c_sources)
+libvtv_init_la_SOURCES = $(vtv_init_sources)
+libvtv_stubs_la_SOURCES = $(vtv_stubs_sources)
 
 cp-demangle.c:
 	rm -f $@
Index: libstdc++-v3/libsupc++/Makefile.in
===================================================================
--- libstdc++-v3/libsupc++/Makefile.in	(revision 196516)
+++ libstdc++-v3/libsupc++/Makefile.in	(working copy)
@@ -103,7 +103,8 @@ am__objects_1 = array_type_info.lo atexi
 	new_handler.lo new_op.lo new_opnt.lo new_opv.lo new_opvnt.lo \
 	pbase_type_info.lo pmem_type_info.lo pointer_type_info.lo \
 	pure.lo si_class_type_info.lo tinfo.lo tinfo2.lo vec.lo \
-	vmi_class_type_info.lo vterminate.lo
+	vmi_class_type_info.lo vterminate.lo vtv_rts.lo vtv_malloc.lo \
+	vtv_utils.lo
 @GLIBCXX_HOSTED_TRUE@am__objects_2 = cp-demangle.lo
 am_libsupc___la_OBJECTS = $(am__objects_1) $(am__objects_2)
 libsupc___la_OBJECTS = $(am_libsupc___la_OBJECTS)
@@ -111,6 +112,14 @@ libsupc__convenience_la_LIBADD =
 am_libsupc__convenience_la_OBJECTS = $(am__objects_1) $(am__objects_2)
 libsupc__convenience_la_OBJECTS =  \
 	$(am_libsupc__convenience_la_OBJECTS)
+libvtv_init_la_LIBADD =
+am__objects_3 = vtv_init.lo
+am_libvtv_init_la_OBJECTS = $(am__objects_3)
+libvtv_init_la_OBJECTS = $(am_libvtv_init_la_OBJECTS)
+libvtv_stubs_la_LIBADD =
+am__objects_4 = vtv_stubs.lo
+am_libvtv_stubs_la_OBJECTS = $(am__objects_4)
+libvtv_stubs_la_OBJECTS = $(am_libvtv_stubs_la_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp =
 am__depfiles_maybe =
@@ -123,7 +132,8 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLF
 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
 	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
 CXXLD = $(CXX)
-SOURCES = $(libsupc___la_SOURCES) $(libsupc__convenience_la_SOURCES)
+SOURCES = $(libsupc___la_SOURCES) $(libsupc__convenience_la_SOURCES) \
+	$(libvtv_init_la_SOURCES) $(libvtv_stubs_la_SOURCES)
 HEADERS = $(bits_HEADERS) $(std_HEADERS)
 ETAGS = etags
 CTAGS = ctags
@@ -347,7 +357,7 @@ AM_CPPFLAGS = $(GLIBCXX_INCLUDES)
 # Need this library to both be part of libstdc++.a, and installed
 # separately too.
 # 1) separate libsupc++.la
-toolexeclib_LTLIBRARIES = libsupc++.la
+toolexeclib_LTLIBRARIES = libsupc++.la libvtv_init.la libvtv_stubs.la
 # 2) integrated libsupc++convenience.la that is to be a part of libstdc++.a
 noinst_LTLIBRARIES = libsupc++convenience.la
 std_HEADERS = \
@@ -410,10 +420,21 @@ sources = \
 	tinfo2.cc \
 	vec.cc \
 	vmi_class_type_info.cc \
-	vterminate.cc
+	vterminate.cc \
+	vtv_rts.cc \
+	vtv_malloc.cc \
+	vtv_utils.cc
+
+vtv_init_sources = \
+	vtv_init.cc
+
+vtv_stubs_sources = \
+	vtv_stubs.cc 
 
 libsupc___la_SOURCES = $(sources) $(c_sources)
 libsupc__convenience_la_SOURCES = $(sources) $(c_sources)
+libvtv_init_la_SOURCES = $(vtv_init_sources)
+libvtv_stubs_la_SOURCES = $(vtv_stubs_sources)
 
 # AM_CXXFLAGS needs to be in each subdirectory so that it can be
 # modified in a per-library or per-sub-library way.  Need to manually
@@ -575,6 +596,10 @@ libsupc++.la: $(libsupc___la_OBJECTS) $(
 	$(CXXLINK) -rpath $(toolexeclibdir) $(libsupc___la_OBJECTS) $(libsupc___la_LIBADD) $(LIBS)
 libsupc++convenience.la: $(libsupc__convenience_la_OBJECTS) $(libsupc__convenience_la_DEPENDENCIES) 
 	$(CXXLINK)  $(libsupc__convenience_la_OBJECTS) $(libsupc__convenience_la_LIBADD) $(LIBS)
+libvtv_init.la: $(libvtv_init_la_OBJECTS) $(libvtv_init_la_DEPENDENCIES) 
+	$(CXXLINK) -rpath $(toolexeclibdir) $(libvtv_init_la_OBJECTS) $(libvtv_init_la_LIBADD) $(LIBS)
+libvtv_stubs.la: $(libvtv_stubs_la_OBJECTS) $(libvtv_stubs_la_DEPENDENCIES) 
+	$(CXXLINK) -rpath $(toolexeclibdir) $(libvtv_stubs_la_OBJECTS) $(libvtv_stubs_la_LIBADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
Index: libstdc++-v3/libsupc++/vtv_rts.cc
===================================================================
--- libstdc++-v3/libsupc++/vtv_rts.cc	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_rts.cc	(revision 0)
@@ -0,0 +1,1189 @@
+/* Copyright (C) 2012-2013
+ Free Software Foundation
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ <http://www.gnu.org/licenses/>.  */
+
+/* This file is part of the vtable security feature implementation.
+   The vtable security feature is designed to detect when a virtual
+   call is about to be made through an invalid vtable pointer
+   (possibly due to data corruption or malicious attacks). The
+   compiler finds every virtual call, and inserts a verification call
+   before the virtual call.  The verification call takes the actual
+   vtable pointer value in the object through which the virtual call
+   is being made, and compares the vtable pointer against a set of all
+   valid vtable pointers that the object could contain (this set is
+   based on the declared type of the object).  If the pointer is in
+   the valid set, execution is allowed to continue; otherwise the
+   program is halted.
+
+  There are several pieces needed in order to make this work: 1. For
+  every virtual class in the program (i.e. a class that contains
+  virtual methods), we need to build the set of all possible valid
+  vtables that an object of that class could point to.  This includes
+  vtables for any class(es) that inherit from the class under
+  consideration.  2. For every such data set we build up, we need a
+  way to find and reference the data set.  This is complicated by the
+  fact that the real vtable addresses are not known until runtime,
+  when the program is loaded into memory, but we need to reference the
+  sets at compile time when we are inserting verification calls into
+  the program.  3.  We need to find every virtual call in the program,
+  and insert the verification call (with the appropriate arguments)
+  before the virtual call.  4. We need some runtime library pieces:
+  the code to build up the data sets at runtime; the code to actually
+  perform the verification using the data sets; and some code to set
+  protections on the data sets, so they themselves do not become
+  hacker targets.
+
+  To find and reference the set of valid vtable pointers for any given
+  virtual class, we create a special global varible for each virtual
+  class.  We refer to this as the "vtable map variable" for that
+  class.  The vtable map variable has the type "void *", and is
+  initialized by the compiler to NULL.  At runtime when the set of
+  valid vtable pointers for a virtual class, e.g. class Foo, is built,
+  the vtable map variable for class Foo is made to point to the set.
+  During compile time, when the compiler is inserting verification
+  calls into the program, it passes the vtable map variable for the
+  appropriate class to the verification call, so that at runtime the
+  verification call can find the appropriate data set.
+
+  The actual set of valid vtable pointers for a polymorphic class,
+  e.g. class Foo, cannot be built until runtime, when the vtables get
+  loaded into memory and their addresses are known.  But the knowledge
+  about which vtables belong in which class' hierarchy is only known
+  at compile time.  Therefore at compile time we collect class
+  hierarchy and vtable information about every virtual class, and we
+  generate calls to build up the data sets at runtime.  To build the
+  data sets, we call one of the functions we add to the runtime
+  library, __VLTRegisterPair.  __VLTRegisterPair takes two arguments,
+  a vtable map variable and the address of a vtable.  If the vtable
+  map variable is currently NULL, it creates a new data set (hash
+  table), makes the vtable map variable point to the new data set, and
+  inserts the vtable address into the data set.  If the vtable map
+  variable is not NULL, it just inserts the vtable address into the
+  data set.  In order to make sure that our data sets are built before
+  any verification calls happen, we create a special constructor
+  initialization function for each compilation unit, give it a very
+  high initialization priority, and insert all of our calls to
+  __VLTRegisterPair into our special constructor initialization
+  function.  */
+
+/* This file contains the main externally visible runtime library
+   functions for vtable verification: __VLTChangePermission,
+   __VLTRegisterPair, and __VLTVerifyVtablePointer.  It also contains
+   debug versions __VLTRegisterPairDebug and
+   __VLTVerifyVtablePointerDebug, which have extra parameters in order
+   to make it easier to debug verification failures.
+
+   This file also contains the failure functions that get called when
+   a vtable pointer is not found in the data set.  Two particularly
+   important functions are __vtv_verify_fail and __vtv_really_fail.
+   They are both externally visible.  __vtv_verify_fail is defined in
+   such a way that it can be replaced by a programmer, if desired.  It
+   is the function that __VLTVerifyVtablePointer calls if it can't
+   find the pointer in the data set.  Allowing the programmer to
+   overwrite this function means that he/she can do some alternate
+   verification, including NOT failing in certain specific cases, if
+   desired.  This may be the case if the programmer has to deal wtih
+   unverified third party software, for example.  __vtv_really_fail is
+   available for the programmer to call from his version of
+   __vtv_verify_fail, if he decides the failure is real.
+
+   The final piece of functionality implemented in this file is symbol
+   resolution for multiple instances of the same vtable map variable.
+   If the same virtual class is used in two different compilation
+   units, then each compilation unit will create a vtable map variable
+   for the class.  We need all instances of the same vtable map
+   variable to point to the same (single) set of valid vtable
+   pointers for the class, so we wrote our own hashtable-based symbol
+   resolution for vtable map variables (with a tiny optimization in
+   the case where there is only one instance of the variable).
+
+   There are two other important pieces to the runtime for vtable
+   verification besides the main pieces that go into libstdc++.so: two
+   special tiny shared libraries, libvtv_init.so and libvtv_stubs.so.
+   libvtv_init.so is built from vtv_init.cc.  It is designed to help
+   minimize the calls made to mprotect (see the comments in
+   vtv_init.cc for more details).  Anything compiled with
+   "-fvtable-verify=std" must be linked with libvtv_init.so (the gcc
+   driver has been modified to do this).  vtv_stubs.so is built from
+   vtv_stubs.cc.  It replaces the main runtime functions
+   (__VLTChangePermissino, __VLTRegisterPair and
+   __VLTVerifyVtablePointer) with stub functions that do nothing.  If
+   a programmer has a library that was built with verification, but
+   wishes to not have verification turned on, the programmer can link
+   in the vtv_stubs.so library.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <execinfo.h>
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <link.h>
+#include <fcntl.h>
+
+/* For gthreads suppport */
+#include <bits/c++config.h>
+#include <ext/concurrence.h>
+
+#include "vtv_utils.h"
+#include "vtv_malloc.h"
+#include "vtv_set.h"
+#include "vtv_map.h"
+#include "vtv_rts.h"
+#include "vtv_fail.h"
+
+bool vtv_debug = false;
+
+/* This is used to disable aborts for debugging purposes.  */
+bool vtv_no_abort = false;
+
+extern "C" {
+
+  /* __fortify_fail is a function in glibc that calls __libc_message,
+     causing it to print out a program termination error message
+     (including the name of the binary being terminated), a stack
+     trace where the error occurred, and a memory map dump.  Ideally
+     we would have called __libc_message directly, but that function
+     does not appear to be accessible to functions outside glibc,
+     whereas __fortify_fail is.  We call __fortify_fail from
+     __vtv_really_fail.  We looked at calling __libc_fatal, which is
+     externally accessible, but it does not do the back trace and
+     memory dump.  */
+
+  extern void __fortify_fail (const char *) __attribute__((noreturn));
+
+} /* extern "C" */
+
+
+/* Be careful about initialization of statics in this file.  Some of
+   the routines below are called before any runtime initialization for
+   statics in this file will be done. For example, dont try to
+   initialize any of these statics with a runtime call (for ex:
+   sysconf). The initialization will happen after calls to the routines
+   to protect/unprotec the vtabla_map variables */
+
+/* No need to mark the following variables with VTV_PROTECTED_VAR.
+   These are either const or are only used for debugging/tracing.
+   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;
+
+
+/* Global file descriptor variables for logging, tracing and debugging.  */
+
+static int init_log_fd = -1;
+static int verify_vtable_log_fd = -1;
+static int vtv_failures_log_fd = -1;
+static int set_log_fd = -1;
+
+/* This holds a formatted error logging message, to be written to the
+   vtable verify failures log.  */
+static char debug_log_message[1024];
+
+
+#ifdef __GTHREAD_MUTEX_INIT
+static __gthread_mutex_t change_permissions_lock = __GTHREAD_MUTEX_INIT;
+#else
+static __gthread_mutex_t change_permissions_lock;
+#endif
+
+
+/* Types needed by insert_only_hash_sets.  */
+typedef uintptr_t int_vptr;
+
+/* The set of valid vtable pointers for each virtual class is stored
+   in a hash table.  This is the hashing function used for the hash
+   table.  For more information on the implementation of the hash
+   table, see the class insert_only_hash_sets in vtv_set.h.  */
+
+struct vptr_hash
+  {
+    /* Hash function, used to convert vtable pointer, V, (a memory
+       address) into an index into the hash table.  */
+    size_t
+    operator() (int_vptr v) const
+      {
+	const uint32_t x = 0x7a35e4d9;
+	const int shift = (sizeof (v) == 8) ? 23 : 21;
+	v = x * v;
+	return v ^ (v >> shift);
+      }
+  };
+
+/* This is the memory allocator used to create the hash table data
+   sets of valid vtable pointers.  We use VTV_malloc in order to keep
+   track of which pages have been allocated, so we can update the
+   protections on those pages appropriately.  See the class
+   insert_only_hash_sets in vtv_set.h for more information.  */
+
+struct vptr_set_alloc
+  {
+    /* Memory allocator operator.  N is the number of bytes to be
+       allocated.  */
+    void *
+    operator() (size_t n) const
+      {
+	return VTV_malloc (n);
+      }
+  };
+
+/* Instantiate the template classes (in vtv_set.h) for our particular
+   hash table needs.  */
+typedef insert_only_hash_sets<int_vptr, vptr_hash, vptr_set_alloc> vtv_sets;
+typedef vtv_sets::insert_only_hash_set vtv_set;
+typedef vtv_set * vtv_set_handle;
+typedef vtv_set_handle * vtv_set_handle_handle; 
+
+/* Data structure passed to our dl_iterate_phdr callback function,
+   indicating whether mprotect should make the pages readonly or
+   read/write, and what page size to use.  */
+
+struct mprotect_data
+  {
+    int prot_mode;
+    unsigned long page_size;
+  };
+
+/* This function tries to read COUNT bytes out of the file referred to
+   by FD into the buffer BUF.  It returns the actual number of bytes
+   it succeeded in reading.  */
+
+static size_t
+ReadPersistent (int fd, void *buf, size_t count)
+{
+  char *buf0 = (char *) buf;
+  size_t num_bytes = 0;
+  while (num_bytes < count)
+    {
+      int len;
+      len = read (fd, buf0 + num_bytes, count - num_bytes);
+      if (len < 0)
+	return -1;
+      if (len == 0)
+	break;
+      num_bytes += len;
+    }
+
+  return num_bytes;
+}
+
+/* This function tries to read COUNT bytes, starting at OFFSET from
+   the file referred to by FD, and put them into BUF.  It calls
+   ReadPersistent to help it do so.  It returns the actual number of
+   bytes read, or -1 if it fails altogether.  */
+
+static size_t
+ReadFromOffset (int fd, void *buf, const size_t count, const off_t offset)
+{
+  off_t off = lseek (fd, offset, SEEK_SET);
+  if (off != (off_t) -1)
+    return ReadPersistent (fd, buf, count);
+  return -1;
+}
+
+/* The function takes a MESSAGE and attempts to write it to the vtable
+   memory protection log (for debugging purposes).  If the file is not
+   open, it attempts to open the file first.  Sometimes multiple
+   processes may be attempting to write to the log file at the same
+   time, so we may attempt to open multiple log files (with versioned
+   names) if the first open fails.  */
+
+static void
+log_memory_protection_data (char *message)
+{
+  static int log_fd = -1;
+
+  char buffer[50];
+  int i = 0;
+
+  /* Attempt to open up to 25 log files.*/
+  while (log_fd == -1 && i < 25)
+    {
+      snprintf (buffer, sizeof (buffer), "vtv_memory_protection_data_%d.log",
+		i);
+  
+      if (log_fd == -1)
+	log_fd = vtv_open_log (buffer);
+      ++i;
+    }
+
+  vtv_add_to_log (log_fd, "%s", message);
+  fsync (log_fd);
+}
+
+/* This is the callback function used by dl_iterate_phdr (which is
+   called from VTV_unprotect_vtable_vars and VTV_protect_vtable_vars).
+   It attempts to find the binary file on disk for the INFO record
+   that dl_iterate_phdr passes in; open the binary file, and read its
+   section header information.  If the file contains a
+   ".vtable_map_vars" section, read the section offset and size.  Use
+   the section offset and size, in conjunction with the data in INFO
+   to locate the pages in memory where the section is.  Call
+   'mprotect' on those pages, setting the protection either to
+   read-only or read-write, depending on what's in DATA.  */
+
+static int
+dl_iterate_phdr_callback (struct dl_phdr_info *info, size_t unused, void *data)
+{
+  mprotect_data * mdata = (mprotect_data *) data;
+  off_t map_sect_offset = 0;
+  ElfW (Word) map_sect_len = 0;
+  ElfW (Addr) start_addr = 0;
+  int j;
+  bool found = false;
+  char buffer[1024];
+  char program_name[1024];
+  char *cptr;
+  const ElfW (Phdr) *phdr_info = info->dlpi_phdr;
+  const ElfW (Ehdr) *ehdr_info =
+    (const ElfW (Ehdr) *) (info->dlpi_addr + info->dlpi_phdr[0].p_vaddr
+			   - info->dlpi_phdr[0].p_offset);
+
+  /* Get the name of the main executable.  This may or may not include
+     arguments passed to the program.  Find the first space, assume it
+     is the start of the argument list, and change it to a '\0'. */
+
+  snprintf (program_name, sizeof (program_name), program_invocation_name);
+
+  /* Find the first non-escaped space in the program name and make it
+     the end of the string.  */
+  cptr = strchr (program_name, ' ');
+  if (cptr != NULL && cptr[-1] != '\\')
+    cptr[0] = '\0';
+
+  if ((phdr_info->p_type == PT_PHDR || phdr_info->p_type == PT_LOAD)
+      && (ehdr_info->e_shoff && ehdr_info->e_shnum))
+    {
+      const char *map_sect_name = ".vtable_map_vars";
+      int name_len = strlen (map_sect_name);
+      int fd = -1;
+
+      /* Attempt to open the binary file on disk.  */
+
+      if (strlen (info->dlpi_name) == 0)
+	{
+	  if (phdr_info->p_type == PT_PHDR)
+	    fd = open (program_name, O_RDONLY);
+	}
+      else
+	fd = open (info->dlpi_name, O_RDONLY);
+      
+      if (fd != -1)
+	{
+	  /* Find the section header information in the file.  */
+	  
+	  ElfW (Half) strtab_idx = ehdr_info->e_shstrndx;
+	  ElfW (Shdr) shstrtab;
+	  off_t shstrtab_offset = ehdr_info->e_shoff +
+	                                 (ehdr_info->e_shentsize * strtab_idx);
+	  size_t bytes_read = ReadFromOffset (fd, &shstrtab, sizeof (shstrtab),
+					      shstrtab_offset);
+	  if (bytes_read == sizeof (shstrtab))
+	    {
+	      ElfW (Shdr) sect_hdr;
+	      /* Loop through all the section headers, looking for one
+		 whose name is ".vtable_map_vars".  */
+
+	      for (int i = 0; i < ehdr_info->e_shnum && !found; ++i)
+		{
+		  off_t offset = ehdr_info->e_shoff
+		                                + (ehdr_info->e_shentsize * i);
+		  bytes_read = ReadFromOffset (fd, &sect_hdr,
+					       sizeof (sect_hdr), offset);
+		  if (bytes_read == sizeof (sect_hdr))
+		    {
+		      char header_name[64];
+		      off_t name_offset = shstrtab.sh_offset +
+			                                      sect_hdr.sh_name;
+		      bytes_read = ReadFromOffset (fd, &header_name, 64,
+						   name_offset);
+		      if (bytes_read > 0)
+			if (memcmp (header_name, map_sect_name, name_len) == 0)
+			  {
+			    /* We found the section; get its load
+			       offset and size.  */
+			    map_sect_offset = sect_hdr.sh_addr;
+			    map_sect_len = sect_hdr.sh_size - mdata->page_size;
+			    found = true;
+			  }
+		    }
+		}
+	    }
+	  close (fd);
+	}
+      /* Calculate the start address of the section in memory.  */
+      start_addr = (const ElfW (Addr)) info->dlpi_addr + map_sect_offset;
+    }
+      
+
+  if (debug_functions)
+    {
+      snprintf (buffer, sizeof(buffer),
+		"  Looking at load module %s to change permissions to %s\n",
+		((strlen (info->dlpi_name) == 0) ? program_name
+                                                 : info->dlpi_name),
+		(mdata->prot_mode & PROT_WRITE) ? "READ/WRITE" : "READ-ONLY");
+      log_memory_protection_data (buffer);
+    }
+
+  /* See if we actually found the section.  */
+  if (start_addr && map_sect_len)
+    {
+      ElfW (Addr) relocated_start_addr = start_addr;
+      ElfW (Word) size_in_memory = map_sect_len;
+
+      if ((relocated_start_addr != 0)
+	  && (size_in_memory != 0))
+        {
+	  /* Calculate the address & size to pass to mprotect. */
+          ElfW (Addr) mp_low = relocated_start_addr & ~(mdata->page_size - 1);
+          size_t mp_size = size_in_memory - 1;
+
+	  if (debug_functions)
+	    {
+	      snprintf (buffer, sizeof (buffer),
+			"  (%s): Protecting %p to %p\n", 
+		       ((strlen (info->dlpi_name) == 0) ? program_name
+			                                : info->dlpi_name),
+		       (void *) mp_low,
+		       ((void *) mp_low + mp_size));
+	      log_memory_protection_data (buffer);
+	    }
+	  
+	  /* Change the protections on the pages for the section.  */
+          if (mprotect ((void *) mp_low, mp_size, mdata->prot_mode) == -1)
+            {
+              if (debug_functions)
+                {
+                  snprintf (buffer, sizeof (buffer),
+			    "Failed called to mprotect for %s error: ",
+			    (mdata->prot_mode & PROT_WRITE) ?
+			    "READ/WRITE" : "READ-ONLY");
+		  log_memory_protection_data (buffer);
+                  perror(NULL);
+                }
+              VTV_error();
+            }
+          else if (debug_functions)
+	    {
+	      snprintf (buffer, sizeof (buffer),
+			"mprotect'ed range [%p, %p]\n",
+			(void *) mp_low, (char *) mp_low + mp_size);
+	      log_memory_protection_data (buffer);
+	    }
+        }
+    }
+
+  return 0;
+}
+
+/* Unprotect all the vtable map vars and other side data that is used
+   to keep the core hash_map data. All of these data have been put
+   into relro sections */
+
+static void
+VTV_unprotect_vtable_vars (void)
+{
+  mprotect_data mdata;
+
+  mdata.prot_mode = PROT_READ | PROT_WRITE;
+  mdata.page_size = sysconf (_SC_PAGE_SIZE);
+  dl_iterate_phdr (dl_iterate_phdr_callback, (void *) &mdata);
+}
+
+/* Protect all the vtable map vars and other side data that is used
+   to keep the core hash_map data. All of these data have been put
+   into relro sections */
+
+static void
+VTV_protect_vtable_vars (void)
+{
+  mprotect_data mdata;
+
+  mdata.prot_mode = PROT_READ;
+  mdata.page_size = sysconf (_SC_PAGE_SIZE);
+  dl_iterate_phdr (dl_iterate_phdr_callback, (void *) &mdata);
+}
+
+#ifndef __GTHREAD_MUTEX_INIT
+static void
+initialize_change_permissions_mutexes ()
+{
+  __GTHREAD_MUTEX_INIT_FUNCTION (&change_permissions_lock);
+}
+#endif
+
+/*  Variables needed for getting the statistics about the hashtable set.  */
+#if HASHTABLE_STATS
+_AtomicStatCounter stat_contains = 0;
+_AtomicStatCounter stat_insert = 0;
+_AtomicStatCounter stat_resize = 0;
+_AtomicStatCounter stat_create = 0;
+_AtomicStatCounter stat_probes_in_non_trivial_set = 0;
+_AtomicStatCounter stat_contains_size0 = 0;
+_AtomicStatCounter stat_contains_size1 = 0;
+_AtomicStatCounter stat_contains_size2 = 0;
+_AtomicStatCounter stat_contains_size3 = 0;
+_AtomicStatCounter stat_contains_size4 = 0;
+_AtomicStatCounter stat_contains_size5 = 0;
+_AtomicStatCounter stat_contains_size6 = 0;
+_AtomicStatCounter stat_contains_size7 = 0;
+_AtomicStatCounter stat_contains_size8 = 0;
+_AtomicStatCounter stat_contains_size9 = 0;
+_AtomicStatCounter stat_contains_size10 = 0;
+_AtomicStatCounter stat_contains_size11 = 0;
+_AtomicStatCounter stat_contains_size12 = 0;
+_AtomicStatCounter stat_contains_size13_or_more = 0;
+_AtomicStatCounter stat_contains_sizes = 0;
+_AtomicStatCounter stat_grow_from_size0_to_1 = 0;
+_AtomicStatCounter stat_grow_from_size1_to_2 = 0;
+_AtomicStatCounter stat_double_the_number_of_buckets = 0;
+_AtomicStatCounter stat_insert_found_hash_collision = 0;
+_AtomicStatCounter stat_contains_in_non_trivial_set = 0;
+_AtomicStatCounter stat_insert_key_that_was_already_present = 0;
+#endif
+/* Record statistics about the hash table sets, for debugging.  */
+
+static void
+log_set_stats (void)
+{
+#if HASHTABLE_STATS
+      if (set_log_fd == -1)
+	set_log_fd = vtv_open_log ("vtv_set_stats.log");
+
+      vtv_add_to_log (set_log_fd, "---\n%s\n",
+		      insert_only_hash_tables_stats().c_str());
+#endif
+}
+
+/* Change the permissions on all the pages we have allocated for the
+   data sets and all the ".vtable_map_var" sections in memory (which
+   contain our vtable map variables).  PERM indicates whether to make
+   the permissions read-only or read-write.  */
+
+void
+__VLTChangePermission (int perm)
+{
+  if (debug_functions)
+    {
+      if (perm == __VLTP_READ_WRITE)
+	fprintf (stdout, "Changing VLT permisisons to Read-Write.\n");
+      else if (perm == __VLTP_READ_ONLY)
+	fprintf (stdout, "Changing VLT permissions to Read-only.\n");
+      else
+	fprintf (stdout, "Unrecognized permissions value: %d\n", perm);
+    }
+
+#ifndef __GTHREAD_MUTEX_INIT
+  static __gthread_once_t mutex_once VTV_PROTECTED_VAR = __GTHREAD_ONCE_INIT;
+
+  __gthread_once (&mutex_once, initialize_change_permissions_mutexes);
+#endif
+
+  /* Ordering of these unprotect/protect calls is very important.
+     You first need to unprotect all the map vars and side
+     structures before you do anything with the core data
+     structures (hash_maps) */
+
+  if (perm == __VLTP_READ_WRITE)
+    {
+      /* TODO: Need to revisit this code for dlopen. It most probably
+         is not unlocking the protected vtable vars after for load
+         module that is not the first load module.  */
+      __gthread_mutex_lock (&change_permissions_lock);
+
+      VTV_unprotect_vtable_vars ();
+      VTV_malloc_init ();
+      VTV_malloc_unprotect ();
+
+    }
+  else if (perm == __VLTP_READ_ONLY)
+    {
+      if (debug_hash)
+        log_set_stats();
+
+      VTV_malloc_protect ();
+      VTV_protect_vtable_vars ();
+
+      __gthread_mutex_unlock (&change_permissions_lock);
+    }
+}
+
+/* This is the memory allocator used to create the hash table that
+   maps from vtable map variable name to the data set that vtable map
+   variable should point to.  This is part of our vtable map variable
+   symbol resolution, which is necessary because the same vtable map
+   variable may be created by multiple compilation units and we need a
+   method to make sure that all vtable map variables for a particular
+   class point to the same data set at runtime.  */
+
+struct insert_only_hash_map_allocator
+  {
+    /* N is the number of bytes to allocate.  */
+    void *
+    alloc (size_t n) const
+    {  
+      return VTV_malloc (n);
+    }
+
+    /* P points to the memory to be deallocated; N is the number of
+       bytes to deallocate.  */
+    void
+    dealloc (void *p, size_t n) const
+    {
+      VTV_free (p);
+    }
+  };
+
+/* Explicitly instantiate this class since this file is compiled with
+   -fno-implicit-templates.  These are for the hash table that is used
+   to do vtable map variable symbol resolution.  */
+template class insert_only_hash_map <vtv_set_handle *, 
+				     insert_only_hash_map_allocator >;
+typedef insert_only_hash_map <vtv_set_handle *,
+                              insert_only_hash_map_allocator > s2s;
+typedef const s2s::key_type  vtv_symbol_key;
+
+static s2s * vtv_symbol_unification_map VTV_PROTECTED_VAR = NULL;
+
+const unsigned long SET_HANDLE_HANDLE_BIT = 0x2;
+
+/* In the case where a vtable map variable is the only instance of the
+   variable we have seen, it points directly to the set of valid
+   vtable pointers.  All subsequent instances of the 'same' vtable map
+   variable point to the first vtable map variable.  This function,
+   given a vtable map variable PTR, checks a bit to see whether it's
+   pointing directly to the data set or to the first vtable map
+   variable.  */
+
+static inline bool
+is_set_handle_handle (void * ptr)
+{
+  return ((unsigned long) ptr & SET_HANDLE_HANDLE_BIT)
+                                                      == SET_HANDLE_HANDLE_BIT;
+}
+
+/* Returns the actual pointer value of a vtable map variable, PTR (see
+   comments for is_set_handle_handle for more details).  */
+
+static inline vtv_set_handle * 
+ptr_from_set_handle_handle (void * ptr)
+{
+  return (vtv_set_handle *) ((unsigned long) ptr & ~SET_HANDLE_HANDLE_BIT);
+}
+
+/* Given a vtable map variable, PTR, this function sets the bit that
+   says this is the second (or later) instance of a vtable map
+   variable.  */
+
+static inline vtv_set_handle_handle
+set_handle_handle (vtv_set_handle * ptr)
+{
+  return (vtv_set_handle_handle) ((unsigned long) ptr | SET_HANDLE_HANDLE_BIT);
+}
+
+/* Open error logging file, if not already open, and write vtable
+   verification failure messages (LOG_MSG) to the log file.  Also
+   generate a backtrace in the log file, if GENERATE_BACKTRACE is
+   set.  */
+
+static void
+log_error_message (const char *log_msg, bool generate_backtrace)
+{
+  if (vtv_failures_log_fd == -1)
+    vtv_failures_log_fd = vtv_open_log ("vtable_verification_failures.log");
+
+  if (vtv_failures_log_fd == -1)
+    return;
+
+  vtv_add_to_log (vtv_failures_log_fd, "%s", log_msg);
+
+  if (generate_backtrace)
+    {
+#define STACK_DEPTH 20
+      void *callers[STACK_DEPTH];
+      int actual_depth = backtrace (callers, STACK_DEPTH);
+      backtrace_symbols_fd (callers, actual_depth, vtv_failures_log_fd);
+    }
+}
+
+/* This routine initializes a set handle to a vtable set. It makes
+   sure that there is only one set handle for a particular set by
+   using a map from set name to pointer to set handle. Since there
+   will be multiple copies of the pointer to the set handle (one per
+   compilation unit that uses it), it makes sure to initialize all the
+   pointers to the set handle so that the set handle is unique. To
+   make this a little more efficient and avoid a level of indirection
+   in some cases, the first pointer to handle for a particular handle
+   becomes the handle itself and the other pointers will point to the
+   set handle.  This is the debug version of this function, so it
+   outputs extra debugging messages and logging.  SET_HANDLE_PTR is
+   the address of the vtable map variable, SET_SYMBOL_KEY is the hash
+   table key (containing the name of the map variable and the hash
+   value) and SIZE_HINT is a guess for the best initial size for the
+   set of vtable pointers that SET_HANDLE_POINTER will point to.  */
+
+void __VLTInitSetSymbolDebug (void **set_handle_ptr,
+			      const void *set_symbol_key, 
+			      size_t size_hint)
+{
+  VTV_DEBUG_ASSERT (set_handle_ptr);
+
+  if (vtv_symbol_unification_map == NULL)
+    {
+      /* TODO:  For now we have chosen 1024, but we need to come up with a
+	 better initial size for this.  */
+      vtv_symbol_unification_map = s2s::create (1024);
+      VTV_DEBUG_ASSERT(vtv_symbol_unification_map);
+    }
+
+  vtv_set_handle *handle_ptr = (vtv_set_handle *) set_handle_ptr;
+  vtv_symbol_key *symbol_key_ptr = (vtv_symbol_key *) set_symbol_key;
+
+  const s2s::value_type * map_value_ptr = 
+                              vtv_symbol_unification_map->get (symbol_key_ptr);
+  char buffer[200];
+  if (map_value_ptr == NULL)
+    {
+      if (*handle_ptr != NULL)
+	{
+	  snprintf (buffer, sizeof(buffer), 
+		    "*** Found non-NULL local set ptr %p missing for symbol"
+		    " %.*s",
+		    *handle_ptr, symbol_key_ptr->n, symbol_key_ptr->bytes);
+	  log_error_message (buffer, true);
+	  VTV_DEBUG_ASSERT (0);
+	}
+    }
+  else if (*handle_ptr != NULL && 
+           (handle_ptr != *map_value_ptr && 
+            ptr_from_set_handle_handle (*handle_ptr) != *map_value_ptr))
+    {
+      VTV_DEBUG_ASSERT (*map_value_ptr != NULL);
+      snprintf (buffer, sizeof(buffer), 
+		"*** Found diffence between local set ptr %p and set ptr %p"
+		"for symbol %.*s", 
+		*handle_ptr, *map_value_ptr, 
+		symbol_key_ptr->n, symbol_key_ptr->bytes);
+      log_error_message (buffer, true);
+      VTV_DEBUG_ASSERT (0);
+    }
+  else if (*handle_ptr == NULL)
+    {
+      /* Execution should not reach this point.  */
+    }
+
+  if (*handle_ptr != NULL)
+    {
+      if (!is_set_handle_handle (*set_handle_ptr))
+        handle_ptr = (vtv_set_handle *) set_handle_ptr;
+      else
+        handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
+      snprintf (buffer, sizeof (buffer), "  Calling resize with %p\n",
+		handle_ptr);
+      log_memory_protection_data (buffer);
+      vtv_sets::resize (size_hint, handle_ptr);
+      return;
+    }
+
+  VTV_DEBUG_ASSERT (*handle_ptr == NULL);
+  if (map_value_ptr != NULL)
+    {
+      if (*map_value_ptr == handle_ptr)
+	{
+	  snprintf (buffer, sizeof (buffer), "  Calling resize with %p\n",
+		    *map_value_ptr);
+	  log_memory_protection_data (buffer);
+	  vtv_sets::resize (size_hint, *map_value_ptr);
+	}
+      else
+        {
+          /* The one level handle to the set already exists. So, we
+             are adding one level of indirection here and we will
+             store a pointer to the one level handle here.  */
+
+          vtv_set_handle_handle * handle_handle_ptr = 
+                                           (vtv_set_handle_handle *)handle_ptr;
+          *handle_handle_ptr = set_handle_handle(*map_value_ptr);
+          VTV_DEBUG_ASSERT(*handle_handle_ptr != NULL);
+
+          /* The handle can itself be NULL if the set has only
+	     been initiazlied with size hint == 1. */
+	  snprintf (buffer, sizeof (buffer), "  Calling resize with %p\n",
+		    *map_value_ptr);
+	  log_memory_protection_data (buffer);
+          vtv_sets::resize (size_hint, *map_value_ptr);
+        }
+    }
+  else
+    {
+      /* We will create a new set. So, in this case handle_ptr is the
+         one level pointer to the set handle.  Create copy of map name
+         in case the memory where this comes from gets unmapped by
+         dlclose.  */
+      size_t map_key_len = symbol_key_ptr->n + sizeof (vtv_symbol_key);
+      void *map_key = VTV_malloc (map_key_len);
+
+      memcpy (map_key, symbol_key_ptr, map_key_len);
+
+      s2s::value_type *value_ptr;
+      vtv_symbol_unification_map = 
+        vtv_symbol_unification_map->find_or_add_key ((vtv_symbol_key *)map_key,
+						     &value_ptr);              
+      *value_ptr = handle_ptr;
+
+      /*  TODO: We should verify the return value. */
+      vtv_sets::create (size_hint, handle_ptr);
+      VTV_DEBUG_ASSERT (size_hint <= 1 || *handle_ptr != NULL);
+    }
+
+  if (debug_init)
+    {
+      if (init_log_fd == -1)
+	init_log_fd = vtv_open_log ("vtv_init.log");
+
+      vtv_add_to_log (init_log_fd, 
+		      "Init handle:%p for symbol:%.*s hash:%u size_hint:%lu"
+		      "number of symbols:%lu \n",
+		      set_handle_ptr, symbol_key_ptr->n,
+		      symbol_key_ptr->bytes, symbol_key_ptr->hash, size_hint, 
+		      vtv_symbol_unification_map->size ());
+    }
+}
+
+/* This function takes a the address of a vtable map variable
+   (SET_HANDLE_PTR), a VTABLE_PTR to add to the data set, the name of
+   the vtable map variable (SET_SYMBOL_NAME) and the name of the
+   vtable (VTABLE_NAME) being pointed to.  If the vtable map variable
+   is NULL it creates a new data set and initializes the variable,
+   otherwise it uses our symbol unification to find the right data
+   set; in either case it then adds the vtable pointer to the set.
+   The other two parameters are used for debugging information.  */
+
+void
+__VLTRegisterPairDebug (void **set_handle_ptr, const void *vtable_ptr,
+                        const char *set_symbol_name, const char *vtable_name)
+			
+{
+  VTV_DEBUG_ASSERT(set_handle_ptr != NULL);
+  /* set_handle_ptr can be NULL if the call to InitSetSymbol had a
+     size hint of 1.  */
+
+  int_vptr vtbl_ptr = (int_vptr) vtable_ptr;
+  VTV_DEBUG_ASSERT (vtv_symbol_unification_map != NULL);
+
+  vtv_set_handle *handle_ptr;
+  if (!is_set_handle_handle (*set_handle_ptr))
+    handle_ptr = (vtv_set_handle *) set_handle_ptr;
+  else
+    handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
+
+  /* TODO: We should verify the return value.  */
+  vtv_sets::insert (vtbl_ptr, handle_ptr);
+
+  if (debug_init)
+    {
+      if (init_log_fd == -1)
+	init_log_fd = vtv_open_log("vtv_init.log");
+
+      vtv_add_to_log(init_log_fd, 
+                     "Registered %s : %s (%p) 2 level deref = %s\n",
+		     set_symbol_name, vtable_name, vtbl_ptr, 
+                     is_set_handle_handle(*set_handle_ptr) ? "yes" : "no" );
+    }
+}
+
+/* This function is called from __VLTVerifyVtablePointerDebug; it
+   sends as much debugging information as it can to the error log
+   file, then calls __vtv_verify_fail.  SET_HANDLE_PTR is the pointer
+   to the set of valid vtable pointers, VTBL_PTR is the pointer that
+   was not found in the set, and DEBUG_MSG is the message to be
+   written to the log file before failing. n */
+
+static void
+__vtv_verify_fail_debug (void **set_handle_ptr, const void *vtbl_ptr, 
+                         const char *debug_msg)
+{
+  log_error_message (debug_msg, false);
+
+  /* Call the public interface in case it has been overwritten by
+     user.  */
+  __vtv_verify_fail (set_handle_ptr, vtbl_ptr);
+
+  log_error_message ("Returned from __vtv_verify_fail."
+                     " Secondary verification succeeded.\n", false);
+}
+
+/* This is the debug version of the verification function.  It takes
+   the address of a vtable map variable (SET_HANDLE_PTR) and a
+   VTABLE_PTR to validate, as well as the name of the vtable map
+   variable (SET_SYMBOL_NAME) and VTABLE_NAME, which are used for
+   debugging messages.  It checks to see if VTABLE_PTR is in the set
+   pointed to by SET_HANDLE_PTR.  If so, it returns VTABLE_PTR,
+   otherwise it calls __vtv_verify_fail, which usually logs error
+   messages and calls abort.  */
+
+const void *
+__VLTVerifyVtablePointerDebug (void **set_handle_ptr, const void *vtable_ptr,
+                               const char *set_symbol_name,
+			       const char *vtable_name)
+{
+  VTV_DEBUG_ASSERT (set_handle_ptr != NULL && *set_handle_ptr != NULL);
+  int_vptr vtbl_ptr = (int_vptr) vtable_ptr;
+
+  vtv_set_handle *handle_ptr;
+  if (!is_set_handle_handle (*set_handle_ptr))
+    handle_ptr = (vtv_set_handle *) set_handle_ptr;
+  else
+    handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
+
+  if (vtv_sets::contains (vtbl_ptr, handle_ptr))
+    {
+      if (debug_verify_vtable)
+        {
+          if (verify_vtable_log_fd == -1)
+            vtv_open_log ("vtv_verify_vtable.log");
+          vtv_add_to_log (verify_vtable_log_fd,
+			  "Verified %s %s value = %p\n",
+			  set_symbol_name, vtable_name, vtable_ptr);
+        }
+    }
+  else
+    {
+      /* We failed to find the vtable pointer in the set of valid
+	 pointers.  Log the error data and call the failure
+	 function.  */
+      snprintf (debug_log_message, sizeof (debug_log_message),
+		"Looking for %s in %s\n", vtable_name, set_symbol_name);
+      __vtv_verify_fail_debug (set_handle_ptr, vtable_ptr, debug_log_message);
+
+      /* Normally __vtv_verify_fail_debug will call abort, so we won't
+         execute the return below.  If we get this far, the assumption
+         is that the programmer has replaced __vtv_verify_fail_debug
+         with some kind of secondary verification AND this secondary
+         verification succeeded, so the vtable pointer is valid.  */
+    }
+
+  return vtable_ptr;
+}
+
+/* This routine initializes a set handle to a vtable set. It makes
+   sure that there is only one set handle for a particular set by
+   using a map from set name to pointer to set handle. Since there
+   will be multiple copies of the pointer to the set handle (one per
+   compilation unit that uses it), it makes sure to initialize all the
+   pointers to the set handle so that the set handle is unique. To
+   make this a little more efficient and avoid a level of indirection
+   in some cases, the first pointer to handle for a particular handle
+   becomes the handle itself and the other pointers will point to the
+   set handle.  SET_HANDLE_PTR is the address of the vtable map
+   variable, SET_SYMBOL_KEY is the hash table key (containing the name
+   of the map variable and the hash value) and SIZE_HINT is a guess
+   for the best initial size for the set of vtable pointers that
+   SET_HANDLE_POINTER will point to.*/
+
+void __VLTInitSetSymbol (void **set_handle_ptr, const void *set_symbol_key,
+			 size_t size_hint)
+{
+  vtv_set_handle *handle_ptr = (vtv_set_handle *) set_handle_ptr;
+  if (*handle_ptr != NULL)
+    {
+      if (!is_set_handle_handle (*set_handle_ptr))
+        handle_ptr = (vtv_set_handle *) set_handle_ptr;
+      else
+        handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
+      vtv_sets::resize (size_hint, handle_ptr);
+      return;
+    }
+
+  if (vtv_symbol_unification_map == NULL)
+    vtv_symbol_unification_map = s2s::create (1024);
+
+  vtv_symbol_key *symbol_key_ptr = (vtv_symbol_key *) set_symbol_key;
+  const s2s::value_type *map_value_ptr = 
+                              vtv_symbol_unification_map->get (symbol_key_ptr);
+
+  if (map_value_ptr != NULL)
+    {
+      if (*map_value_ptr == handle_ptr)
+	vtv_sets::resize (size_hint, *map_value_ptr);
+      else
+	{
+	  /* The one level handle to the set already exists. So, we
+	     are adding one level of indirection here and we will
+	     store a pointer to the one level pointer here.  */
+	  vtv_set_handle_handle *handle_handle_ptr = 
+	                                  (vtv_set_handle_handle *) handle_ptr;
+	  *handle_handle_ptr = set_handle_handle (*map_value_ptr);
+	  vtv_sets::resize (size_hint, *map_value_ptr);
+	}
+    }
+  else
+    {
+      /* We will create a new set. So, in this case handle_ptr is the
+         one level pointer to the set handle.  Create copy of map name
+         in case the memory where this comes from gets unmapped by
+         dlclose.  */
+      size_t map_key_len = symbol_key_ptr->n + sizeof (vtv_symbol_key);
+      void * map_key = VTV_malloc (map_key_len);
+      memcpy (map_key, symbol_key_ptr, map_key_len);
+
+      s2s::value_type * value_ptr;
+      vtv_symbol_unification_map = 
+	vtv_symbol_unification_map->find_or_add_key ((vtv_symbol_key *)map_key,
+						     &value_ptr);
+            
+      *value_ptr = handle_ptr;
+
+      /* TODO: We should verify the return value.  */
+      vtv_sets::create (size_hint, handle_ptr);
+    }
+}
+
+/* This function takes a the address of a vtable map variable
+   (SET_HANDLE_PTR) and a VTABLE_PTR.  If the vtable map variable is
+   NULL it creates a new data set and initializes the variable,
+   otherwise it uses our symbol unification to find the right data
+   set; in either case it then adds the vtable pointer to the set.  */
+
+void 
+__VLTRegisterPair (void **set_handle_ptr, const void *vtable_ptr)
+{
+  int_vptr vtbl_ptr = (int_vptr) vtable_ptr;
+
+  vtv_set_handle *handle_ptr;
+  if (!is_set_handle_handle (*set_handle_ptr))
+    handle_ptr = (vtv_set_handle *) set_handle_ptr;
+  else
+    handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
+
+  /* TODO: We should verify the return value.  */
+  vtv_sets::insert (vtbl_ptr, handle_ptr);
+}
+
+
+/* This is the main verification function.  It takes the address of a
+   vtable map variable (SET_HANDLE_PTR) and a VTABLE_PTR to validate.
+   It checks to see if VTABLE_PTR is in the set pointed to by
+   SET_HANDLE_PTR.  If so, it returns VTABLE_PTR, otherwise it calls
+   __vtv_verify_fail, which usually logs error messages and calls
+   abort.  Since this function gets called VERY frequently, it is
+   important for it to be as efficient as possible.  */
+
+const void *
+__VLTVerifyVtablePointer (void ** set_handle_ptr, const void * vtable_ptr)
+{
+  int_vptr vtbl_ptr = (int_vptr) vtable_ptr;
+
+  vtv_set_handle *handle_ptr;
+  if (!is_set_handle_handle (*set_handle_ptr))
+    handle_ptr = (vtv_set_handle *) set_handle_ptr;
+  else
+    handle_ptr = ptr_from_set_handle_handle (*set_handle_ptr);
+
+  if (!vtv_sets::contains (vtbl_ptr, handle_ptr))
+    {
+      __vtv_verify_fail ((void **) handle_ptr, vtable_ptr);
+      /* Normally __vtv_verify_fail will call abort, so we won't
+         execute the return below.  If we get this far, the assumption
+         is that the programmer has replaced __vtv_verify_fail with
+         some kind of secondary verification AND this secondary
+         verification succeeded, so the vtable pointer is valid.  */
+    }
+
+  return vtable_ptr;
+}
+
+/* This function calls __fortify_fail with a FAILURE_MSG and then
+   calls abort.  */
+
+void
+__vtv_really_fail (const char *failure_msg)
+{
+  __fortify_fail (failure_msg);
+
+  /* We should never get this far; __fortify_fail calls __libc_message
+     which prints out a back trace and a memory dump and then is
+     supposed to call abort, but let's play it safe anyway and call abort
+     ourselves.  */
+  abort ();
+}
+
+/* This function takes an error MSG, a vtable map variable
+   (DATA_SET_PTR) and a vtable pointer (VTBL_PTR).  It is called when
+   an attempt to verify VTBL_PTR with the set pointed to by
+   DATA_SET_PTR failed.  It outputs a failure message with the
+   addresses involved, and calls __vtv_really_fail.  */
+
+static void
+vtv_fail (const char *msg, void **data_set_ptr, const void *vtbl_ptr)
+{
+  char buffer[128];
+  int buf_len;
+  const char *format_str =
+                 "*** Unable to verify vtable pointer (%p) in set (%p) *** \n";
+
+  snprintf (buffer, sizeof (buffer), format_str, vtbl_ptr,
+            is_set_handle_handle(*data_set_ptr) ?
+              ptr_from_set_handle_handle (*data_set_ptr) :
+	      *data_set_ptr);
+  buf_len = strlen (buffer);
+  /*  Send this to to stderr.  */
+  write (2, buffer, buf_len);
+
+  if (!vtv_no_abort)
+    __vtv_really_fail (msg);
+}
+
+/* Send information about what we were trying to do when verification
+   failed to the error log, then call vtv_fail.  This function can be
+   overwritten/replaced by the user, to implement a secondary
+   verification function instead.  DATA_SET_PTR is the vtable map
+   variable used for the failed verification, and VTBL_PTR is the
+   vtable pointer that was not found in the set.  */
+
+void
+__vtv_verify_fail (void **data_set_ptr, const void *vtbl_ptr)
+{
+  char log_msg[256];
+  snprintf (log_msg, sizeof (log_msg), "Looking for vtable %p in set %p.\n",
+            vtbl_ptr,
+            is_set_handle_handle (*data_set_ptr) ?
+              ptr_from_set_handle_handle (*data_set_ptr) :
+              *data_set_ptr);
+  log_error_message (log_msg, false);
+
+  const char *format_str =
+            "*** Unable to verify vtable pointer (%p) in set (%p) *** \n";
+  snprintf (log_msg, sizeof (log_msg), format_str, vtbl_ptr, *data_set_ptr);
+  log_error_message (log_msg, false);
+  log_error_message ("  Backtrace: \n", true);
+
+  const char *fail_msg = "Potential vtable pointer corruption detected!!\n";
+  vtv_fail (fail_msg, data_set_ptr, vtbl_ptr);
+}
Index: libstdc++-v3/libsupc++/vtv_malloc.h
===================================================================
--- libstdc++-v3/libsupc++/vtv_malloc.h	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_malloc.h	(revision 0)
@@ -0,0 +1,49 @@
+// Copyright (C) 2012-2013
+// Free Software Foundation
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// GCC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef _VTV_MALLOC_H
+#define _VTV_MALLOC_H 1
+
+#include <stdlib.h>
+
+/* Alignment mask for any object returned by the VTV memory pool */
+#ifdef __LP64__
+#define VTV_ALIGNMENT_MASK (0x7)
+#else
+#define VTV_ALIGNMENT_MASK (0x3)
+#endif
+
+extern void VTV_malloc_init (void);
+
+extern void *VTV_malloc (size_t size);
+extern void VTV_free (void * ptr);
+
+
+extern void VTV_malloc_protect (void);
+extern void VTV_malloc_unprotect (void);
+
+extern void VTV_malloc_stats (void);
+extern void VTV_malloc_dump_stats (void);
+
+#endif /* vtv_malloc.h */
Index: libstdc++-v3/libsupc++/vtv_rts.h
===================================================================
--- libstdc++-v3/libsupc++/vtv_rts.h	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_rts.h	(revision 0)
@@ -0,0 +1,48 @@
+// Copyright (C) 2012-2013
+// Free Software Foundation
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// GCC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef _VTV_RTS_H
+#define _VTV_RTS_H 1
+
+#include <cstdlib>
+
+/* This prototype needs to be kept in sync with the compiler-
+   generated declaration in vtable-class-hierarchy.c.  */
+
+/* We could have used an enumeration here but it just makes it more
+   difficult for the compiler to generate a call to this.  */
+#define __VLTP_READ_ONLY  0
+#define __VLTP_READ_WRITE 1
+
+extern void __VLTChangePermission (int);
+extern void __VLTRegisterPair      (void **, const void *);
+extern void __VLTRegisterPairDebug (void **, const void *, const char *,
+				    const char *);
+extern const void *__VLTVerifyVtablePointer      (void **, const void *);
+extern const void *__VLTVerifyVtablePointerDebug (void **, const void *,
+						  const char *, const char *);
+extern void __VLTInitSetSymbolDebug (void **, const void *, std::size_t);
+extern void __VLTInitSetSymbol      (void **, const void *, std::size_t );
+
+#endif /* _VTV_RTS_H */
Index: libstdc++-v3/libsupc++/vtv_fail.h
===================================================================
--- libstdc++-v3/libsupc++/vtv_fail.h	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_fail.h	(revision 0)
@@ -0,0 +1,53 @@
+// Copyright (C) 2012-2013
+// Free Software Foundation
+//
+// This file is part of GCC.
+//
+// GCC is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// GCC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef _VTV_FAIL_H
+#define _VTV_FAIL_H 1
+
+/* __vtv_really_fail prints a backtrace and a memory dump, then calls
+  abort.  It is here for programmers to call, presumably from
+  __vtv_verify_fail, if they choose to overwrite the standard
+  __vtv_verify_fail with one of their own.  Programmers should NOT
+  attempt to rewrite __vtv_really_fail. */
+
+extern void
+__vtv_really_fail (const char *fail_msg) __attribute__ ((noreturn));
+
+/* __vtv_verify_fail is the function that gets called if the vtable
+  verification code discovers a vtable pointer that it cannot verify
+  as valid.  Normally __vtv_verify_fail calls __vtv_really_fail.
+  However programmers can write and link in their own version of
+  __vtv_verify_fail, if they wish to do some kind of secondary
+  verification, for example.  The main verification code assumes that
+  IF __vtv_verify_fail returns, then some kind of secondary
+  verification was done AND that the secondary verification succeeded,
+  i.e. that the vtable pointer is actually valid and ok to use.  If
+  the secondary verification fails, then __vtv_verify_fail should not
+  return.  */
+
+extern void
+__vtv_verify_fail (void **data_set_ptr, const void *vtbl_pointer)
+                                 __attribute__((visibility ("default")));
+
+#endif /* _VTV_FAIL_H */
Index: libstdc++-v3/libsupc++/vtv_map.h
===================================================================
--- libstdc++-v3/libsupc++/vtv_map.h	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_map.h	(revision 0)
@@ -0,0 +1,311 @@
+/* Copyright (C) 2012-2013
+   Free Software Foundation
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _VTV_MAP_H
+#define _VTV_MAP_H 1
+
+#include <string.h>
+#include <vtv_utils.h>
+
+inline uint64_t
+load8bytes (const void *p)
+{
+  uint64_t result;
+  memcpy (&result, p, 8);
+  return result;
+}
+
+/* Insert_only_hash_map maps keys to values.  The implementation is a
+   basic hash table with open addressing.  The keys are not "owned" by
+   the table; it only stores pointers to keys.  The key type is
+   specified below (see insert_only_hash_map::key_type) and is,
+   roughly speaking, a string of any length with the string length and
+   a hash code stored at the front.  The code here does not compute
+   any hash codes, but rather uses what's given.  */
+
+template<typename T, typename Alloc>
+class insert_only_hash_map
+  {
+    public:
+      typedef size_t size_type;
+      typedef T value_type;
+      typedef Alloc alloc_type;
+      enum { min_capacity = 4 };
+#if HASHMAP_STATS
+  enum { stats = true };
+#else
+  enum { stats = false };
+#endif
+
+  /* Keys are a byte string (up to 2^32 - 1 long) plus a uint32_t
+     that's used as a hash code.  The latter can encode arbitrary
+     information at the client's discretion, so, e.g., multiple keys
+     that are the same string still "differ" if the hash codes differ.
+     Keys are equal if the first 8 bytes are equal and the next n
+     bytes are equal.  */
+  struct key_type
+  {
+    uint32_t n;
+    uint32_t hash;
+    char bytes[0];
+
+    bool
+    equals (const key_type *k) const;
+  };
+
+  /* Create an empty map with a reasonable number of buckets for the
+     expected size.  Returns NULL if the allocator fails.  */
+
+  static insert_only_hash_map *
+  create (size_type expected_size);
+
+  /* The opposite of create().  Free the memory for the given map.  */
+
+  static void
+  destroy (insert_only_hash_map *m)
+  { Alloc().dealloc (m, m->size_in_bytes_); }
+
+  /* Return a map identical to this except that *k is mapped to v.
+     Typcially it's done by modifying this in place, but if a resize
+     is necessary then this is deallocated and a new map is returned.
+     Requires k to be non-NULL.  Does nothing and returns NULL if the
+     allocator fails.  */
+
+  insert_only_hash_map*
+  put (const key_type *k, const value_type &v)
+  { return this->put_internal (k, v, false); }
+
+  /* If *k is a key in this then set *v to point to the corresponding
+     value.  Otherwise, do the equivalent of insert(k, value_type())
+     and, if that succeeds, set *v to point to the inserted value.
+     Requires k to be non-NULL.  Does nothing and returns NULL if the
+     allocator fails.  Typically returns this, but will return a new
+     insert_only_hash_map if a resize occurs.  If the return value is
+     non-NULL, *v is set and it's valid until a resize of the map that
+     is the return value.  */
+
+  insert_only_hash_map *
+  find_or_add_key (const key_type *k, value_type **v);
+
+  /* Get the value corresponding to *k.  Returns NULL if there is
+     none.  Requires k to be non-NULL.  The return value is valid
+     until any resize.  */
+  const value_type *get (const key_type *k) const;
+
+  size_type
+  size () const
+  { return num_entries_; }
+
+  bool
+  empty () const
+  { return this->size () == 0; }
+
+  size_type
+  bucket_count () const
+  { return num_buckets_; }
+
+ private:
+  typedef std::pair <const key_type *, value_type> bucket_type;
+
+  insert_only_hash_map *put_internal (const key_type *, const value_type &,
+				      bool);
+
+  /* This function determines when to resize the table.  */
+  bool
+  is_too_full (size_type entries) const
+  { return entries > (this->bucket_count () * 0.7); }
+
+  /* Return a copy with double the number of buckets.  Returns NULL if
+     the allocator fails.  Otherwise, calls destroy (this).  */
+  insert_only_hash_map *destructive_copy ();
+
+ /* Must be a power of 2 not less than min_capacity. */
+  size_type num_buckets_; 
+  size_type num_entries_;
+  size_type size_in_bytes_;
+  bucket_type buckets[0];  /* Actual array size is num_buckets.  */
+};
+
+template <typename T, typename Alloc>
+insert_only_hash_map <T, Alloc> *
+insert_only_hash_map <T, Alloc>::create (size_type expected_size)
+{
+  size_t cap = min_capacity;
+  while (expected_size >= cap)
+    {
+      cap *= 2;
+    }
+  size_t size_in_bytes = sizeof (insert_only_hash_map <T, Alloc>)
+                                                  + cap * sizeof (bucket_type);
+  insert_only_hash_map <T, Alloc>* result =
+      static_cast <insert_only_hash_map <T, Alloc>*> (Alloc ()
+                                                       .alloc (size_in_bytes));
+  if (result != NULL)
+    {
+      result->size_in_bytes_ = size_in_bytes;
+      result->num_buckets_ = cap;
+      result->num_entries_ = 0;
+      memset (result->buckets, 0, cap * sizeof (bucket_type));
+    }
+  return result;
+}
+
+template <typename T, typename Alloc>
+insert_only_hash_map <T, Alloc>*
+insert_only_hash_map <T, Alloc>::destructive_copy ()
+{
+  insert_only_hash_map* copy = create (this->bucket_count ());
+  if (copy == NULL)
+    return NULL;
+  VTV_DEBUG_ASSERT (copy->bucket_count () == 2 * this->bucket_count ());
+  for (size_type i = 0; i < this->bucket_count (); i++)
+    if (this->buckets[i].first != NULL)
+      copy->put_internal (this->buckets[i].first, this->buckets[i].second,
+			  true);
+  VTV_DEBUG_ASSERT (copy->size () == this->size ());
+  destroy (this);
+  return copy;
+}
+
+template <typename T, typename Alloc>
+insert_only_hash_map <T, Alloc>*
+insert_only_hash_map <T, Alloc>::find_or_add_key (const key_type *k,
+						  value_type **v)
+{
+  /* Table size is always a power of 2.  */
+  const size_type mask = this->bucket_count () - 1;
+  size_type bucket_index = k->hash & mask;
+  size_type step = 1;
+  for (;;)
+    {
+      bucket_type &bucket = this->buckets[bucket_index];
+      if (bucket.first == NULL)
+        {
+          /* Key was not present. */
+          if (this->is_too_full (this->size () + 1))
+            {
+              insert_only_hash_map <T, Alloc>* result =
+		                                     this->destructive_copy ();
+              return result == NULL
+                  ? NULL
+                  : result->find_or_add_key (k, v);
+            }
+          else
+            {
+              bucket.first = k;
+              bucket.second = T ();
+              this->num_entries_++;
+              *v = &bucket.second;
+              return this;
+            }
+        }
+      else if (bucket.first->equals (k))
+        {
+          /* Key was present. */
+          *v = &bucket.second;
+          return this;
+        }
+      else
+        bucket_index = (bucket_index + step++) & mask;
+    }
+}
+
+template <typename T, typename Alloc>
+insert_only_hash_map <T, Alloc>*
+insert_only_hash_map <T, Alloc>::put_internal (
+				     const insert_only_hash_map::key_type *k,
+				     const insert_only_hash_map::value_type &v,
+				     bool unique_key_and_resize_not_needed)
+{
+  /* Table size is always a power of 2.  */
+  const size_type mask = this->bucket_count () - 1;
+  size_type bucket_index = k->hash & mask;
+  size_type step = 1;
+  for (;;)
+    {
+      bucket_type &bucket = this->buckets[bucket_index];
+      if (bucket.first == NULL)
+        {
+          /* Key was not present.  */
+          if (!unique_key_and_resize_not_needed
+              && this->is_too_full (this->size () + 1))
+            {
+              insert_only_hash_map <T, Alloc>* result =
+                                                     this->destructive_copy ();
+              return result == NULL
+                  ? NULL
+                  : result->put_internal (k, v, true);
+            }
+          else
+            {
+              bucket.first = k;
+              bucket.second = v;
+              this->num_entries_++;
+              return this;
+            }
+        }
+      else if (!unique_key_and_resize_not_needed && bucket.first->equals (k))
+        {
+          /* Key was present.  Just change the value.  */
+          bucket.second = v;
+          return this;
+        }
+      else
+        bucket_index = (bucket_index + step++) & mask;
+    }
+}
+
+template <typename T, typename Alloc>
+const typename insert_only_hash_map <T, Alloc>::value_type*
+insert_only_hash_map <T, Alloc>::get (const insert_only_hash_map::key_type *k)
+                                                                          const
+{
+  /* Table size is always a power of 2.  */
+  const size_type mask = this->bucket_count () - 1;
+  size_type bucket_index = k->hash & mask;
+  size_type step = 1;
+  for (;;)
+    {
+      const bucket_type &bucket = this->buckets[bucket_index];
+      if (bucket.first == NULL)
+        return NULL;
+      else if (bucket.first->equals (k))
+        return &bucket.second;
+      else
+        bucket_index = (bucket_index + step++) & mask;
+    }
+}
+
+template <typename T, typename Alloc>
+bool
+insert_only_hash_map <T, Alloc>::key_type::equals (
+             const typename insert_only_hash_map <T, Alloc>::key_type *k) const
+{
+  const char* x = reinterpret_cast <const char *> (k);
+  const char* y = reinterpret_cast <const char *> (this);
+  return (load8bytes (x) == load8bytes (y)
+          && memcmp (x + 8, y + 8, this->n) == 0);
+}
+
+#endif  /* _VTV_MAP_H  */
Index: libstdc++-v3/config/abi/pre/gnu.ver
===================================================================
--- libstdc++-v3/config/abi/pre/gnu.ver	(revision 196516)
+++ libstdc++-v3/config/abi/pre/gnu.ver	(working copy)
@@ -1336,6 +1336,19 @@ GLIBCXX_3.4.18 {
       std::__detail::_Prime_rehash_policy::*;
     };
 
+    # Virtual table verification symbols
+    _Z12__VLTprotectv;
+    _Z14__VLTunprotectv;
+    _Z18__VLTInitSetSymbol*;
+    _Z23__VLTInitSetSymbolDebug*;
+    _Z17__VLTRegisterPair*;
+    _Z22__VLTRegisterPairDebug*;
+    _Z21__VLTChangePermission*;
+    _Z24__VLTVerifyVtablePointer*;
+    _Z29__VLTVerifyVtablePointerDebug*;
+    _Z17__vtv_verify_fail*;
+    _Z17__vtv_really_fail*;
+
     # std::this_thread::__sleep_for
     _ZNSt11this_thread11__sleep_for*;
 
Index: libstdc++-v3/acinclude.m4
===================================================================
--- libstdc++-v3/acinclude.m4	(revision 196516)
+++ libstdc++-v3/acinclude.m4	(working copy)
@@ -2207,6 +2207,25 @@ AC_DEFUN([GLIBCXX_ENABLE_EXTERN_TEMPLATE
 ])
 
 dnl
+dnl Use vtable verification.
+dnl
+dnl --enable-vtable-verify defines _GLIBCXX_VTABLE_VERIFY to 1
+dnl --disable-vtable-verify defines _GLIBCXX_VTABLE_VERIFY to 0
+
+dnl  +  Usage:  GLIBCXX_ENABLE_VTABLE_VERIFY[(DEFAULT)]
+dnl       Where DEFAULT is `yes' or `no'.
+dnl
+AC_DEFUN([GLIBCXX_ENABLE_VTABLE_VERIFY], [
+
+  GLIBCXX_ENABLE(vtable-verify,$1,,[enable vtable verify])
+
+  AC_MSG_CHECKING([for vtable verify support])
+  AC_MSG_RESULT([$enable_vtable_verify])
+
+  GLIBCXX_CONDITIONAL(ENABLE_VTABLE_VERIFY, test $enable_vtable_verify = yes)
+])
+
+dnl
 dnl Check for parallel mode pre-requisites, including OpenMP support.
 dnl
 dnl  +  Usage:  GLIBCXX_ENABLE_PARALLEL
Index: configure.ac
===================================================================
--- configure.ac	(revision 196516)
+++ configure.ac	(working copy)
@@ -3157,10 +3157,10 @@ GCC_TARGET_TOOL(as, AS_FOR_TARGET, AS, [
 GCC_TARGET_TOOL(cc, CC_FOR_TARGET, CC, [gcc/xgcc -B$$r/$(HOST_SUBDIR)/gcc/])
 dnl see comments for CXX_FOR_TARGET_FLAG_TO_PASS
 GCC_TARGET_TOOL(c++, CXX_FOR_TARGET, CXX,
-		[gcc/xg++ -B$$r/$(HOST_SUBDIR)/gcc/ -nostdinc++ `if test -f $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags; then $(SHELL) $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags --build-includes; else echo -funconfigured-libstdc++-v3 ; fi` -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs],
+		[gcc/xg++ -B$$r/$(HOST_SUBDIR)/gcc/ -nostdinc++ `if test -f $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags; then $(SHELL) $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags --build-includes; else echo -funconfigured-libstdc++-v3 ; fi` -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/libsupc++/.libs],
 		c++)
 GCC_TARGET_TOOL(c++ for libstdc++, RAW_CXX_FOR_TARGET, CXX,
-		[gcc/xgcc -shared-libgcc -B$$r/$(HOST_SUBDIR)/gcc -nostdinc++ -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs],
+		[gcc/xgcc -shared-libgcc -B$$r/$(HOST_SUBDIR)/gcc -nostdinc++ -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs -L$$r/$(TARGET_SUBDIR)/libstdc++-v3/libsupc++/.libs],
 		c++)
 GCC_TARGET_TOOL(dlltool, DLLTOOL_FOR_TARGET, DLLTOOL, [binutils/dlltool])
 GCC_TARGET_TOOL(gcc, GCC_FOR_TARGET, , [gcc/xgcc -B$$r/$(HOST_SUBDIR)/gcc/])
