public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
@ 2013-02-25 19:31 Caroline Tice
  2013-02-25 19:53 ` Caroline Tice
  0 siblings, 1 reply; 9+ messages in thread
From: Caroline Tice @ 2013-02-25 19:31 UTC (permalink / raw)
  To: GCC Patches, libstdc++; +Cc: Diego Novillo, Luis Lozano, Bhaskar Janakiraman

Here are the latest changes to the vtable pointer verification patches
(again there are 3 patches: c++ front end, main gcc, and c++ runtime
library).  I think these address all the review comments I have
received so far.  This patch is the for C++ runtime library changes.
Please review these changes and let me know if they will be ok to
commit once stage 1 opens.

-- Caroline Tice
cmtice@google.com

2013-02-25  Caroline Tice  <cmtice@google.com>

	* config/abi/pre/gnu.ver:  Add vtable verification runtime functions to
	the list of globally visible symbols.
	* acinclude.m4: Add GLIBCXX_ENABLE_VTABLE_VERIFY option and comments.
	* configure (ENABLE_VTABLE_VERIFY_FALSE, ENABLE_VTABLE_VERIFY_TRUE,
	enable_vtable_verify):  New definitions.
	(predep_objects): Add vtv_start.o. if --enable-vtable-verify=yes was
	used.
	(postdep_objects):  Add vtv_end.o. if --enable-vtable-verify=yes was
	used.
	Add test for --enable-vtabkle-verify=yes. Add definitions for
	ENABLE_VTABLE_VERIFY_FALSE and ENABLE_VTABLE_VERIFY_TRUE.
	* src/Makefile.am (libvtv__la_LIBADD): Add definition, conditioned on
	ENABLE_VTABLE_VERIFY.
	(LIBVTV_FLAGS): Add definition, conditioned on ENABLE_VTABLE_VERIFY.
	(libstdc___la_LDFLAGS): Add 'Wl,-u_vtable_map_var_start,
	-u_vtable_map_var_end' if ENABLE_VTABLE_VERIFY is true.
	(CXXLINK):  Add LIBVTV_FLAGS.
	* src/Makefile.in: Regenerate from Makefile.am.
	* configure.ac (GLIBCXX_ENABLE_VTABLE_VERIFY): New definition.
	* libsupc++/vtv_utils.cc:  New file.
	* libsupc++/vtv_rts.h:  New file.
	* libsupc++/vtv_map.h:  New file.
	* libsupc++/vtv_set.h:  New file.
	* libsupc++/vtv_utils.h:  New file.
	* libsupc++/vtv_init.cc:  New file.
	* libsupc++/vtv_malloc.h:  New file.
	* libsupc++/Makefile.am (sources):  Add vtv_rts.cc, vtv_malloc.cc and
	vtv_utils.cc to the list.
	(vtv_init_sources, vtv_stubs_soruces, libvtv_init_la_sources,
	libvtv_stubs_la_sources):  New definitions.
	(toolexeclib_LTLIBRARIES):  Add libvtv_init.la and libvtv_stubs.la.
	* libsupc++/Makefile.in:  Regenerate from Makefile.am.
	* libsupc++/vtv_stubs.cc:  New file.
	* libsupc++/vtv_malloc.cc:  New file.
	* libsupc++/vtv_rts.cc:  New file.
	* libsupc++/vtv_fail.h:  New file.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-02-25 19:31 [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3) Caroline Tice
@ 2013-02-25 19:53 ` Caroline Tice
  2013-02-25 21:15   ` Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Caroline Tice @ 2013-02-25 19:53 UTC (permalink / raw)
  To: GCC Patches, libstdc++; +Cc: Diego Novillo, Luis Lozano, Bhaskar Janakiraman

[-- Attachment #1: Type: text/plain, Size: 2723 bytes --]

I got too excited about being done and forgot to attach the patch. :-(
 Sorry. Here it is.

-- Caroline
cmtice@google.com


On Mon, Feb 25, 2013 at 11:31 AM, Caroline Tice <cmtice@google.com> wrote:
> Here are the latest changes to the vtable pointer verification patches
> (again there are 3 patches: c++ front end, main gcc, and c++ runtime
> library).  I think these address all the review comments I have
> received so far.  This patch is the for C++ runtime library changes.
> Please review these changes and let me know if they will be ok to
> commit once stage 1 opens.
>
> -- Caroline Tice
> cmtice@google.com
>
> 2013-02-25  Caroline Tice  <cmtice@google.com>
>
>         * config/abi/pre/gnu.ver:  Add vtable verification runtime functions to
>         the list of globally visible symbols.
>         * acinclude.m4: Add GLIBCXX_ENABLE_VTABLE_VERIFY option and comments.
>         * configure (ENABLE_VTABLE_VERIFY_FALSE, ENABLE_VTABLE_VERIFY_TRUE,
>         enable_vtable_verify):  New definitions.
>         (predep_objects): Add vtv_start.o. if --enable-vtable-verify=yes was
>         used.
>         (postdep_objects):  Add vtv_end.o. if --enable-vtable-verify=yes was
>         used.
>         Add test for --enable-vtabkle-verify=yes. Add definitions for
>         ENABLE_VTABLE_VERIFY_FALSE and ENABLE_VTABLE_VERIFY_TRUE.
>         * src/Makefile.am (libvtv__la_LIBADD): Add definition, conditioned on
>         ENABLE_VTABLE_VERIFY.
>         (LIBVTV_FLAGS): Add definition, conditioned on ENABLE_VTABLE_VERIFY.
>         (libstdc___la_LDFLAGS): Add 'Wl,-u_vtable_map_var_start,
>         -u_vtable_map_var_end' if ENABLE_VTABLE_VERIFY is true.
>         (CXXLINK):  Add LIBVTV_FLAGS.
>         * src/Makefile.in: Regenerate from Makefile.am.
>         * configure.ac (GLIBCXX_ENABLE_VTABLE_VERIFY): New definition.
>         * libsupc++/vtv_utils.cc:  New file.
>         * libsupc++/vtv_rts.h:  New file.
>         * libsupc++/vtv_map.h:  New file.
>         * libsupc++/vtv_set.h:  New file.
>         * libsupc++/vtv_utils.h:  New file.
>         * libsupc++/vtv_init.cc:  New file.
>         * libsupc++/vtv_malloc.h:  New file.
>         * libsupc++/Makefile.am (sources):  Add vtv_rts.cc, vtv_malloc.cc and
>         vtv_utils.cc to the list.
>         (vtv_init_sources, vtv_stubs_soruces, libvtv_init_la_sources,
>         libvtv_stubs_la_sources):  New definitions.
>         (toolexeclib_LTLIBRARIES):  Add libvtv_init.la and libvtv_stubs.la.
>         * libsupc++/Makefile.in:  Regenerate from Makefile.am.
>         * libsupc++/vtv_stubs.cc:  New file.
>         * libsupc++/vtv_malloc.cc:  New file.
>         * libsupc++/vtv_rts.cc:  New file.
>         * libsupc++/vtv_fail.h:  New file.

[-- Attachment #2: fsf-vtable-verification.v5.runtime.patch --]
[-- Type: application/octet-stream, Size: 120530 bytes --]

Index: libstdc++-v3/config/abi/pre/gnu.ver
===================================================================
--- libstdc++-v3/config/abi/pre/gnu.ver	(revision 196266)
+++ 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 196266)
+++ libstdc++-v3/acinclude.m4	(working copy)
@@ -2202,6 +2202,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: libstdc++-v3/configure
===================================================================
--- libstdc++-v3/configure	(revision 196266)
+++ libstdc++-v3/configure	(working copy)
@@ -645,6 +645,8 @@ GLIBCXX_LDBL_COMPAT_FALSE
 GLIBCXX_LDBL_COMPAT_TRUE
 ENABLE_VISIBILITY_FALSE
 ENABLE_VISIBILITY_TRUE
+ENABLE_VTABLE_VERIFY_FALSE
+ENABLE_VTABLE_VERIFY_TRUE
 libtool_VERSION
 ENABLE_SYMVERS_SUN_FALSE
 ENABLE_SYMVERS_SUN_TRUE
@@ -862,6 +864,7 @@ enable_concept_checks
 enable_libstdcxx_debug_flags
 enable_libstdcxx_debug
 enable_cxx_flags
+enable_vtable_verify
 enable_fully_dynamic_string
 enable_extern_template
 with_python_dir
@@ -1570,6 +1573,8 @@ Optional Features:
                           enables visibility safe usage [default=yes]
   --enable-libstdcxx-threads
                           enable C++11 threads support [default=auto]
+  --enable-vtable-verify
+                          enable vtable verification feature [default=no]
   --enable-version-specific-runtime-libs
                           Specify that runtime libraries should be installed
                           in a compiler-specific directory
@@ -13206,8 +13211,14 @@ $as_echo "$ld_shlibs_CXX" >&6; }
     ## the running order or otherwise move them around unless you know exactly
     ## what you are doing...
     # Dependencies to place before and after the object being linked:
-predep_objects_CXX=
-postdep_objects_CXX=
+if test $enable_vtable_verify = yes; then
+  predep_objects_CXX="${glibcxx_builddir}/../libgcc/vtv_start.o"
+  postdep_objects_CXX="${glibcxx_builddir}/../libgcc/vtv_end.o"
+else
+  predep_objects_CXX=
+  postdep_objects_CXX=
+fi
+
 predeps_CXX=
 postdeps_CXX=
 compiler_lib_search_path_CXX=
@@ -17210,8 +17221,6 @@ else
   enable_libstdcxx_debug_flags="-gdwarf-4 -g3 -O0"
 fi
 
-
-
   # Option parsed, now set things appropriately
   DEBUG_FLAGS="$enable_libstdcxx_debug_flags"
 
@@ -17239,6 +17248,21 @@ fi
 $as_echo "$enable_libstdcxx_debug" >&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}: result: $enable_vtable_verify" >&5
+$as_echo "$enable_vtable_verify" >&6; }
 
 
   enable_parallel=no;
@@ -72849,6 +72873,13 @@ 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
 
 
 cat >confcache <<\_ACEOF
@@ -73217,6 +73248,10 @@ if test -z "${GLIBCXX_BUILD_DEBUG_TRUE}"
   as_fn_error "conditional \"GLIBCXX_BUILD_DEBUG\" 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_EXTERN_TEMPLATE_TRUE}" && test -z "${ENABLE_EXTERN_TEMPLATE_FALSE}"; then
   as_fn_error "conditional \"ENABLE_EXTERN_TEMPLATE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
Index: libstdc++-v3/src/Makefile.am
===================================================================
--- libstdc++-v3/src/Makefile.am	(revision 196266)
+++ libstdc++-v3/src/Makefile.am	(working copy)
@@ -66,12 +66,23 @@ 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
+else
 libstdc___la_LDFLAGS = \
 	-version-info $(libtool_VERSION) ${version_arg} -lm
+libvtv___la_LIBADD =
+LIBVTV_FLAGS =
+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
@@ -173,6 +184,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/Makefile.in
===================================================================
--- libstdc++-v3/src/Makefile.in	(revision 196266)
+++ libstdc++-v3/src/Makefile.in	(working copy)
@@ -366,8 +366,19 @@ 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
 
 libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS)
 
@@ -448,6 +459,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/configure.ac
===================================================================
--- libstdc++-v3/configure.ac	(revision 196266)
+++ libstdc++-v3/configure.ac	(working copy)
@@ -160,7 +160,7 @@ GLIBCXX_ENABLE_LONG_LONG([yes])
 GLIBCXX_ENABLE_WCHAR_T([yes])
 GLIBCXX_ENABLE_C99([yes])
 GLIBCXX_ENABLE_CONCEPT_CHECKS([no])
-GLIBCXX_ENABLE_DEBUG_FLAGS(["-gdwarf-4 -g3 -O0"])
+GLIBCXX_ENABLE_DEBUG_FLAGS(["-gdwarf-3 -g3 -O0"])
 GLIBCXX_ENABLE_DEBUG([no])
 GLIBCXX_ENABLE_PARALLEL([yes])
 GLIBCXX_ENABLE_CXX_FLAGS
@@ -168,6 +168,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_utils.cc
===================================================================
--- libstdc++-v3/libsupc++/vtv_utils.cc	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_utils.cc	(revision 0)
@@ -0,0 +1,106 @@
+/* Copyright (C) 2012
+   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);
+
+  /* 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_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
+// 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_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
+   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/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
+   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_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
+   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
+   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 functionsa (__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.h
===================================================================
--- libstdc++-v3/libsupc++/vtv_malloc.h	(revision 0)
+++ libstdc++-v3/libsupc++/vtv_malloc.h	(revision 0)
@@ -0,0 +1,49 @@
+// Copyright (C) 2012
+// 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++/Makefile.am
===================================================================
--- libstdc++-v3/libsupc++/Makefile.am	(revision 196266)
+++ 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 196266)
+++ 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_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
+   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_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
+   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++/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
+ 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 virtual 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
+   pointters 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 hel[p
+   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
+   __VLTVerifyVtablePoitner) 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 secttion 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: Meed to revisit this code for dlopen. It most probably
+         is not unlocking the protected vtable vars after for a 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_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
+// 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 */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-02-25 19:53 ` Caroline Tice
@ 2013-02-25 21:15   ` Jonathan Wakely
  2013-02-25 22:44     ` Caroline Tice
  2013-03-07 23:53     ` Caroline Tice
  0 siblings, 2 replies; 9+ messages in thread
From: Jonathan Wakely @ 2013-02-25 21:15 UTC (permalink / raw)
  To: Caroline Tice
  Cc: GCC Patches, libstdc++, Diego Novillo, Luis Lozano, Bhaskar Janakiraman

On 25 February 2013 19:52, Caroline Tice wrote:
> I got too excited about being done and forgot to attach the patch. :-(
>  Sorry. Here it is.

Some comments follow, mostly from reading the comments to understand
what this patch does, it's a really interesting feature!

The generated files (configure, */Makefile.in) don't need to be in the
patch and their ChangeLog entry can be simply "Regenerated"

Was configure regenerated of modified by hand? When regenerating it
with Autoconf 2.64 I get a different output.

I also get this warning when regenerating the configury bits:
src/Makefile.am:80: variable `libvtv___la_LIBADD' is defined but no program or
src/Makefile.am:80: library has `libvtv___la' as canonical name (possible typo)

The copyright dates should be updated to 2012-2013.

vtv_add_to_log in libstdc++-v3/libsupc++/vtv_utils.cc uses va_start
but the matching call to va_end is missing.

Am I right in thinking there's no danger of namespace pollution from
vtv_map.h etc. because those headers will never be included unless
explicitly requested by users?

I'm not sure what the rules are regarding flexible array members in
C++ (as it's an extension) but it looks like insert_only_hash_map is a
non-POD (formally, it has non-trivial initialization) but no
constructor or destructor runs for it, so formally the object's
lifetime never begins or ends, it is just a block of memory that gets
allocated, some bytes are set, then the memory is deallocated again.

The comments in libstdc++-v3/libsupc++/vtv_init.cc have a typo:

+/* 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 functionsa (__VLTunprotect and
s/functionsa/functions/

And in the comments in libstdc++-v3/libsupc++/vtv_rts.cc

+  The actual set of valid vtable pointers for a virtual class,
Should that be "polymorphic class" instead of "virtual class"?

Further on there are a few typos:

+   pointters for the class, so we wrote our own hashtable-based symbol
s/pointters/pointers/

+   libvtv_init.so is built from vtv_init.cc.  It is designed to hel[p
s/hel\[p/help/


+   __VLTVerifyVtablePoitner) with stub functions that do nothing.  If
s/Poitner/Pointer/

+   initialize any of these statics with a runtime call (for ex:
+   sysconf.
(Unclosed parenthesis)

+   the secttion offset and size, in conjunction with the data in INFO
s/secttion/section/

+      /* TODO: Meed to revisit this code for dlopen. It most probably
+         is not unlocking the protected vtable vars after for a load

s/Meed/Need/
s/after for a load/after a load/

I see a few TODO comments in the code, I assume the plan is to address
them eventually as time permits, rather than this being a code-drop
that becomes abandonware :-)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-02-25 21:15   ` Jonathan Wakely
@ 2013-02-25 22:44     ` Caroline Tice
  2013-02-25 22:49       ` Jonathan Wakely
  2013-03-07 23:53     ` Caroline Tice
  1 sibling, 1 reply; 9+ messages in thread
From: Caroline Tice @ 2013-02-25 22:44 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: GCC Patches, libstdc++, Diego Novillo, Luis Lozano, Bhaskar Janakiraman

On Mon, Feb 25, 2013 at 1:14 PM, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
> On 25 February 2013 19:52, Caroline Tice wrote:
>> I got too excited about being done and forgot to attach the patch. :-(
>>  Sorry. Here it is.
>
> Some comments follow, mostly from reading the comments to understand
> what this patch does, it's a really interesting feature!
>
> The generated files (configure, */Makefile.in) don't need to be in the
> patch and their ChangeLog entry can be simply "Regenerated"
>
> Was configure regenerated of modified by hand? When regenerating it
> with Autoconf 2.64 I get a different output.
>

I modified the configure file by hand.  I didn't realize it was
auto-generated.  :-(

> I also get this warning when regenerating the configury bits:
> src/Makefile.am:80: variable `libvtv___la_LIBADD' is defined but no program or
> src/Makefile.am:80: library has `libvtv___la' as canonical name (possible typo)


I was trying to define them as empty (this was in the else clause,
where "--enable-vtable-verify=yes" was not specified when doing the
original
configure.  I should probably remove libvtv___la_LIBADD from the else
clause altogether.
>
> The copyright dates should be updated to 2012-2013.
>
Ok.

> vtv_add_to_log in libstdc++-v3/libsupc++/vtv_utils.cc uses va_start
> but the matching call to va_end is missing.
>

Ok.

> Am I right in thinking there's no danger of namespace pollution from
> vtv_map.h etc. because those headers will never be included unless
> explicitly requested by users?

That should be correct.

>
> I'm not sure what the rules are regarding flexible array members in
> C++ (as it's an extension) but it looks like insert_only_hash_map is a
> non-POD (formally, it has non-trivial initialization) but no
> constructor or destructor runs for it, so formally the object's
> lifetime never begins or ends, it is just a block of memory that gets
> allocated, some bytes are set, then the memory is deallocated again.
>

I will go back and look at this again.  It's been a while since I
looked at that code.

> The comments in libstdc++-v3/libsupc++/vtv_init.cc have a typo:
>
> +/* 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 functionsa (__VLTunprotect and
> s/functionsa/functions/
>

I'll fix that.

> And in the comments in libstdc++-v3/libsupc++/vtv_rts.cc
>
> +  The actual set of valid vtable pointers for a virtual class,
> Should that be "polymorphic class" instead of "virtual class"?
>

Ok.

> Further on there are a few typos:
>
> +   pointters for the class, so we wrote our own hashtable-based symbol
> s/pointters/pointers/
>
> +   libvtv_init.so is built from vtv_init.cc.  It is designed to hel[p
> s/hel\[p/help/
>
>
> +   __VLTVerifyVtablePoitner) with stub functions that do nothing.  If
> s/Poitner/Pointer/
>
> +   initialize any of these statics with a runtime call (for ex:
> +   sysconf.
> (Unclosed parenthesis)
>
> +   the secttion offset and size, in conjunction with the data in INFO
> s/secttion/section/
>
> +      /* TODO: Meed to revisit this code for dlopen. It most probably
> +         is not unlocking the protected vtable vars after for a load
>
> s/Meed/Need/
> s/after for a load/after a load/
>
> I see a few TODO comments in the code, I assume the plan is to address
> them eventually as time permits, rather than this being a code-drop
> that becomes abandonware :-)

Yes.  They are things that we are planning on addressing but did not
seem worth holding up the patch for.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-02-25 22:44     ` Caroline Tice
@ 2013-02-25 22:49       ` Jonathan Wakely
  0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Wakely @ 2013-02-25 22:49 UTC (permalink / raw)
  To: Caroline Tice
  Cc: GCC Patches, libstdc++, Diego Novillo, Luis Lozano, Bhaskar Janakiraman

On 25 February 2013 22:43, Caroline Tice wrote:
> On Mon, Feb 25, 2013 at 1:14 PM, Jonathan Wakely wrote:
>>
>> Was configure regenerated of modified by hand? When regenerating it
>> with Autoconf 2.64 I get a different output.
>>
>
> I modified the configure file by hand.  I didn't realize it was
> auto-generated.  :-(

Yes, changes should go in configure.ac then configure gets regenerated
by running Autoconf 2.64's autoreconf tool.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-02-25 21:15   ` Jonathan Wakely
  2013-02-25 22:44     ` Caroline Tice
@ 2013-03-07 23:53     ` Caroline Tice
  2013-03-08  0:12       ` Jonathan Wakely
  1 sibling, 1 reply; 9+ messages in thread
From: Caroline Tice @ 2013-03-07 23:53 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: GCC Patches, libstdc++, Diego Novillo, Luis Lozano, Bhaskar Janakiraman

[-- Attachment #1: Type: text/plain, Size: 2614 bytes --]

Hello,

I believe this patch addresses all of your comments; I modified the
configure.ac files to generate the configures, and I fixed the
spelling mistakes in the comments.  I still get the warnings when
generating the Makefile.in files from the Makefile.am files, but the
resulting files seem to be correct, and I don't know how to make the
warnings go away.

Please review this patch and let me know if it will be ok to commit
when GCC opens up again.

-- Caroline Tice
cmtice@google.com

ChangeLog (toplevel):
2013-03-07  Caroline Tice  <cmtice@google.com>

	* configure.ac (CXX_FOR_TARGET,RAW_CXX_FOR_TARGET): Add
	libstdc++-v3/libsupc++/.libs to the library search path.
	* configure: Regenerate.


ChangeLog (libstdc++-v3):
2013-03-07  Caroline Tice  <cmtice@google.com>

	* configure: Regenerate.
	* src/Makefile.in: Regenerate.
	* src/c++98/Makefile.am (EXTRA_VTV_LDFLAGS, LIBVTV_FLAGS, VTV_CXXFLAGS):
	New definitions, conditioned on ENABLE_VTABLE_VERIFY.
	(AM_CXXFLAGS):  Add VTV_CXXFLAGS to list.
	(CXXLINK): Add LIBVTV_FLAGS.
	* src/c++11/Makefile.am: Ditto.
	* src/c++98/Makefile.in: Regenerate.
	* src/Makefile.am (libvtv__la_LIBADD): Add definition, conditioned on
	ENABLE_VTABLE_VERIFY.
	(LIBVTV_FLAGS): Add definition, conditioned on ENABLE_VTABLE_VERIFY.
	(libstdc___la_LDFLAGS): Add 'Wl,-u_vtable_map_var_start,
	-u_vtable_map_var_end' if ENABLE_VTABLE_VERIFY is true.
	(AM_CXXFLAGS): Add VTV_CXXFLAGS.
	(CXXLINK):  Add LIBVTV_FLAGS.
	* src/c++11/Makefile.in: Regenerate.
	* configure.ac (predep_objects_CXX): Add libgcc/vtv_start.o, if
	enable_vtable_verify is yes.
	(postdep_objects_CXX): Add libgcc/vtv_end.o if enable_vtable_verify is
	yes.
	(GLIBCXX_ENABLE_VTABLE_VERIFY): New definition.
	* libsupc++/vtv_set.h:  New file.
	* libsupc++/vtv_stubs.cc:  New file.
	* libsupc++/vtv_utils.cc:  New file.
	* libsupc++/vtv_utils.h:  New file.
	* libsupc++/vtv_init.cc:  New file.
	* libsupc++/vtv_malloc.cc:  New file.
	* libsupc++/Makefile.am (sources):  Add vtv_rts.cc, vtv_malloc.cc and
	vtv_utils.cc to the list.
	(vtv_init_sources, vtv_stubs_soruces, libvtv_init_la_sources,
	libvtv_stubs_la_sources):  New definitions.
	(toolexeclib_LTLIBRARIES):  Add libvtv_init.la and libvtv_stubs.la
	* libsupc++/Makefile.in:  Regenerate.
	* libsupc++/vtv_rts.cc:  New file.
	* libsupc++/vtv_malloc.h:  New file.
	* libsupc++/vtv_rts.h:  New file.
	* libsupc++/vtv_fail.h:  New file.
	* libsupc++/vtv_map.h:  New file.
	* config/abi/pre/gnu.ver:  Add vtable verification runtime functions to
	the list of globally visible symbols.
	* acinclude.m4: Add GLIBCXX_ENABLE_VTABLE_VERIFY option and comments.

[-- Attachment #2: fsf-vtable-verification.v6.runtime.patch --]
[-- Type: application/octet-stream, Size: 133544 bytes --]

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/])

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-03-07 23:53     ` Caroline Tice
@ 2013-03-08  0:12       ` Jonathan Wakely
  2013-03-08  8:13         ` Dave Korn
  2013-05-21  2:01         ` Benjamin De Kosnik
  0 siblings, 2 replies; 9+ messages in thread
From: Jonathan Wakely @ 2013-03-08  0:12 UTC (permalink / raw)
  To: Caroline Tice
  Cc: GCC Patches, libstdc++, Diego Novillo, Luis Lozano, Bhaskar Janakiraman

On 7 March 2013 23:53, Caroline Tice wrote:
> Hello,
>
> I believe this patch addresses all of your comments; I modified the
> configure.ac files to generate the configures, and I fixed the
> spelling mistakes in the comments.  I still get the warnings when
> generating the Makefile.in files from the Makefile.am files, but the
> resulting files seem to be correct, and I don't know how to make the
> warnings go away.
>
> Please review this patch and let me know if it will be ok to commit
> when GCC opens up again.

I'd like to know if someone with better automake skills than I have
can do anything about that warning, but otherwise that looks OK to me,
thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-03-08  0:12       ` Jonathan Wakely
@ 2013-03-08  8:13         ` Dave Korn
  2013-05-21  2:01         ` Benjamin De Kosnik
  1 sibling, 0 replies; 9+ messages in thread
From: Dave Korn @ 2013-03-08  8:13 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: Caroline Tice, GCC Patches, libstdc++,
	Diego Novillo, Luis Lozano, Bhaskar Janakiraman

On 08/03/2013 00:11, Jonathan Wakely wrote:
> On 7 March 2013 23:53, Caroline Tice wrote:

>> I believe this patch addresses all of your comments; I modified the
>> configure.ac files to generate the configures, and I fixed the
>> spelling mistakes in the comments.  I still get the warnings when
>> generating the Makefile.in files from the Makefile.am files, but the
>> resulting files seem to be correct, and I don't know how to make the
>> warnings go away.
>>
>> Please review this patch and let me know if it will be ok to commit
>> when GCC opens up again.
> 
> I'd like to know if someone with better automake skills than I have
> can do anything about that warning, but otherwise that looks OK to me,
> thanks.

  Looks like libvtv___la_LIBADD is still being defined in the else clause.
I'm also getting warnings for src/c++11/Makefile.am about EXTRA_VTV_LDFLAGS,
which may need renaming to avoid confusing automake:

src/c++11/Makefile.am:70: variable `EXTRA_VTV_LDFLAGS' is defined but no
program or
src/c++11/Makefile.am:70: library has `EXTRA_VTV' as canonical name (possible
typo)
src/c++98/Makefile.am:152: variable `EXTRA_VTV_LDFLAGS' is defined but no
program or
src/c++98/Makefile.am:152: library has `EXTRA_VTV' as canonical name (possible
typo)

  Also, it should generally contain only .lo and .la object and libraries to
link against.  From the automake manual:

> 8.3.7 _LIBADD, _LDFLAGS, and _LIBTOOLFLAGS
> As shown in previous sections, the ‘library_LIBADD’ variable should be used
> to list extra libtool objects (‘.lo’ files) or libtool libraries (‘.la’)
> to add to library. The ‘library_LDFLAGS’ variable is the place to list
> additional libtool linking flags, such as ‘-version-info’, ‘-static’, and a
> lot more.

  So putting a dir path into LIBADD and then concatenating -L and including it
wholesale in some other flag variable seems incorrect.

  Also, both that and the top-level change looks dubious to me.  The libtool
subdir isn't necessarily called '.libs' on all platforms, and you should never
need to reach into it(*).  Likewise LIBVTV_FLAGS.  Instead of adding
-lvtv_init or -lvtv_stubs to the linker flags, I think you're supposed to add
the corresponding .la files to the relevant LIBADD variable.  And w.r.t. the
top-level change, I think it may turn out to be unneeded altogether once the
libtool stuff is correct.

  It also looks odd to me that linker flags are being added into a CXXFLAGS
variable (EXTRA_VTV_LDFLAGS via VTV_CXXFLAGS) rather than the corresponding
LDFLAGS.

  I'm not a libtool expert, I've just been told to avoid similar dubious
practices in patches I've submitted in the past.

  And one minor nit, it is conventional not to include the generated files
(Makefile.in, configure) in patches.  They should autogenerate exactly the
same everywhere and it saves clutter.

    cheers,
      DaveK
-- 
(*) - I see a couple of cases have slipped through already, I think we should
avoid adding any more.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3)
  2013-03-08  0:12       ` Jonathan Wakely
  2013-03-08  8:13         ` Dave Korn
@ 2013-05-21  2:01         ` Benjamin De Kosnik
  1 sibling, 0 replies; 9+ messages in thread
From: Benjamin De Kosnik @ 2013-05-21  2:01 UTC (permalink / raw)
  To: Jonathan Wakely
  Cc: Caroline Tice, GCC Patches, libstdc++,
	Diego Novillo, Luis Lozano, Bhaskar Janakiraman


> I'd like to know if someone with better automake skills than I have
> can do anything about that warning, but otherwise that looks OK to me,
> thanks.

Hey dude. Caroline and I are working off-line on this. 

-benjamin

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-05-21  2:01 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-25 19:31 [PATCH, updated] Vtable pointer verification, runtime library changes (patch 3 of 3) Caroline Tice
2013-02-25 19:53 ` Caroline Tice
2013-02-25 21:15   ` Jonathan Wakely
2013-02-25 22:44     ` Caroline Tice
2013-02-25 22:49       ` Jonathan Wakely
2013-03-07 23:53     ` Caroline Tice
2013-03-08  0:12       ` Jonathan Wakely
2013-03-08  8:13         ` Dave Korn
2013-05-21  2:01         ` Benjamin De Kosnik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).