summaryrefslogtreecommitdiff
path: root/libvtv/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'libvtv/testsuite')
-rw-r--r--libvtv/testsuite/Makefile.am56
-rw-r--r--libvtv/testsuite/Makefile.in380
-rw-r--r--libvtv/testsuite/const_vtable.cc82
-rw-r--r--libvtv/testsuite/dataentry.cc37
-rw-r--r--libvtv/testsuite/dlopen.cc38
-rw-r--r--libvtv/testsuite/dlopen_mt.cc112
-rw-r--r--libvtv/testsuite/dup_name.cc60
-rw-r--r--libvtv/testsuite/environment-fail-32.s514
-rw-r--r--libvtv/testsuite/environment-fail-64.s425
-rw-r--r--libvtv/testsuite/environment.cc37
-rw-r--r--libvtv/testsuite/event-definitions.cc10
-rw-r--r--libvtv/testsuite/event-main.cc13
-rw-r--r--libvtv/testsuite/event-private.cc10
-rw-r--r--libvtv/testsuite/event-private.h7
-rw-r--r--libvtv/testsuite/event.h29
-rw-r--r--libvtv/testsuite/event.list1
-rw-r--r--libvtv/testsuite/field-test.cc94
-rw-r--r--libvtv/testsuite/mempool_negative.c196
-rw-r--r--libvtv/testsuite/mempool_positive.c196
-rw-r--r--libvtv/testsuite/nested_vcall_test.cc76
-rw-r--r--libvtv/testsuite/parts-test-extra-parts-views.cc16
-rw-r--r--libvtv/testsuite/parts-test-extra-parts-views.h14
-rw-r--r--libvtv/testsuite/parts-test-extra-parts.cc15
-rw-r--r--libvtv/testsuite/parts-test-extra-parts.h13
-rw-r--r--libvtv/testsuite/parts-test-main.cc37
-rw-r--r--libvtv/testsuite/parts-test-main.h15
-rw-r--r--libvtv/testsuite/parts-test.list1
-rw-r--r--libvtv/testsuite/povray-derived.cc72
-rw-r--r--libvtv/testsuite/register_pair.cc39
-rw-r--r--libvtv/testsuite/register_pair_inserts.cc46
-rw-r--r--libvtv/testsuite/register_pair_inserts_mt.cc100
-rw-r--r--libvtv/testsuite/register_pair_mt.cc102
-rw-r--r--libvtv/testsuite/replace-fail.cc11
-rw-r--r--libvtv/testsuite/so.cc93
-rw-r--r--libvtv/testsuite/temp_deriv.cc67
-rw-r--r--libvtv/testsuite/temp_deriv2.cc69
-rw-r--r--libvtv/testsuite/temp_deriv3.cc79
-rw-r--r--libvtv/testsuite/template-list-iostream.cc118
-rw-r--r--libvtv/testsuite/template-list.cc92
-rw-r--r--libvtv/testsuite/template-list2.cc44
-rw-r--r--libvtv/testsuite/thunk.cc35
-rw-r--r--libvtv/testsuite/thunk_vtable_map_attack.cc111
-rw-r--r--libvtv/testsuite/virtual_inheritance.cc46
43 files changed, 3608 insertions, 0 deletions
diff --git a/libvtv/testsuite/Makefile.am b/libvtv/testsuite/Makefile.am
new file mode 100644
index 00000000000..5f6ab0a037f
--- /dev/null
+++ b/libvtv/testsuite/Makefile.am
@@ -0,0 +1,56 @@
+## Makefile for the testsuite subdirectory of the VTV library.
+##
+## Copyright (C) 2013 Free Software Foundation, Inc.
+##
+## Process this file with automake to produce Makefile.in.
+##
+## This file is part of the Vtable Verification (VTV) Library. This
+## library 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.
+
+## This library 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.
+
+## You should have received a copy of the GNU General Public License
+## along with this library; see the file COPYING3. If not see
+## <http://www.gnu.org/licenses/>.
+
+AUTOMAKE_OPTIONS = nostdinc
+
+# Runs the testsuite via a script.
+
+# Create subdirectories.
+stamp-subdir:
+ if test ! -d lib64; then \
+ mkdir -p lib64; \
+ fi; \
+ if test ! -d lib32; then \
+ mkdir -p lib32; \
+ fi; \
+ echo `date` > stamp-subdir;
+
+
+testing_script=${libvtv_srcdir}/scripts/run-testsuite.sh
+check-script: ${testing_script} stamp-subdir
+ -@(chmod +x ${testing_script}; \
+ ${testing_script} ${libvtv_srcdir} ${libvtv_builddir})
+
+if ENABLE_VTABLE_VERIFY
+check-am:
+ $(MAKE) $(AM_MAKEFLAGS) check-script
+else
+check-am:
+endif
+
+.PHONY: check-script
+
+# By adding these files here, automake will remove them for 'make clean'
+CLEANFILES = *.out environment-fail-* stamp-* replace-fail-*
+
+# To remove directories.
+clean-local:
+ rm -rf lib*
diff --git a/libvtv/testsuite/Makefile.in b/libvtv/testsuite/Makefile.in
new file mode 100644
index 00000000000..2992a905142
--- /dev/null
+++ b/libvtv/testsuite/Makefile.in
@@ -0,0 +1,380 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = testsuite
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+ $(top_srcdir)/../config/depstand.m4 \
+ $(top_srcdir)/../config/lead-dot.m4 \
+ $(top_srcdir)/../config/libstdc++-raw-cxx.m4 \
+ $(top_srcdir)/../config/multi.m4 \
+ $(top_srcdir)/../config/override.m4 \
+ $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+ $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSTDCXX_RAW_CXX_CXXFLAGS = @LIBSTDCXX_RAW_CXX_CXXFLAGS@
+LIBSTDCXX_RAW_CXX_LDFLAGS = @LIBSTDCXX_RAW_CXX_LDFLAGS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XCFLAGS = @XCFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libtool_VERSION = @libtool_VERSION@
+libvtv_builddir = @libvtv_builddir@
+libvtv_srcdir = @libvtv_srcdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_noncanonical = @target_noncanonical@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
+toplevel_srcdir = @toplevel_srcdir@
+AUTOMAKE_OPTIONS = nostdinc
+testing_script = ${libvtv_srcdir}/scripts/run-testsuite.sh
+
+# By adding these files here, automake will remove them for 'make clean'
+CLEANFILES = *.out environment-fail-* stamp-* replace-fail-*
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign testsuite/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ clean-local distclean distclean-generic distclean-libtool dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Runs the testsuite via a script.
+
+# Create subdirectories.
+stamp-subdir:
+ if test ! -d lib64; then \
+ mkdir -p lib64; \
+ fi; \
+ if test ! -d lib32; then \
+ mkdir -p lib32; \
+ fi; \
+ echo `date` > stamp-subdir;
+check-script: ${testing_script} stamp-subdir
+ -@(chmod +x ${testing_script}; \
+ ${testing_script} ${libvtv_srcdir} ${libvtv_builddir})
+
+@ENABLE_VTABLE_VERIFY_TRUE@check-am:
+@ENABLE_VTABLE_VERIFY_TRUE@ $(MAKE) $(AM_MAKEFLAGS) check-script
+@ENABLE_VTABLE_VERIFY_FALSE@check-am:
+
+.PHONY: check-script
+
+# To remove directories.
+clean-local:
+ rm -rf lib*
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libvtv/testsuite/const_vtable.cc b/libvtv/testsuite/const_vtable.cc
new file mode 100644
index 00000000000..a0946abf4fe
--- /dev/null
+++ b/libvtv/testsuite/const_vtable.cc
@@ -0,0 +1,82 @@
+extern "C" int printf(const char *,...);
+struct V1 {
+ int v;
+ virtual int foo();
+ V1();
+ ~V1();
+};
+struct V2 : virtual V1 {
+ int v2;
+ virtual int foo();
+ V2();
+ ~V2();
+};
+struct C : virtual V1, virtual V2 {
+ int c;
+ virtual int foo();
+ C();
+ ~C();
+};
+
+struct B {
+ int b; };
+struct D : B, C {
+ int d;
+ virtual int bar();
+ D();
+ ~D();
+};
+extern "C" int printf(const char *,...);
+main()
+{
+ try {
+ D *d = new D;
+ delete d;
+ } catch (int) {
+ printf("Int caught\n");
+ }
+}
+
+int V1::foo() {
+ printf("V1::foo called\n"); return 1; }
+V1::V1() : v(5) {
+ printf("V1 called\n"); }
+V1::~V1() {
+ printf("~V1 called\n"); }
+
+int V2::foo() {
+ printf("V2::foo called\n"); return 1; }
+V2::V2() : v2(6) {
+ printf("V2 called\n"); }
+V2::~V2() {
+ printf("~V2 called\n"); }
+
+int C::foo() {
+ printf("C::foo called %d\n", c); return 1; }
+C::C() : c(7) {
+ printf("C called\n");
+ V1 *vv = this; vv->foo();
+ C *cp = dynamic_cast<C *>(vv);
+ if (this == cp) {
+ printf("PASSED this == cp\n");
+ } else {
+ printf("FAILED this != cp\n");
+ }
+}
+C::~C() {
+ printf("~C called\n");
+ V1 *vv = this; vv->foo();
+ C *cp = dynamic_cast<C *>(vv);
+ if (this == cp) {
+ printf("PASSED this == cp\n");
+ } else {
+ printf("FAILED this != cp\n");
+ }
+}
+
+int D::bar() {
+ printf("D::bar called\n"); return 1; }
+D::D() : d(8) {
+ printf("D called\n"); throw 5; }
+D::~D() {
+ printf("~D called\n"); }
diff --git a/libvtv/testsuite/dataentry.cc b/libvtv/testsuite/dataentry.cc
new file mode 100644
index 00000000000..fa027d5bc71
--- /dev/null
+++ b/libvtv/testsuite/dataentry.cc
@@ -0,0 +1,37 @@
+template<int patch_dim, int patch_space_dim>
+class DataOutInterface
+{
+ public:
+ virtual ~DataOutInterface() {}
+};
+
+template <int dof_handler_dim, int patch_dim, int patch_space_dim=patch_dim>
+class DataOut_DoFData : public DataOutInterface<patch_dim,patch_space_dim>
+{
+ public:
+ virtual ~DataOut_DoFData() {}
+
+class DataEntryBase {
+ public:
+ virtual ~DataEntryBase () {}
+};
+
+template <typename T>
+class DataEntry : public DataEntryBase
+{
+ public:
+ virtual ~DataEntry() {}
+};
+};
+
+template <typename T> void Destroy(T * p) __attribute__((noinline));
+template <typename T> void Destroy(T * p)
+{
+ delete p;
+}
+
+int main()
+{
+ DataOut_DoFData<3,3>::DataEntryBase * p = new DataOut_DoFData<3,3>::DataEntry<int>();
+ Destroy(p);
+}
diff --git a/libvtv/testsuite/dlopen.cc b/libvtv/testsuite/dlopen.cc
new file mode 100644
index 00000000000..4ffbe83acf7
--- /dev/null
+++ b/libvtv/testsuite/dlopen.cc
@@ -0,0 +1,38 @@
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+
+
+typedef void (*voidfn)(void);
+
+int failures = 0;
+
+void
+__vtv_verify_fail (void **data_set_ptr, const void *vtbl_pointer)
+{
+ failures++;
+ return;
+}
+
+
+int main()
+{
+ char so_name[] = "so0.so";
+ void * dlhandle = dlopen(so_name, RTLD_NOW);
+ if (!dlhandle)
+ {
+ fprintf(stderr, "dlopen %s error: %s\n", so_name, dlerror());
+ exit(1);
+ }
+ voidfn so_entry = (voidfn)dlsym(dlhandle, "so_entry_0");
+ if (!so_entry)
+ {
+ fprintf(stderr, "dlopen %s dlsym error: %s\n", so_name, dlerror());
+ exit(2);
+ }
+
+ so_entry();
+
+ dlclose(dlhandle);
+}
diff --git a/libvtv/testsuite/dlopen_mt.cc b/libvtv/testsuite/dlopen_mt.cc
new file mode 100644
index 00000000000..772e8a733ed
--- /dev/null
+++ b/libvtv/testsuite/dlopen_mt.cc
@@ -0,0 +1,112 @@
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+#include "vtv_utils.h"
+#include "vtv_rts.h"
+#include "pthread.h"
+
+#define NUM_REPEATS 10
+#define NUM_THREADS 10
+#define NUM_SOS 100
+#define NUM_SOS_PER_THREAD (NUM_SOS/NUM_THREADS)
+
+typedef void (*voidfn)(void);
+
+int failures = 0;
+
+void
+__vtv_verify_fail (void **data_set_ptr, const void *vtbl_pointer)
+{
+ failures++;
+ return;
+}
+
+
+void do_dlopen(int so_num)
+{
+ char so_name [sizeof("soxxx.so")];
+ sprintf(so_name, "so%d.so", so_num);
+ // printf("dl-opening %s\n", so_name);
+ void * dlhandle = dlopen(so_name, RTLD_NOW);
+ if (!dlhandle)
+ {
+ fprintf(stderr, "dlopen so:%s error: %s\n", so_name, dlerror());
+ exit(1);
+ }
+ char so_entry [sizeof("so_entry_xxx")];
+ sprintf(so_entry, "so_entry_%d", so_num);
+ voidfn so_entry_fn = (voidfn)dlsym(dlhandle, so_entry);
+ if (!so_entry_fn)
+ {
+ fprintf(stderr, "so:%s dlsym error: %s\n", so_name, dlerror());
+ exit(2);
+ }
+
+ so_entry_fn();
+
+ dlclose(dlhandle);
+}
+
+volatile int threads_completed_it = 0;
+volatile int current_wave = -1;
+
+void * do_dlopens(void * ptid)
+{
+ for (int k = 0; k < NUM_REPEATS; k++)
+ {
+
+ for (int i = 0; i < NUM_SOS_PER_THREAD; i++)
+ {
+ while (current_wave < (k*NUM_SOS_PER_THREAD + i)) /* from 0 to 99 */
+ ;
+
+ do_dlopen((NUM_SOS_PER_THREAD * *(int *)ptid) + i);
+
+ int old_value;
+ do {
+ old_value = threads_completed_it;
+ } while (!__sync_bool_compare_and_swap(&threads_completed_it, old_value, old_value + 1));
+
+ if (old_value == (NUM_THREADS - 1)) // Only one thread will do this.
+ {
+ threads_completed_it = 0;
+ printf("%c%d", 13, current_wave + 1);
+ fflush(stdout);
+ current_wave++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+int main()
+{
+ pthread_t thread_ids[NUM_THREADS];
+ int thread_nids[NUM_THREADS];
+
+ for (int t = 0; t < NUM_THREADS; t++ )
+ {
+ thread_nids[t] = t;
+ if (pthread_create(&thread_ids[t], NULL, do_dlopens, &thread_nids[t]) != 0)
+ {
+ printf("failed pthread_create\n");
+ exit(1);
+ }
+ }
+
+ current_wave = 0; // start the work on the other threads
+
+ for (int t = 0; t < NUM_THREADS; t++)
+ if (pthread_join(thread_ids[t], NULL) != 0)
+ {
+ printf("failed pthread_join\n");
+ exit(2);
+ }
+
+ printf("\n");
+
+ return 0;
+}
diff --git a/libvtv/testsuite/dup_name.cc b/libvtv/testsuite/dup_name.cc
new file mode 100644
index 00000000000..f0f1c2a8136
--- /dev/null
+++ b/libvtv/testsuite/dup_name.cc
@@ -0,0 +1,60 @@
+#include <assert.h>
+
+extern "C" int printf(const char *, ...);
+
+class Subscriptor
+{
+ public:
+
+ Subscriptor()
+ { counter = 1;}
+
+ virtual ~Subscriptor()
+ {
+ counter--;
+ assert(counter == 0);
+ }
+
+ private:
+ static int counter;
+};
+
+int Subscriptor::counter;
+
+template <typename number>
+class Polynomial : public Subscriptor
+{
+};
+
+class LagrangeEquidistant: public Polynomial<double>
+{
+};
+
+template <int value>
+class A
+{
+ public:
+ class Nested: public LagrangeEquidistant
+ {
+ };
+ A() { n = new Nested; }
+ ~A() { delete n; }
+ Subscriptor * n;
+};
+
+template<typename _Tp>
+inline void
+_MyDestroy(_Tp* __pointer)
+ { __pointer->~_Tp(); }
+
+int main()
+{
+ Subscriptor * s1 = new LagrangeEquidistant;
+ _MyDestroy(s1);
+ A<1> * a1 = new A<1>;
+ _MyDestroy(a1);
+ A<2> * a2 = new A<2>;
+ _MyDestroy(a2);
+
+ return 0;
+}
diff --git a/libvtv/testsuite/environment-fail-32.s b/libvtv/testsuite/environment-fail-32.s
new file mode 100644
index 00000000000..cac501652a7
--- /dev/null
+++ b/libvtv/testsuite/environment-fail-32.s
@@ -0,0 +1,514 @@
+ .file "environment.cc"
+ .section .text._ZN15EnvironmentImpl6GetVarEPKcPc,"axG",@progbits,_ZN15EnvironmentImpl6GetVarEPKcPc,comdat
+ .align 2
+ .weak _ZN15EnvironmentImpl6GetVarEPKcPc
+ .type _ZN15EnvironmentImpl6GetVarEPKcPc, @function
+_ZN15EnvironmentImpl6GetVarEPKcPc:
+.LFB0:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ movl $1, %eax
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE0:
+ .size _ZN15EnvironmentImpl6GetVarEPKcPc, .-_ZN15EnvironmentImpl6GetVarEPKcPc
+ .text
+ .align 2
+ .globl _ZN11EnvironmentD2Ev
+ .type _ZN11EnvironmentD2Ev, @function
+_ZN11EnvironmentD2Ev:
+.LFB2:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %ebx
+ subl $20, %esp
+ .cfi_offset 3, -12
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl 8(%ebp), %eax
+ movl _ZTV11Environment@GOT(%ebx), %edx
+ leal 8(%edx), %edx
+ movl %edx, (%eax)
+ movl $0, %eax
+ testl %eax, %eax
+ je .L3
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call _ZdlPv@PLT
+.L3:
+ addl $20, %esp
+ popl %ebx
+ .cfi_restore 3
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE2:
+ .size _ZN11EnvironmentD2Ev, .-_ZN11EnvironmentD2Ev
+ .globl _ZN11EnvironmentD1Ev
+ .set _ZN11EnvironmentD1Ev,_ZN11EnvironmentD2Ev
+ .align 2
+ .globl _ZN11EnvironmentD0Ev
+ .type _ZN11EnvironmentD0Ev, @function
+_ZN11EnvironmentD0Ev:
+.LFB4:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %ebx
+ subl $20, %esp
+ .cfi_offset 3, -12
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call _ZN11EnvironmentD1Ev@PLT
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call _ZdlPv@PLT
+ addl $20, %esp
+ popl %ebx
+ .cfi_restore 3
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE4:
+ .size _ZN11EnvironmentD0Ev, .-_ZN11EnvironmentD0Ev
+ .section .text._ZN11EnvironmentC2Ev,"axG",@progbits,_ZN11EnvironmentC5Ev,comdat
+ .align 2
+ .weak _ZN11EnvironmentC2Ev
+ .type _ZN11EnvironmentC2Ev, @function
+_ZN11EnvironmentC2Ev:
+.LFB8:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ call __x86.get_pc_thunk.cx
+ addl $_GLOBAL_OFFSET_TABLE_, %ecx
+ movl 8(%ebp), %eax
+ movl _ZTV11Environment@GOT(%ecx), %edx
+ leal 8(%edx), %edx
+ movl %edx, (%eax)
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE8:
+ .size _ZN11EnvironmentC2Ev, .-_ZN11EnvironmentC2Ev
+ .weak _ZN11EnvironmentC1Ev
+ .set _ZN11EnvironmentC1Ev,_ZN11EnvironmentC2Ev
+ .section .text._ZN15EnvironmentImplC2Ev,"axG",@progbits,_ZN15EnvironmentImplC5Ev,comdat
+ .align 2
+ .weak _ZN15EnvironmentImplC2Ev
+ .type _ZN15EnvironmentImplC2Ev, @function
+_ZN15EnvironmentImplC2Ev:
+.LFB10:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %ebx
+ subl $20, %esp
+ .cfi_offset 3, -12
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call _ZN11EnvironmentC2Ev@PLT
+ movl 8(%ebp), %eax
+ movl _ZTV15EnvironmentImpl@GOT(%ebx), %edx
+ leal 8(%edx), %edx
+ movl %edx, (%eax)
+ addl $20, %esp
+ popl %ebx
+ .cfi_restore 3
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE10:
+ .size _ZN15EnvironmentImplC2Ev, .-_ZN15EnvironmentImplC2Ev
+ .weak _ZN15EnvironmentImplC1Ev
+ .set _ZN15EnvironmentImplC1Ev,_ZN15EnvironmentImplC2Ev
+ .text
+ .align 2
+ .globl _ZN11Environment6CreateEv
+ .type _ZN11Environment6CreateEv, @function
+_ZN11Environment6CreateEv:
+.LFB5:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %esi
+ pushl %ebx
+ subl $16, %esp
+ .cfi_offset 6, -12
+ .cfi_offset 3, -16
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl $4, (%esp)
+ call _Znwj@PLT
+ movl %eax, %esi
+ movl $0, (%esi)
+ movl %esi, (%esp)
+ call _ZN15EnvironmentImplC1Ev@PLT
+ movl %esi, %eax
+ addl $16, %esp
+ popl %ebx
+ .cfi_restore 3
+ popl %esi
+ .cfi_restore 6
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE5:
+ .size _ZN11Environment6CreateEv, .-_ZN11Environment6CreateEv
+ .section .rodata
+.LC0:
+ .string "%p\n"
+ .text
+ .globl main
+ .type main, @function
+main:
+.LFB12:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %ebx
+ andl $-16, %esp
+ subl $32, %esp
+ .cfi_offset 3, -12
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl $0, 28(%esp)
+ call _ZN11Environment6CreateEv@PLT
+ movl %eax, 24(%esp)
+ movl 24(%esp), %eax
+ movl (%eax), %eax
+ movl %eax, 4(%esp)
+ leal _ZN4_VTVI11EnvironmentE12__vtable_mapE@GOTOFF(%ebx), %eax
+ movl %eax, (%esp)
+ call _Z24__VLTVerifyVtablePointerPPvPKv@PLT
+ addl $8, %eax
+ movl (%eax), %eax
+ movl 28(%esp), %edx
+ movl %edx, 8(%esp)
+ movl $0, 4(%esp)
+ movl 24(%esp), %edx
+ movl %edx, (%esp)
+ call *%eax
+ movl 24(%esp), %eax
+ movl %eax, 4(%esp)
+ leal .LC0@GOTOFF(%ebx), %eax
+ movl %eax, (%esp)
+ call printf@PLT
+ movl $0, %eax
+ movl -4(%ebp), %ebx
+ leave
+ .cfi_restore 5
+ .cfi_restore 3
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE12:
+ .size main, .-main
+ .weak _ZTV11Environment
+ .section .data.rel.ro._ZTV11Environment,"awG",@progbits,_ZTV11Environment,comdat
+ .align 8
+ .type _ZTV11Environment, @object
+ .size _ZTV11Environment, 20
+_ZTV11Environment:
+ .long 0
+ .long _ZTI11Environment
+ .long _ZN11EnvironmentD1Ev
+ .long _ZN11EnvironmentD0Ev
+ .long __cxa_pure_virtual
+ .weak _ZTV15EnvironmentImpl
+ .section .data.rel.ro._ZTV15EnvironmentImpl,"awG",@progbits,_ZTV15EnvironmentImpl,comdat
+ .align 8
+ .type _ZTV15EnvironmentImpl, @object
+ .size _ZTV15EnvironmentImpl, 20
+_ZTV15EnvironmentImpl:
+ .long 0
+ .long _ZTI15EnvironmentImpl
+ .long _ZN15EnvironmentImplD1Ev
+ .long _ZN15EnvironmentImplD0Ev
+ .long _ZN15EnvironmentImpl6GetVarEPKcPc
+ .section .text._ZN15EnvironmentImplD2Ev,"axG",@progbits,_ZN15EnvironmentImplD5Ev,comdat
+ .align 2
+ .weak _ZN15EnvironmentImplD2Ev
+ .type _ZN15EnvironmentImplD2Ev, @function
+_ZN15EnvironmentImplD2Ev:
+.LFB14:
+ .cfi_startproc
+ .cfi_personality 0x9b,DW.ref.__gxx_personality_v0
+ .cfi_lsda 0x1b,.LLSDA14
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %ebx
+ subl $20, %esp
+ .cfi_offset 3, -12
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl 8(%ebp), %eax
+ movl _ZTV15EnvironmentImpl@GOT(%ebx), %edx
+ leal 8(%edx), %edx
+ movl %edx, (%eax)
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+.LEHB0:
+ call _ZN11EnvironmentD2Ev@PLT
+.LEHE0:
+ movl $0, %eax
+ testl %eax, %eax
+ je .L19
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call _ZdlPv@PLT
+ jmp .L19
+.L18:
+ movl %eax, (%esp)
+.LEHB1:
+ call _Unwind_Resume@PLT
+.LEHE1:
+.L19:
+ addl $20, %esp
+ popl %ebx
+ .cfi_restore 3
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE14:
+ .globl __gxx_personality_v0
+ .section .gcc_except_table._ZN15EnvironmentImplD2Ev,"aG",@progbits,_ZN15EnvironmentImplD5Ev,comdat
+.LLSDA14:
+ .byte 0xff
+ .byte 0xff
+ .byte 0x1
+ .uleb128 .LLSDACSE14-.LLSDACSB14
+.LLSDACSB14:
+ .uleb128 .LEHB0-.LFB14
+ .uleb128 .LEHE0-.LEHB0
+ .uleb128 .L18-.LFB14
+ .uleb128 0
+ .uleb128 .LEHB1-.LFB14
+ .uleb128 .LEHE1-.LEHB1
+ .uleb128 0
+ .uleb128 0
+.LLSDACSE14:
+ .section .text._ZN15EnvironmentImplD2Ev,"axG",@progbits,_ZN15EnvironmentImplD5Ev,comdat
+ .size _ZN15EnvironmentImplD2Ev, .-_ZN15EnvironmentImplD2Ev
+ .weak _ZN15EnvironmentImplD1Ev
+ .set _ZN15EnvironmentImplD1Ev,_ZN15EnvironmentImplD2Ev
+ .section .text._ZN15EnvironmentImplD0Ev,"axG",@progbits,_ZN15EnvironmentImplD0Ev,comdat
+ .align 2
+ .weak _ZN15EnvironmentImplD0Ev
+ .type _ZN15EnvironmentImplD0Ev, @function
+_ZN15EnvironmentImplD0Ev:
+.LFB16:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %ebx
+ subl $20, %esp
+ .cfi_offset 3, -12
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call _ZN15EnvironmentImplD1Ev@PLT
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call _ZdlPv@PLT
+ addl $20, %esp
+ popl %ebx
+ .cfi_restore 3
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE16:
+ .size _ZN15EnvironmentImplD0Ev, .-_ZN15EnvironmentImplD0Ev
+ .weak _ZTS15EnvironmentImpl
+ .section .rodata._ZTS15EnvironmentImpl,"aG",@progbits,_ZTS15EnvironmentImpl,comdat
+ .type _ZTS15EnvironmentImpl, @object
+ .size _ZTS15EnvironmentImpl, 18
+_ZTS15EnvironmentImpl:
+ .string "15EnvironmentImpl"
+ .weak _ZTI15EnvironmentImpl
+ .section .data.rel.ro._ZTI15EnvironmentImpl,"awG",@progbits,_ZTI15EnvironmentImpl,comdat
+ .align 4
+ .type _ZTI15EnvironmentImpl, @object
+ .size _ZTI15EnvironmentImpl, 12
+_ZTI15EnvironmentImpl:
+ .long _ZTVN10__cxxabiv120__si_class_type_infoE+8
+ .long _ZTS15EnvironmentImpl
+ .long _ZTI11Environment
+ .weak _ZTI11Environment
+ .section .data.rel.ro._ZTI11Environment,"awG",@progbits,_ZTI11Environment,comdat
+ .align 4
+ .type _ZTI11Environment, @object
+ .size _ZTI11Environment, 8
+_ZTI11Environment:
+ .long _ZTVN10__cxxabiv117__class_type_infoE+8
+ .long _ZTS11Environment
+ .weak _ZTS11Environment
+ .section .rodata._ZTS11Environment,"aG",@progbits,_ZTS11Environment,comdat
+ .type _ZTS11Environment, @object
+ .size _ZTS11Environment, 14
+_ZTS11Environment:
+ .string "11Environment"
+ .hidden _ZN4_VTVI11EnvironmentE12__vtable_mapE
+ .weak _ZN4_VTVI11EnvironmentE12__vtable_mapE
+ .section .vtable_map_vars,"awG",@progbits,_ZN4_VTVI11EnvironmentE12__vtable_mapE,comdat
+ .align 4
+ .type _ZN4_VTVI11EnvironmentE12__vtable_mapE, @gnu_unique_object
+ .size _ZN4_VTVI11EnvironmentE12__vtable_mapE, 4
+_ZN4_VTVI11EnvironmentE12__vtable_mapE:
+ .zero 4
+ .hidden _ZN4_VTVI15EnvironmentImplE12__vtable_mapE
+ .weak _ZN4_VTVI15EnvironmentImplE12__vtable_mapE
+ .section .vtable_map_vars,"awG",@progbits,_ZN4_VTVI15EnvironmentImplE12__vtable_mapE,comdat
+ .align 4
+ .type _ZN4_VTVI15EnvironmentImplE12__vtable_mapE, @gnu_unique_object
+ .size _ZN4_VTVI15EnvironmentImplE12__vtable_mapE, 4
+_ZN4_VTVI15EnvironmentImplE12__vtable_mapE:
+ .zero 4
+ .section .data.rel.ro,"aw",@progbits
+ .align 4
+ .type __vptr_array_11Environment, @object
+ .size __vptr_array_11Environment, 8
+__vptr_array_11Environment:
+ .long _ZTV11Environment+8
+ .long _ZTV15EnvironmentImpl+8
+ .section .rodata
+ .align 4
+.LC1:
+ .string "&"
+ .string ""
+ .string ""
+ .ascii "\224\tl\022_ZN4_VTVI11EnvironmentE12__vtable_mapE"
+ .align 4
+.LC2:
+ .string "*"
+ .string ""
+ .string ""
+ .ascii "N\225\r\334_ZN4_VTVI15EnvironmentImplE12__vtable_mapE"
+ .text
+ .type _GLOBAL__sub_I.00099_environment.cc, @function
+_GLOBAL__sub_I.00099_environment.cc:
+.LFB17:
+ .cfi_startproc
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset 5, -8
+ movl %esp, %ebp
+ .cfi_def_cfa_register 5
+ pushl %ebx
+ subl $36, %esp
+ .cfi_offset 3, -12
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ leal __vptr_array_11Environment@GOTOFF(%ebx), %eax
+ movl %eax, 16(%esp)
+ movl $2, 12(%esp)
+ movl $2, 8(%esp)
+ leal .LC1@GOTOFF(%ebx), %eax
+ movl %eax, 4(%esp)
+ leal _ZN4_VTVI11EnvironmentE12__vtable_mapE@GOTOFF(%ebx), %eax
+ movl %eax, (%esp)
+ movl _ZTV15EnvironmentImpl@GOT(%ebx), %eax
+ leal 8(%eax), %eax
+ movl %eax, 12(%esp)
+ movl $1, 8(%esp)
+ leal .LC2@GOTOFF(%ebx), %eax
+ movl %eax, 4(%esp)
+ leal _ZN4_VTVI15EnvironmentImplE12__vtable_mapE@GOTOFF(%ebx), %eax
+ movl %eax, (%esp)
+ call _Z17__VLTRegisterPairPPvPKvjS2_@PLT
+ addl $36, %esp
+ popl %ebx
+ .cfi_restore 3
+ popl %ebp
+ .cfi_restore 5
+ .cfi_def_cfa 4, 4
+ ret
+ .cfi_endproc
+.LFE17:
+ .size _GLOBAL__sub_I.00099_environment.cc, .-_GLOBAL__sub_I.00099_environment.cc
+ .section .init_array.00099,"aw"
+ .align 4
+ .long _GLOBAL__sub_I.00099_environment.cc
+ .section .text.__x86.get_pc_thunk.cx,"axG",@progbits,__x86.get_pc_thunk.cx,comdat
+ .globl __x86.get_pc_thunk.cx
+ .hidden __x86.get_pc_thunk.cx
+ .type __x86.get_pc_thunk.cx, @function
+__x86.get_pc_thunk.cx:
+.LFB18:
+ .cfi_startproc
+ movl (%esp), %ecx
+ ret
+ .cfi_endproc
+.LFE18:
+ .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+ .globl __x86.get_pc_thunk.bx
+ .hidden __x86.get_pc_thunk.bx
+ .type __x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+.LFB19:
+ .cfi_startproc
+ movl (%esp), %ebx
+ ret
+ .cfi_endproc
+.LFE19:
+ .hidden DW.ref.__gxx_personality_v0
+ .weak DW.ref.__gxx_personality_v0
+ .section .data.DW.ref.__gxx_personality_v0,"awG",@progbits,DW.ref.__gxx_personality_v0,comdat
+ .align 4
+ .type DW.ref.__gxx_personality_v0, @object
+ .size DW.ref.__gxx_personality_v0, 4
+DW.ref.__gxx_personality_v0:
+ .long __gxx_personality_v0
+ .ident "GCC: (GNU) 4.9.0 20130616 (experimental)"
+ .section .note.GNU-stack,"",@progbits
diff --git a/libvtv/testsuite/environment-fail-64.s b/libvtv/testsuite/environment-fail-64.s
new file mode 100644
index 00000000000..d75db248b07
--- /dev/null
+++ b/libvtv/testsuite/environment-fail-64.s
@@ -0,0 +1,425 @@
+ .file "environment.cc"
+ .section .text._ZN15EnvironmentImpl6GetVarEPKcPc,"axG",@progbits,_ZN15EnvironmentImpl6GetVarEPKcPc,comdat
+ .align 2
+ .weak _ZN15EnvironmentImpl6GetVarEPKcPc
+ .type _ZN15EnvironmentImpl6GetVarEPKcPc, @function
+_ZN15EnvironmentImpl6GetVarEPKcPc:
+.LFB0:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ movq %rdi, -8(%rbp)
+ movq %rsi, -16(%rbp)
+ movq %rdx, -24(%rbp)
+ movl $1, %eax
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE0:
+ .size _ZN15EnvironmentImpl6GetVarEPKcPc, .-_ZN15EnvironmentImpl6GetVarEPKcPc
+ .text
+ .align 2
+ .globl _ZN11EnvironmentD2Ev
+ .type _ZN11EnvironmentD2Ev, @function
+_ZN11EnvironmentD2Ev:
+.LFB2:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+ movq %rdi, -8(%rbp)
+ movq -8(%rbp), %rax
+ movq _ZTV11Environment@GOTPCREL(%rip), %rdx
+ leaq 16(%rdx), %rdx
+ movq %rdx, (%rax)
+ movl $0, %eax
+ testl %eax, %eax
+ je .L3
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+ call _ZdlPv@PLT
+.L3:
+ leave
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE2:
+ .size _ZN11EnvironmentD2Ev, .-_ZN11EnvironmentD2Ev
+ .globl _ZN11EnvironmentD1Ev
+ .set _ZN11EnvironmentD1Ev,_ZN11EnvironmentD2Ev
+ .align 2
+ .globl _ZN11EnvironmentD0Ev
+ .type _ZN11EnvironmentD0Ev, @function
+_ZN11EnvironmentD0Ev:
+.LFB4:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+ movq %rdi, -8(%rbp)
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+ call _ZN11EnvironmentD1Ev@PLT
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+ call _ZdlPv@PLT
+ leave
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE4:
+ .size _ZN11EnvironmentD0Ev, .-_ZN11EnvironmentD0Ev
+ .section .text._ZN11EnvironmentC2Ev,"axG",@progbits,_ZN11EnvironmentC5Ev,comdat
+ .align 2
+ .weak _ZN11EnvironmentC2Ev
+ .type _ZN11EnvironmentC2Ev, @function
+_ZN11EnvironmentC2Ev:
+.LFB8:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ movq %rdi, -8(%rbp)
+ movq -8(%rbp), %rax
+ movq _ZTV11Environment@GOTPCREL(%rip), %rdx
+ leaq 16(%rdx), %rdx
+ movq %rdx, (%rax)
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE8:
+ .size _ZN11EnvironmentC2Ev, .-_ZN11EnvironmentC2Ev
+ .weak _ZN11EnvironmentC1Ev
+ .set _ZN11EnvironmentC1Ev,_ZN11EnvironmentC2Ev
+ .section .text._ZN15EnvironmentImplC2Ev,"axG",@progbits,_ZN15EnvironmentImplC5Ev,comdat
+ .align 2
+ .weak _ZN15EnvironmentImplC2Ev
+ .type _ZN15EnvironmentImplC2Ev, @function
+_ZN15EnvironmentImplC2Ev:
+.LFB10:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+ movq %rdi, -8(%rbp)
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+ call _ZN11EnvironmentC2Ev@PLT
+ movq -8(%rbp), %rax
+ movq _ZTV15EnvironmentImpl@GOTPCREL(%rip), %rdx
+ leaq 16(%rdx), %rdx
+ movq %rdx, (%rax)
+ leave
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE10:
+ .size _ZN15EnvironmentImplC2Ev, .-_ZN15EnvironmentImplC2Ev
+ .weak _ZN15EnvironmentImplC1Ev
+ .set _ZN15EnvironmentImplC1Ev,_ZN15EnvironmentImplC2Ev
+ .text
+ .align 2
+ .globl _ZN11Environment6CreateEv
+ .type _ZN11Environment6CreateEv, @function
+_ZN11Environment6CreateEv:
+.LFB5:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ pushq %rbx
+ subq $8, %rsp
+ .cfi_offset 3, -24
+ movl $8, %edi
+ call _Znwm@PLT
+ movq %rax, %rbx
+ movq $0, (%rbx)
+ movq %rbx, %rdi
+ call _ZN15EnvironmentImplC1Ev@PLT
+ movq %rbx, %rax
+ addq $8, %rsp
+ popq %rbx
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE5:
+ .size _ZN11Environment6CreateEv, .-_ZN11Environment6CreateEv
+ .section .rodata
+.LC0:
+ .string "%p\n"
+ .text
+ .globl main
+ .type main, @function
+main:
+.LFB12:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+ movq $0, -8(%rbp)
+ call _ZN11Environment6CreateEv@PLT
+ movq %rax, -16(%rbp)
+ movq -16(%rbp), %rax
+ movq (%rax), %rax
+ movq %rax, %rsi
+ leaq _ZN4_VTVI11EnvironmentE12__vtable_mapE(%rip), %rdi
+ call _Z24__VLTVerifyVtablePointerPPvPKv@PLT
+ addq $16, %rax
+ movq (%rax), %rax
+ movq -8(%rbp), %rdx
+ movq -16(%rbp), %rcx
+ movl $0, %esi
+ movq %rcx, %rdi
+ call *%rax
+ movq -16(%rbp), %rax
+ movq %rax, %rsi
+ leaq .LC0(%rip), %rdi
+ movl $0, %eax
+ call printf@PLT
+ movl $0, %eax
+ leave
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE12:
+ .size main, .-main
+ .weak _ZTV11Environment
+ .section .data.rel.ro._ZTV11Environment,"awG",@progbits,_ZTV11Environment,comdat
+ .align 32
+ .type _ZTV11Environment, @object
+ .size _ZTV11Environment, 40
+_ZTV11Environment:
+ .quad 0
+ .quad _ZTI11Environment
+ .quad _ZN11EnvironmentD1Ev
+ .quad _ZN11EnvironmentD0Ev
+ .quad __cxa_pure_virtual
+ .weak _ZTV15EnvironmentImpl
+ .section .data.rel.ro._ZTV15EnvironmentImpl,"awG",@progbits,_ZTV15EnvironmentImpl,comdat
+ .align 32
+ .type _ZTV15EnvironmentImpl, @object
+ .size _ZTV15EnvironmentImpl, 40
+_ZTV15EnvironmentImpl:
+ .quad 0
+ .quad _ZTI15EnvironmentImpl
+ .quad _ZN15EnvironmentImplD1Ev
+ .quad _ZN15EnvironmentImplD0Ev
+ .quad _ZN15EnvironmentImpl6GetVarEPKcPc
+ .section .text._ZN15EnvironmentImplD2Ev,"axG",@progbits,_ZN15EnvironmentImplD5Ev,comdat
+ .align 2
+ .weak _ZN15EnvironmentImplD2Ev
+ .type _ZN15EnvironmentImplD2Ev, @function
+_ZN15EnvironmentImplD2Ev:
+.LFB14:
+ .cfi_startproc
+ .cfi_personality 0x9b,DW.ref.__gxx_personality_v0
+ .cfi_lsda 0x1b,.LLSDA14
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+ movq %rdi, -8(%rbp)
+ movq -8(%rbp), %rax
+ movq _ZTV15EnvironmentImpl@GOTPCREL(%rip), %rdx
+ leaq 16(%rdx), %rdx
+ movq %rdx, (%rax)
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+.LEHB0:
+ call _ZN11EnvironmentD2Ev@PLT
+.LEHE0:
+ movl $0, %eax
+ testl %eax, %eax
+ je .L19
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+ call _ZdlPv@PLT
+ jmp .L19
+.L18:
+ movq %rax, %rdi
+.LEHB1:
+ call _Unwind_Resume@PLT
+.LEHE1:
+.L19:
+ leave
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE14:
+ .globl __gxx_personality_v0
+ .section .gcc_except_table._ZN15EnvironmentImplD2Ev,"aG",@progbits,_ZN15EnvironmentImplD5Ev,comdat
+.LLSDA14:
+ .byte 0xff
+ .byte 0xff
+ .byte 0x1
+ .uleb128 .LLSDACSE14-.LLSDACSB14
+.LLSDACSB14:
+ .uleb128 .LEHB0-.LFB14
+ .uleb128 .LEHE0-.LEHB0
+ .uleb128 .L18-.LFB14
+ .uleb128 0
+ .uleb128 .LEHB1-.LFB14
+ .uleb128 .LEHE1-.LEHB1
+ .uleb128 0
+ .uleb128 0
+.LLSDACSE14:
+ .section .text._ZN15EnvironmentImplD2Ev,"axG",@progbits,_ZN15EnvironmentImplD5Ev,comdat
+ .size _ZN15EnvironmentImplD2Ev, .-_ZN15EnvironmentImplD2Ev
+ .weak _ZN15EnvironmentImplD1Ev
+ .set _ZN15EnvironmentImplD1Ev,_ZN15EnvironmentImplD2Ev
+ .section .text._ZN15EnvironmentImplD0Ev,"axG",@progbits,_ZN15EnvironmentImplD0Ev,comdat
+ .align 2
+ .weak _ZN15EnvironmentImplD0Ev
+ .type _ZN15EnvironmentImplD0Ev, @function
+_ZN15EnvironmentImplD0Ev:
+.LFB16:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ subq $16, %rsp
+ movq %rdi, -8(%rbp)
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+ call _ZN15EnvironmentImplD1Ev@PLT
+ movq -8(%rbp), %rax
+ movq %rax, %rdi
+ call _ZdlPv@PLT
+ leave
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE16:
+ .size _ZN15EnvironmentImplD0Ev, .-_ZN15EnvironmentImplD0Ev
+ .weak _ZTS15EnvironmentImpl
+ .section .rodata._ZTS15EnvironmentImpl,"aG",@progbits,_ZTS15EnvironmentImpl,comdat
+ .align 16
+ .type _ZTS15EnvironmentImpl, @object
+ .size _ZTS15EnvironmentImpl, 18
+_ZTS15EnvironmentImpl:
+ .string "15EnvironmentImpl"
+ .weak _ZTI15EnvironmentImpl
+ .section .data.rel.ro._ZTI15EnvironmentImpl,"awG",@progbits,_ZTI15EnvironmentImpl,comdat
+ .align 16
+ .type _ZTI15EnvironmentImpl, @object
+ .size _ZTI15EnvironmentImpl, 24
+_ZTI15EnvironmentImpl:
+ .quad _ZTVN10__cxxabiv120__si_class_type_infoE+16
+ .quad _ZTS15EnvironmentImpl
+ .quad _ZTI11Environment
+ .weak _ZTI11Environment
+ .section .data.rel.ro._ZTI11Environment,"awG",@progbits,_ZTI11Environment,comdat
+ .align 16
+ .type _ZTI11Environment, @object
+ .size _ZTI11Environment, 16
+_ZTI11Environment:
+ .quad _ZTVN10__cxxabiv117__class_type_infoE+16
+ .quad _ZTS11Environment
+ .weak _ZTS11Environment
+ .section .rodata._ZTS11Environment,"aG",@progbits,_ZTS11Environment,comdat
+ .type _ZTS11Environment, @object
+ .size _ZTS11Environment, 14
+_ZTS11Environment:
+ .string "11Environment"
+ .hidden _ZN4_VTVI11EnvironmentE12__vtable_mapE
+ .weak _ZN4_VTVI11EnvironmentE12__vtable_mapE
+ .section .vtable_map_vars,"awG",@progbits,_ZN4_VTVI11EnvironmentE12__vtable_mapE,comdat
+ .align 8
+ .type _ZN4_VTVI11EnvironmentE12__vtable_mapE, @gnu_unique_object
+ .size _ZN4_VTVI11EnvironmentE12__vtable_mapE, 8
+_ZN4_VTVI11EnvironmentE12__vtable_mapE:
+ .zero 8
+ .hidden _ZN4_VTVI15EnvironmentImplE12__vtable_mapE
+ .weak _ZN4_VTVI15EnvironmentImplE12__vtable_mapE
+ .section .vtable_map_vars,"awG",@progbits,_ZN4_VTVI15EnvironmentImplE12__vtable_mapE,comdat
+ .align 8
+ .type _ZN4_VTVI15EnvironmentImplE12__vtable_mapE, @gnu_unique_object
+ .size _ZN4_VTVI15EnvironmentImplE12__vtable_mapE, 8
+_ZN4_VTVI15EnvironmentImplE12__vtable_mapE:
+ .zero 8
+ .section .data.rel.ro,"aw",@progbits
+ .align 16
+ .type __vptr_array_11Environment, @object
+ .size __vptr_array_11Environment, 16
+__vptr_array_11Environment:
+ .quad _ZTV11Environment+16
+ .quad _ZTV15EnvironmentImpl+16
+ .section .rodata
+ .align 8
+.LC1:
+ .string "&"
+ .string ""
+ .string ""
+ .ascii "\224\tl\022_ZN4_VTVI11EnvironmentE12__vtable_mapE"
+ .align 8
+.LC2:
+ .string "*"
+ .string ""
+ .string ""
+ .ascii "N\225\r\334_ZN4_VTVI15EnvironmentImplE12__vtable_mapE"
+ .text
+ .type _GLOBAL__sub_I.00099_environment.cc, @function
+_GLOBAL__sub_I.00099_environment.cc:
+.LFB17:
+ .cfi_startproc
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset 6, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register 6
+ leaq __vptr_array_11Environment(%rip), %r8
+ movl $2, %ecx
+ movl $2, %edx
+ leaq .LC1(%rip), %rsi
+ leaq _ZN4_VTVI11EnvironmentE12__vtable_mapE(%rip), %rdi
+ movq _ZTV15EnvironmentImpl@GOTPCREL(%rip), %rax
+ leaq 16(%rax), %rcx
+ movl $1, %edx
+ leaq .LC2(%rip), %rsi
+ leaq _ZN4_VTVI15EnvironmentImplE12__vtable_mapE(%rip), %rdi
+ call _Z17__VLTRegisterPairPPvPKvmS2_@PLT
+ popq %rbp
+ .cfi_def_cfa 7, 8
+ ret
+ .cfi_endproc
+.LFE17:
+ .size _GLOBAL__sub_I.00099_environment.cc, .-_GLOBAL__sub_I.00099_environment.cc
+ .section .init_array.00099,"aw"
+ .align 8
+ .quad _GLOBAL__sub_I.00099_environment.cc
+ .hidden DW.ref.__gxx_personality_v0
+ .weak DW.ref.__gxx_personality_v0
+ .section .data.DW.ref.__gxx_personality_v0,"awG",@progbits,DW.ref.__gxx_personality_v0,comdat
+ .align 8
+ .type DW.ref.__gxx_personality_v0, @object
+ .size DW.ref.__gxx_personality_v0, 8
+DW.ref.__gxx_personality_v0:
+ .quad __gxx_personality_v0
+ .ident "GCC: (GNU) 4.9.0 20130616 (experimental)"
+ .section .note.GNU-stack,"",@progbits
diff --git a/libvtv/testsuite/environment.cc b/libvtv/testsuite/environment.cc
new file mode 100644
index 00000000000..83adf53b601
--- /dev/null
+++ b/libvtv/testsuite/environment.cc
@@ -0,0 +1,37 @@
+
+extern "C" int printf(const char *, ...);
+
+class Environment {
+ public:
+ virtual ~Environment();
+
+ // Static factory method that returns the implementation that provide the
+ // appropriate platform-specific instance.
+ static Environment* Create();
+
+ // Gets an environment variable's value and stores it in |result|.
+ // Returns false if the key is unset.
+ virtual bool GetVar(const char* variable_name, char* result) = 0;
+};
+
+class EnvironmentImpl : public Environment {
+ public:
+ virtual bool GetVar(const char* variable_name, char* result) {
+ return true;
+ }
+};
+
+Environment::~Environment() {}
+
+// static
+Environment* Environment::Create() {
+ return new EnvironmentImpl();
+}
+
+int main()
+{
+ char * null = 0;
+ Environment * env = Environment::Create();
+ env->GetVar(0, null);
+ printf("%p\n", env);
+}
diff --git a/libvtv/testsuite/event-definitions.cc b/libvtv/testsuite/event-definitions.cc
new file mode 100644
index 00000000000..ba9efe11a4d
--- /dev/null
+++ b/libvtv/testsuite/event-definitions.cc
@@ -0,0 +1,10 @@
+#include "event.h"
+
+Event::Event()
+{
+}
+
+Event::~Event()
+{
+
+}
diff --git a/libvtv/testsuite/event-main.cc b/libvtv/testsuite/event-main.cc
new file mode 100644
index 00000000000..b0312848934
--- /dev/null
+++ b/libvtv/testsuite/event-main.cc
@@ -0,0 +1,13 @@
+#include "event-private.h"
+
+template<typename T> void derefIfNotNull(T* ptr)
+{
+ if (ptr != 0)
+ ptr->deref();
+}
+
+int main()
+{
+ Event * ev = new Event;
+ derefIfNotNull(ev);
+}
diff --git a/libvtv/testsuite/event-private.cc b/libvtv/testsuite/event-private.cc
new file mode 100644
index 00000000000..a27f4697a25
--- /dev/null
+++ b/libvtv/testsuite/event-private.cc
@@ -0,0 +1,10 @@
+#include "event-private.h"
+
+PrivateEvent::PrivateEvent()
+{
+}
+
+PrivateEvent::~PrivateEvent()
+{
+
+}
diff --git a/libvtv/testsuite/event-private.h b/libvtv/testsuite/event-private.h
new file mode 100644
index 00000000000..678ab5f68af
--- /dev/null
+++ b/libvtv/testsuite/event-private.h
@@ -0,0 +1,7 @@
+#include "event.h"
+
+class PrivateEvent: public Event {
+ public:
+ PrivateEvent();
+ ~PrivateEvent ();
+};
diff --git a/libvtv/testsuite/event.h b/libvtv/testsuite/event.h
new file mode 100644
index 00000000000..61e1d7c9172
--- /dev/null
+++ b/libvtv/testsuite/event.h
@@ -0,0 +1,29 @@
+class RefCountedBase {
+protected:
+ bool derefBase()
+ {
+ return true;
+ }
+};
+
+template<typename T> class RefCounted : public RefCountedBase {
+public:
+ void deref()
+ {
+ if (derefBase())
+ delete static_cast<T*>(this);
+ }
+
+protected:
+ // RefCounted() { }
+ ~RefCounted()
+ {
+ }
+};
+
+
+class Event : public RefCounted<Event> {
+ public:
+ Event();
+ virtual ~Event();
+};
diff --git a/libvtv/testsuite/event.list b/libvtv/testsuite/event.list
new file mode 100644
index 00000000000..83226fdd03f
--- /dev/null
+++ b/libvtv/testsuite/event.list
@@ -0,0 +1 @@
+event-main.cc event-definitions.cc event-private.cc \ No newline at end of file
diff --git a/libvtv/testsuite/field-test.cc b/libvtv/testsuite/field-test.cc
new file mode 100644
index 00000000000..b6f34bca02c
--- /dev/null
+++ b/libvtv/testsuite/field-test.cc
@@ -0,0 +1,94 @@
+// Compile with /home/llozano/local2/proj/vtable/gcc-root/usr/local/bin/g++ -m32 -fvtable-verify=std -fpic -rdynamic -Wl,-R,/home/llozano/local2/proj/vtable/gcc-root/usr/local/lib32:./lib32 -I/home/llozano/local2/proj/vtable/vt2/gcc-4_6-mobile-vtable-security//libstdc++-v3/libsupc++ temp_deriv.cc -O0 -ldl -lpthread -Wl,--whole-archive,-lvtv_init,--no-whole-archive,-z,relro -DTPID=0 -g
+// Look at assembly with: objdump -drl a.out
+
+#include <dlfcn.h>
+#include <assert.h>
+#include <stdlib.h>
+
+extern "C" int printf(const char *, ...);
+
+static int counter = 0;
+
+int i = TPID;
+struct base
+{
+ virtual void inc() { counter += i; }
+};
+
+struct derived: public base
+{
+ virtual void inc() { counter += (10*i); }
+};
+
+// We don't use this class. It is just here so that the
+// compiler does not devirtualize calls to derived::inc()
+struct derived2: public derived
+{
+ virtual void inc() { counter += (20*i); }
+};
+
+/*
+static base * bp = new base();
+static derived * dp = new derived();
+static base * dbp = new derived();
+*/
+
+struct my_struct {
+ base *bp;
+ derived *dp;
+ base *dbp;
+};
+
+typedef void * vtptr;
+
+vtptr get_vtptr(void * object_ptr)
+{
+ vtptr * object_vtptr_ptr = (vtptr *)object_ptr;
+ return *object_vtptr_ptr;
+}
+
+void set_vptr(void * object_ptr, vtptr vtp)
+{
+ vtptr * object_vtptr_ptr = (vtptr *)object_ptr;
+ *object_vtptr_ptr = vtp;
+}
+
+// Given 2 pointers to C++ objects (non PODs), exchange the pointers to vtable
+void exchange_vtptr(void * object1_ptr, void * object2_ptr)
+{
+ vtptr object1_vtptr = get_vtptr(object1_ptr);
+ vtptr object2_vtptr = get_vtptr(object2_ptr);
+ set_vptr(object1_ptr, object2_vtptr);
+ set_vptr(object2_ptr, object1_vtptr);
+}
+
+main()
+{
+ int prev_counter;
+
+ struct my_struct *my_obj = (struct my_struct *) malloc (sizeof (struct my_struct));
+
+ my_obj->bp = new base();
+ my_obj->dp = new derived ();
+ my_obj->dbp = new derived ();
+
+
+ counter = 0;
+ my_obj->bp->inc();
+ my_obj->dp->inc();
+ my_obj->dbp->inc();
+ assert(counter == (TPID + 10*TPID + 10*TPID));
+
+ prev_counter = counter;
+ printf("before ex bp vptr=%x dp vptr=%x\n", get_vtptr(my_obj->bp), get_vtptr(my_obj->dp));
+ exchange_vtptr(my_obj->bp, my_obj->dp);
+ printf("after ex bp vptr=%x dp vptr=%x\n", get_vtptr(my_obj->bp), get_vtptr(my_obj->dp));
+ my_obj->bp->inc(); // This one should not abort but it is calling the wrong member
+ assert(counter == (prev_counter + 10*TPID));
+ printf("Pass first attack! Expected!\n");
+ printf("TPDI=%d counter %d\n", TPID, counter);
+ my_obj->dp->inc();
+ printf("Pass second attack! SHOULD NOT BE HERE!\n");
+ printf("TPDI=%d counter %d\n", TPID, counter);
+ exit(1);
+}
diff --git a/libvtv/testsuite/mempool_negative.c b/libvtv/testsuite/mempool_negative.c
new file mode 100644
index 00000000000..50ed53109bd
--- /dev/null
+++ b/libvtv/testsuite/mempool_negative.c
@@ -0,0 +1,196 @@
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <stdio.h>
+#include <setjmp.h>
+
+#include "vtv_malloc.h"
+
+volatile static int signal_count = 0;
+
+sigjmp_buf before_segv;
+
+bool vtv_debug = false;
+
+static void
+handler(int sig, siginfo_t *si, void *unused)
+{
+ /*
+ printf("Got SIGSEGV at address: 0x%lx\n",
+ (long) si->si_addr);
+ */
+
+ signal_count++;
+ /* You are not supposed to longjmp out of a signal handler but it seems
+ to work for this test case and it simplifies it */
+ siglongjmp(before_segv, 1);
+ /* exit(1); */
+}
+
+/* Try to modify the memory pointed by "s" but dont actually change the values.
+ Assumes and verifies the memory to be modified is mprotected */
+void mempoke(void * s, size_t n)
+{
+ volatile char * p = (char *)s;
+ int ret;
+
+ signal_count = 0;
+ ret = sigsetjmp(before_segv, 1);
+ if (ret == 0)
+ p[0] = p[0];
+ /* printf("after first setjmp ret=%d\n", ret); */
+ assert(ret == 1 && signal_count == 1);
+
+ ret = sigsetjmp(before_segv, 1);
+ if (ret == 0)
+ p[n - 1] = p[n - 1];
+ /* printf("after second setjmp ret=%d\n", ret); */
+ assert(ret == 1 && signal_count == 2);
+}
+
+int main()
+{
+ char * ptr;
+ int size;
+
+ /* Set up handler for SIGSEGV. */
+ struct sigaction sa;
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = handler;
+ if (sigaction(SIGSEGV, &sa, NULL) == -1)
+ assert(0);
+
+ __vtv_malloc_init();
+
+ size = 10;
+
+ /* Verify not writable after unprotect */
+ __vtv_malloc_unprotect();
+ ptr = (char *)__vtv_malloc(size);
+ memset(ptr, 'a', size);
+ __vtv_malloc_protect();
+ mempoke(ptr, size);
+ __vtv_free(ptr);
+
+ /* verify not-writable after protect, unprotect */
+ __vtv_malloc_unprotect();
+ ptr = (char *)__vtv_malloc(size);
+ memset(ptr, 'a', size);
+ __vtv_malloc_protect();
+ __vtv_malloc_unprotect();
+ memset(ptr, 'a', size);
+ assert(ptr[size - 1] == 'a');
+ __vtv_malloc_protect();
+ assert(ptr[size - 1] == 'a');
+ mempoke(ptr,size);
+ __vtv_free(ptr);
+
+ /* Allocate a bunch of small objects.
+ Make sure the alignment is correct.
+ Verify data has not been corrupted.
+ Make sure the data cannot modified */
+ {
+ int s;
+ for (s = 3; s < 28; s += 3)
+ {
+ size = s;
+ {
+ int i;
+ #define ITERS 1000
+ char * ptrs[ITERS];
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS; i++)
+ {
+ ptr = (char *)__vtv_malloc(size);
+ assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
+ memset(ptr, (i & 127), size);
+ assert(ptr[size - 1] == (i & 127));
+ ptrs[i] = ptr;
+ }
+ __vtv_malloc_protect();
+
+ for (i = 0; i < ITERS; i++)
+ mempoke(ptrs[i], size);
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS; i++)
+ __vtv_free(ptrs[i]);
+ __vtv_malloc_protect();
+ }
+ }
+ }
+
+ /* Allocate a bunch of medium size objects.
+ Make sure the alignment is correct.
+ Verify data has not been corrupted.
+ Try to modify the data to verify everything gets unprotected */
+ {
+ int s;
+ for (s = 501; s < 2500; s += 91)
+ {
+ size = s;
+ {
+ int i;
+ #define ITERS2 100
+ char * ptrs[ITERS2];
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS2; i++)
+ {
+
+ ptr = (char *)__vtv_malloc(size);
+ assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
+ memset(ptr, i & 127, size);
+ assert(ptr[size - 1] == i & 127);
+ ptrs[i] = ptr;
+ }
+ __vtv_malloc_protect();
+
+ for (i = 0; i < ITERS2; i++)
+ mempoke(ptrs[i], size);
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS2; i++)
+ __vtv_free(ptrs[i]);
+ __vtv_malloc_protect();
+ }
+ }
+ }
+
+ /* Allocate a bunch of medium size objects. Make sure the alignment is correct */
+ {
+ int s;
+ for (s = 3001; s < 15000; s += 307)
+ {
+ size = s;
+ {
+ int i;
+ #define ITERS3 50
+ char * ptrs[ITERS3];
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS3; i++)
+ {
+ ptr = (char *)__vtv_malloc(size);
+ assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
+ memset(ptr, i & 127, size);
+ assert(ptr[size - 1] == i & 127);
+ ptrs[i] = ptr;
+ }
+ __vtv_malloc_protect();
+
+ for (i = 0; i < ITERS3; i++)
+ mempoke(ptrs[i], size);
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS3; i++)
+ __vtv_free(ptrs[i]);
+ __vtv_malloc_protect();
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/libvtv/testsuite/mempool_positive.c b/libvtv/testsuite/mempool_positive.c
new file mode 100644
index 00000000000..511f50a1040
--- /dev/null
+++ b/libvtv/testsuite/mempool_positive.c
@@ -0,0 +1,196 @@
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "vtv_malloc.h"
+
+bool vtv_debug = false;
+
+static void
+handler(int sig, siginfo_t *si, void *unused)
+{
+ printf("Got SIGSEGV at address: 0x%lx\n",
+ (long) si->si_addr);
+ exit(1);
+}
+
+int memchk(const void * s, int c, size_t n)
+{
+ const char * p = (const char *)s;
+ for (; p < ((char *)s + n); p++)
+ if (*p != c)
+ return 1;
+ return 0;
+}
+
+int main()
+{
+ char * ptr;
+ int size;
+
+ /* Set up handler for SIGSEGV. In this test case, we should never hit any SIGSEGV */
+ struct sigaction sa;
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = handler;
+ if (sigaction(SIGSEGV, &sa, NULL) == -1)
+ assert(0);
+
+ __vtv_malloc_init();
+
+ size = 10;
+
+ /* Verify simple allocation and deallocation */
+ __vtv_malloc_unprotect();
+ ptr = (char *)__vtv_malloc(size);
+ __vtv_malloc_protect();
+ __vtv_free(ptr);
+
+ /* Verify writable after unprotect */
+ __vtv_malloc_unprotect();
+ ptr = (char *)__vtv_malloc(size);
+ memset(ptr, 'a', size);
+ __vtv_malloc_protect();
+ __vtv_free(ptr);
+
+ /* verify readable after protect */
+ __vtv_malloc_unprotect();
+ ptr = (char *)__vtv_malloc(size);
+ memset(ptr, 'a', size);
+ __vtv_malloc_protect();
+ assert(ptr[size - 1] == 'a');
+ __vtv_free(ptr);
+
+ /* verify writable after protect, unprotect */
+ __vtv_malloc_unprotect();
+ ptr = (char *)__vtv_malloc(size);
+ memset(ptr, 'a', size);
+ __vtv_malloc_protect();
+ __vtv_malloc_unprotect();
+ memset(ptr, 'a', size);
+ assert(ptr[size - 1] == 'a');
+ __vtv_malloc_protect();
+ assert(ptr[size - 1] == 'a');
+ __vtv_free(ptr);
+
+ /* Allocate a bunch of small objects.
+ Make sure the alignment is correct.
+ Verify data has not been corrupted.
+ Try to modify the data to verify everything gets unprotected */
+ {
+ int s;
+ for (s = 3; s < 28; s += 3)
+ {
+ size = s;
+ {
+ int i;
+ #define ITERS 1000
+ char * ptrs[ITERS];
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS; i++)
+ {
+ ptr = (char *)__vtv_malloc(size);
+ assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
+ memset(ptr, (i & 127), size);
+ assert(ptr[size - 1] == (i & 127));
+ ptrs[i] = ptr;
+ }
+ __vtv_malloc_protect();
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS; i++)
+ {
+ if (memchk(ptrs[i], i & 127, size) != 0)
+ assert(0);
+ memset(ptrs[i], (i + 1) & 127, size);
+ if (memchk(ptrs[i], (i + 1) & 127, size) != 0)
+ assert(0);
+ __vtv_free(ptrs[i]);
+ }
+ __vtv_malloc_protect();
+ }
+ }
+ }
+
+ /* Allocate a bunch of medium size objects.
+ Make sure the alignment is correct.
+ Verify data has not been corrupted.
+ Try to modify the data to verify everything gets unprotected */
+ {
+ int s;
+ for (s = 501; s < 2500; s += 91)
+ {
+ size = s;
+ {
+ int i;
+ #define ITERS2 100
+ char * ptrs[ITERS2];
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS2; i++)
+ {
+
+ ptr = (char *)__vtv_malloc(size);
+ assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
+ memset(ptr, i & 127, size);
+ assert(ptr[size - 1] == i & 127);
+ ptrs[i] = ptr;
+ }
+ __vtv_malloc_protect();
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS2; i++)
+ {
+ if (memchk(ptrs[i], i & 127, size) != 0)
+ assert(0);
+ memset(ptrs[i], (i + 1) & 127, size);
+ if (memchk(ptrs[i], (i + 1) & 127, size) != 0)
+ assert(0);
+ __vtv_free(ptrs[i]);
+ }
+ __vtv_malloc_protect();
+ }
+ }
+ }
+
+ /* Allocate a bunch of medium size objects. Make sure the alignment is correct */
+ {
+ int s;
+ for (s = 3001; s < 15000; s += 307)
+ {
+ size = s;
+ {
+ int i;
+ #define ITERS3 50
+ char * ptrs[ITERS3];
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS3; i++)
+ {
+ ptr = (char *)__vtv_malloc(size);
+ assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
+ memset(ptr, i & 127, size);
+ assert(ptr[size - 1] == i & 127);
+ ptrs[i] = ptr;
+ }
+ __vtv_malloc_protect();
+
+ __vtv_malloc_unprotect();
+ for (i = 0; i < ITERS3; i++)
+ {
+ if (memchk(ptrs[i], i & 127, size) != 0)
+ assert(0);
+ memset(ptrs[i], (i + 1) & 127, size);
+ if (memchk(ptrs[i], (i + 1) & 127, size) != 0)
+ assert(0);
+ __vtv_free(ptrs[i]);
+ }
+ __vtv_malloc_protect();
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/libvtv/testsuite/nested_vcall_test.cc b/libvtv/testsuite/nested_vcall_test.cc
new file mode 100644
index 00000000000..13d7143edf8
--- /dev/null
+++ b/libvtv/testsuite/nested_vcall_test.cc
@@ -0,0 +1,76 @@
+
+class EtherCtrl {
+ protected:
+ int ssap;
+
+ public:
+ EtherCtrl(void);
+ ~EtherCtrl();
+ virtual int getSsap(void) const;
+ virtual void setSsap(int);
+};
+
+class EtherFrameWithLLC {
+ protected:
+ int ssap;
+
+ public:
+ EtherFrameWithLLC(const char *, int);
+ ~EtherFrameWithLLC();
+ virtual int getSsap(void) const;
+ virtual void setSsap(int);
+};
+
+
+EtherCtrl::EtherCtrl()
+{
+ this->ssap = 0;
+}
+
+EtherCtrl::~EtherCtrl()
+{
+}
+
+int EtherCtrl::getSsap() const
+{
+ return ssap;
+}
+
+void EtherCtrl::setSsap(int ssap)
+{
+ this->ssap = ssap;
+}
+
+EtherFrameWithLLC::EtherFrameWithLLC(const char *name, int kind)
+{
+ this->ssap = 0;
+}
+
+EtherFrameWithLLC::~EtherFrameWithLLC()
+{
+}
+
+int EtherFrameWithLLC::getSsap() const
+{
+ return ssap;
+}
+
+void EtherFrameWithLLC::setSsap(int ssap)
+{
+ this->ssap = ssap;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ EtherCtrl *etherctrl = new EtherCtrl ();
+ EtherFrameWithLLC *frame = new EtherFrameWithLLC ("test", 10);
+ int my_value;
+
+ etherctrl->setSsap(43);
+ frame->setSsap(etherctrl->getSsap());
+ my_value = frame->getSsap();
+
+ return 0;
+}
diff --git a/libvtv/testsuite/parts-test-extra-parts-views.cc b/libvtv/testsuite/parts-test-extra-parts-views.cc
new file mode 100644
index 00000000000..13d7fdc6e4f
--- /dev/null
+++ b/libvtv/testsuite/parts-test-extra-parts-views.cc
@@ -0,0 +1,16 @@
+#include "parts-test-extra-parts-views.h"
+
+ExtraPartsViews::ExtraPartsViews ()
+ : ExtraParts () {
+}
+
+ExtraPartsViews::~ExtraPartsViews () {}
+
+void
+ExtraPartsViews::ToolkitInitialized ()
+{
+ /* Do something */
+ int sum = 0;
+ for (int i = 0; i < 10; ++i)
+ sum += i;
+}
diff --git a/libvtv/testsuite/parts-test-extra-parts-views.h b/libvtv/testsuite/parts-test-extra-parts-views.h
new file mode 100644
index 00000000000..0784c0ecdaa
--- /dev/null
+++ b/libvtv/testsuite/parts-test-extra-parts-views.h
@@ -0,0 +1,14 @@
+#ifndef _EXTRA_PARTS_VIEWS_H_
+#define _EXTRA_PARTS_VIEWS_H_
+
+#include "parts-test-extra-parts.h"
+
+class ExtraPartsViews : public ExtraParts {
+ public:
+ ExtraPartsViews ();
+ virtual ~ExtraPartsViews ();
+
+ virtual void ToolkitInitialized ();
+};
+
+#endif /* _EXTRA_PARTS_VIEWS_H_ */
diff --git a/libvtv/testsuite/parts-test-extra-parts.cc b/libvtv/testsuite/parts-test-extra-parts.cc
new file mode 100644
index 00000000000..dbd3dbfd8f5
--- /dev/null
+++ b/libvtv/testsuite/parts-test-extra-parts.cc
@@ -0,0 +1,15 @@
+#include "parts-test-extra-parts.h"
+
+ExtraParts::ExtraParts () {}
+
+ExtraParts::~ExtraParts () {}
+
+void
+ExtraParts::ToolkitInitialized ()
+{
+}
+
+void
+ExtraParts::PreEarlyInitialization ()
+{
+}
diff --git a/libvtv/testsuite/parts-test-extra-parts.h b/libvtv/testsuite/parts-test-extra-parts.h
new file mode 100644
index 00000000000..4ed2a4ce1a0
--- /dev/null
+++ b/libvtv/testsuite/parts-test-extra-parts.h
@@ -0,0 +1,13 @@
+#ifndef _EXTRA_PARTS_H_
+#define _EXTRA_PARTS_H_
+
+class ExtraParts {
+ public:
+ ExtraParts ();
+ virtual ~ExtraParts ();
+
+ virtual void PreEarlyInitialization ();
+ virtual void ToolkitInitialized ();
+};
+
+#endif /* _EXTRA_PARTS_H_ */
diff --git a/libvtv/testsuite/parts-test-main.cc b/libvtv/testsuite/parts-test-main.cc
new file mode 100644
index 00000000000..c90901e7919
--- /dev/null
+++ b/libvtv/testsuite/parts-test-main.cc
@@ -0,0 +1,37 @@
+#include "parts-test-main.h"
+#include "parts-test-extra-parts-views.h"
+
+MainParts::MainParts () {}
+
+MainParts::~MainParts ()
+{
+ for (int i = static_cast<int>(main_extra_parts_.size()) - 1; i >= 0; --i)
+ delete main_extra_parts_[i];
+ main_extra_parts_.clear();
+}
+
+void
+MainParts::AddParts (ExtraParts *parts)
+{
+ main_extra_parts_.push_back (parts);
+}
+
+
+void
+MainParts::PreEarlyInitialization (void)
+{
+ for (int i = 0; i < main_extra_parts_.size(); ++i)
+ main_extra_parts_[i]->PreEarlyInitialization ();
+}
+
+
+int
+main (int argc, char **argv)
+{
+ MainParts *main_parts = new MainParts ();
+
+ main_parts->AddParts (new ExtraPartsViews ());
+ main_parts->PreEarlyInitialization ();
+
+ return 0;
+}
diff --git a/libvtv/testsuite/parts-test-main.h b/libvtv/testsuite/parts-test-main.h
new file mode 100644
index 00000000000..fb631dec340
--- /dev/null
+++ b/libvtv/testsuite/parts-test-main.h
@@ -0,0 +1,15 @@
+#include <vector>
+
+class ExtraParts;
+
+class MainParts {
+ public:
+ MainParts ();
+ virtual ~MainParts ();
+ virtual void AddParts (ExtraParts *parts);
+
+ virtual void PreEarlyInitialization ();
+
+ protected:
+ std::vector<ExtraParts *> main_extra_parts_;
+};
diff --git a/libvtv/testsuite/parts-test.list b/libvtv/testsuite/parts-test.list
new file mode 100644
index 00000000000..fdf95a8876c
--- /dev/null
+++ b/libvtv/testsuite/parts-test.list
@@ -0,0 +1 @@
+parts-test-main.cc parts-test-extra-parts.cc parts-test-extra-parts-views.cc
diff --git a/libvtv/testsuite/povray-derived.cc b/libvtv/testsuite/povray-derived.cc
new file mode 100644
index 00000000000..4f56a3d730f
--- /dev/null
+++ b/libvtv/testsuite/povray-derived.cc
@@ -0,0 +1,72 @@
+// Small test case from povray, see if it reproduces.
+
+#include <stdio.h>
+
+class POVMS_MessageReceiver
+{
+
+private:
+ int x;
+ class Handler
+ {
+ public:
+ virtual void print() = 0;
+ };
+protected:
+ template<class T> class MemberHandler : public Handler
+ {
+ public:
+ MemberHandler(T *xx)
+ {
+ x = xx;
+ }
+
+ ~MemberHandler() {}
+
+ void print()
+ {
+ printf("In print\n");
+ }
+ private:
+ T *x;
+ };
+
+private:
+ struct HandlerNode
+ {
+ Handler *handler;
+ };
+
+ HandlerNode *receiver;
+public:
+ POVMS_MessageReceiver(int xx) : x(xx) {}
+ ~POVMS_MessageReceiver() {}
+
+ void foo(int *xx);
+ void try_call();
+};
+
+void POVMS_MessageReceiver::foo(int *xx)
+{
+ receiver = new HandlerNode;
+
+ receiver->handler = new MemberHandler<int>(xx);
+}
+
+void POVMS_MessageReceiver::try_call()
+{
+ receiver->handler->print();
+}
+
+
+int main()
+{
+ int loc = 34;
+ POVMS_MessageReceiver a_test(100);
+
+ a_test.foo(&loc);
+ a_test.try_call();
+}
+
+
+
diff --git a/libvtv/testsuite/register_pair.cc b/libvtv/testsuite/register_pair.cc
new file mode 100644
index 00000000000..0759c472df1
--- /dev/null
+++ b/libvtv/testsuite/register_pair.cc
@@ -0,0 +1,39 @@
+#include "vtv_utils.h"
+#include "vtv_rts.h"
+
+/* This configuration will test mostly inserting of elements that are already inserted since
+ the number of repeats is 200 */
+
+#define NUM_MAPS 4000
+#define ELEMENTS_PER_MAP 100
+#define NUM_REPEATS 200
+
+/* This variable has to be put in rel.ro */
+void * maps[NUM_MAPS] VTV_PROTECTED_VAR;
+
+struct fake_vt {
+ void * fake_vfp [4];
+};
+void * fake_vts [NUM_MAPS * ELEMENTS_PER_MAP];
+
+int main()
+{
+ __VLTChangePermission(__VLTP_READ_WRITE);
+
+ for (int k = 0; k < NUM_REPEATS; k++)
+ {
+ int curr_fake_vt = 0;
+ for (int i = 0; i < NUM_MAPS; i++)
+ for (int j = 0; j < ELEMENTS_PER_MAP; j++)
+ {
+#ifdef VTV_DEBUG
+ __VLTRegisterPairDebug(&maps[i], &fake_vts[curr_fake_vt]);
+#endif
+ curr_fake_vt++;
+ }
+ }
+
+ __VLTChangePermission(__VLTP_READ_ONLY);
+
+ return 0;
+}
diff --git a/libvtv/testsuite/register_pair_inserts.cc b/libvtv/testsuite/register_pair_inserts.cc
new file mode 100644
index 00000000000..72d6d968465
--- /dev/null
+++ b/libvtv/testsuite/register_pair_inserts.cc
@@ -0,0 +1,46 @@
+#include "vtv_utils.h"
+#include "vtv_rts.h"
+
+/* This configuration will test mostly inserting of new elements since
+ the number of repeats is 1. It should also do a lot of rehashing */
+
+/* This test case may fail depending on the system configuration.
+ Check the value of /proc/sys/vm/max_map_count and fix by doing
+ Ex: sudo sh -c "echo 131060 > /proc/sys/vm/max_map_count" */
+
+#define NUM_MAPS 40000
+#define ELEMENTS_PER_MAP 100
+#define NUM_REPEATS 1
+
+/* This variable has to be put in rel.ro */
+void * maps[NUM_MAPS] VTV_PROTECTED_VAR;
+
+struct fake_vt {
+ void * fake_vfp [4];
+};
+void * fake_vts [NUM_MAPS * ELEMENTS_PER_MAP];
+
+
+int main()
+{
+ __VLTChangePermission(__VLTP_READ_WRITE);
+
+ for (int k = 0; k < NUM_REPEATS; k++)
+ {
+ int curr_fake_vt = 0;
+ for (int i = 0; i < NUM_MAPS; i++)
+ for (int j = 0; j < ELEMENTS_PER_MAP; j++)
+ {
+#ifdef VTV_DEBUG
+ __VLTRegisterPairDebug(&maps[i], &fake_vts[curr_fake_vt], 0, 0, 0, 0);
+#else
+ __VLTRegisterPair(&maps[i], &fake_vts[curr_fake_vt]);
+#endif
+ curr_fake_vt++;
+ }
+ }
+
+ __VLTChangePermission(__VLTP_READ_ONLY);
+
+ return 0;
+}
diff --git a/libvtv/testsuite/register_pair_inserts_mt.cc b/libvtv/testsuite/register_pair_inserts_mt.cc
new file mode 100644
index 00000000000..a79dc1f9196
--- /dev/null
+++ b/libvtv/testsuite/register_pair_inserts_mt.cc
@@ -0,0 +1,100 @@
+#include "vtv_utils.h"
+#include "vtv_rts.h"
+#include "pthread.h"
+#include <stdio.h>
+
+
+/* Multi-threaded test for calls to RegisterPair */
+
+/* This configuration will test mostly inserting of new elements since
+ the number of repeats is 1. It should also do a lot of rehashing */
+
+/* This test case may fail depending on the system configuration.
+ Check the value of /proc/sys/vm/max_map_count and fix by doing
+ Ex: sudo sh -c "echo 131060 > /proc/sys/vm/max_map_count" */
+
+#define NUM_MAPS 2000
+#define ELEMENTS_PER_MAP 100
+#define NUM_REPEATS 1
+
+#define NUM_THREADS 9
+
+/* This variable has to be put in rel.ro */
+void * volatile maps[NUM_MAPS] VTV_PROTECTED_VAR;
+
+struct fake_vt {
+ void * fake_vfp [4];
+};
+void * fake_vts [NUM_MAPS * ELEMENTS_PER_MAP];
+
+volatile int current_map = -1;
+volatile int threads_completed_it = 0;
+
+void * do_register_pairs(void *)
+{
+ for (int k = 0; k < NUM_REPEATS; k++)
+ {
+ int curr_fake_vt = 0;
+ for (int i = 0; i < NUM_MAPS; i++)
+ {
+ while (current_map < (k*NUM_MAPS + i))
+ ;
+
+ __VLTChangePermission(__VLTP_READ_WRITE);
+
+ for (int j = 0; j < ELEMENTS_PER_MAP; j++)
+ {
+#ifdef VTV_DEBUG
+ __VLTRegisterPairDebug((void **) &maps[i], &fake_vts[curr_fake_vt], 0, 0, 0, 0);
+#else
+ __VLTRegisterPair((void **) &maps[i], &fake_vts[curr_fake_vt]);
+#endif
+ __VLTVerifyVtablePointer((void **) &maps[i], &fake_vts[curr_fake_vt]);
+ curr_fake_vt++;
+ }
+
+ __VLTChangePermission(__VLTP_READ_ONLY);
+
+ int old_value;
+ do {
+ old_value = threads_completed_it;
+ } while (!__sync_bool_compare_and_swap(&threads_completed_it, old_value, old_value + 1));
+
+ if (old_value == (NUM_THREADS - 1)) // Only one thread will do this.
+ {
+ threads_completed_it = 0;
+ printf("%c%d", 13, current_map + 1);
+ fflush(stdout);
+ current_map++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+int main()
+{
+ pthread_t thread_ids[NUM_THREADS];
+
+ for (int t = 0; t < NUM_THREADS; t++ )
+ if (pthread_create(&thread_ids[t], NULL, do_register_pairs, NULL) != 0)
+ {
+ printf("failed pthread_create\n");
+ exit(1);
+ }
+
+ current_map = 0; // start the work on the other threads
+
+ for (int t = 0; t < NUM_THREADS; t++)
+ if (pthread_join(thread_ids[t], NULL) != 0)
+ {
+ printf("failed pthread_join\n");
+ exit(2);
+ }
+
+ printf("\n");
+
+ return 0;
+}
diff --git a/libvtv/testsuite/register_pair_mt.cc b/libvtv/testsuite/register_pair_mt.cc
new file mode 100644
index 00000000000..e421c4f0d2b
--- /dev/null
+++ b/libvtv/testsuite/register_pair_mt.cc
@@ -0,0 +1,102 @@
+#include "vtv_utils.h"
+#include "vtv_rts.h"
+#include "pthread.h"
+#include <stdio.h>
+
+
+/* Multi-threaded test for calls to RegisterPair */
+
+/* This configuration will test mostly inserting of elements that are already inserted since
+ the number of repeats is 10 */
+
+/* This test case may fail depending on the system configuration.
+ Check the value of /proc/sys/vm/max_map_count and fix by doing
+ Ex: sudo sh -c "echo 131060 > /proc/sys/vm/max_map_count" */
+
+#define NUM_MAPS 200
+#define ELEMENTS_PER_MAP 100
+#define NUM_REPEATS 10
+
+#define NUM_THREADS 9
+
+/* This variable has to be put in rel.ro */
+void * volatile maps[NUM_MAPS] VTV_PROTECTED_VAR;
+
+struct fake_vt {
+ void * fake_vfp [4];
+};
+void * fake_vts [NUM_MAPS * ELEMENTS_PER_MAP];
+
+volatile int current_map = -1;
+volatile int threads_completed_it = 0;
+
+void * do_register_pairs(void *)
+{
+ for (int k = 0; k < NUM_REPEATS; k++)
+ {
+ int curr_fake_vt = 0;
+ for (int i = 0; i < NUM_MAPS; i++)
+ {
+ while (current_map < (k*NUM_MAPS + i))
+ ;
+
+ __VLTChangePermission(__VLTP_READ_WRITE);
+
+ for (int j = 0; j < ELEMENTS_PER_MAP; j++)
+ {
+#ifdef VTV_DEBUG
+ __VLTRegisterPair((void **) &maps[i], &fake_vts[curr_fake_vt], 0, 0, 0, 0);
+#else
+ __VLTRegisterPair((void **) &maps[i], &fake_vts[curr_fake_vt]);
+#endif
+ __VLTVerifyVtablePointer((void **) &maps[i], &fake_vts[curr_fake_vt]);
+ curr_fake_vt++;
+ }
+
+ __VLTChangePermission(__VLTP_READ_ONLY);
+
+ int old_value;
+ do {
+ old_value = threads_completed_it;
+ } while (!__sync_bool_compare_and_swap(&threads_completed_it, old_value, old_value + 1));
+
+ if (old_value == (NUM_THREADS - 1)) // Only one thread will do this.
+ {
+ threads_completed_it = 0;
+ printf("%c%d", 13, current_map + 1);
+ fflush(stdout);
+ current_map++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+int main()
+{
+ pthread_t thread_ids[NUM_THREADS];
+
+ for (int t = 0; t < NUM_THREADS; t++ )
+ if (pthread_create(&thread_ids[t], NULL, do_register_pairs, NULL) != 0)
+ {
+ printf("failed pthread_create\n");
+ exit(1);
+ }
+
+ current_map = 0; // start the work on the other threads
+
+ for (int t = 0; t < NUM_THREADS; t++)
+ if (pthread_join(thread_ids[t], NULL) != 0)
+ {
+ printf("failed pthread_join\n");
+ exit(2);
+ }
+
+ printf("\n");
+
+
+
+ return 0;
+}
diff --git a/libvtv/testsuite/replace-fail.cc b/libvtv/testsuite/replace-fail.cc
new file mode 100644
index 00000000000..2b4070eec77
--- /dev/null
+++ b/libvtv/testsuite/replace-fail.cc
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+
+void __vtv_verify_fail (void **, void*) __attribute__((visibility ("default")));
+
+void
+__vtv_verify_fail (void **hash_table, const void *vtbl_ptr)
+{
+ fprintf (stdout, "Executing alternative failure routine.\n");
+}
diff --git a/libvtv/testsuite/so.cc b/libvtv/testsuite/so.cc
new file mode 100644
index 00000000000..3f0a346f1e8
--- /dev/null
+++ b/libvtv/testsuite/so.cc
@@ -0,0 +1,93 @@
+#include <dlfcn.h>
+#include <assert.h>
+#include <unistd.h>
+#include <vtv_fail.h>
+
+extern "C" int printf(const char *, ...);
+extern "C" int sprintf(char *, const char*, ...);
+
+static int counter = 0;
+extern int failures;
+
+template <int i> struct base
+{
+ virtual char * whoami() {
+ static char sl[100];
+ sprintf(sl, "I am base %d", i);
+ return sl;
+ }
+ virtual void inc() { counter += i; }
+};
+
+template <int i> struct derived: base<i>
+{
+ virtual char * whoami() {
+ static char sl[100];
+ sprintf(sl, "I am derived %d", i);
+ return sl;
+ }
+ virtual void inc() { counter += (10*i); }
+};
+
+// We don't use this class. It is just here so that the
+// compiler does not devirtualize calls to derived::inc()
+template <int i> struct derived2: derived<i>
+{
+ virtual void inc() { counter += (20*i); }
+};
+
+static base<TPID> * bp = new base<TPID>();
+static derived<TPID> * dp = new derived<TPID>();
+static base<TPID> * dbp = new derived<TPID>();
+
+
+// Given 2 pointers to C++ objects (non PODs), exchange the pointers to vtable
+static void exchange_vtptr(void * object1_ptr, void * object2_ptr)
+{
+ void ** object1_vtptr_ptr = (void **)object1_ptr;
+ void ** object2_vtptr_ptr = (void **)object2_ptr;
+ void * object1_vtptr = *object1_vtptr_ptr;
+ void * object2_vtptr = *object2_vtptr_ptr;
+ *object1_vtptr_ptr = object2_vtptr;
+ *object2_vtptr_ptr = object1_vtptr;
+}
+
+#define BUILD_NAME(NAME,ID) NAME##ID
+#define EXPAND(NAME,X) BUILD_NAME(NAME,X)
+extern "C" void EXPAND(so_entry_,TPID)(void)
+{
+ int prev_counter;
+ int prev_failures;
+
+ counter = 0;
+ bp->inc();
+ dp->inc();
+ dbp->inc();
+ assert(counter == (TPID + 10*TPID + 10*TPID));
+
+ prev_counter = counter;
+ exchange_vtptr(bp, dp);
+ bp->inc(); // This one should succeed but it is calling the wrong member
+ if (counter != (prev_counter + 10*TPID))
+ {
+ printf("TPID=%d whoami=%s wrong counter value prev_counter=%d counter=%d\n", TPID, bp->whoami(), prev_counter, counter);
+ sleep(2);
+ }
+ assert(counter == (prev_counter + 10*TPID));
+ // printf("Pass first attack!\n");
+
+ // This one should fail verification!. So it should jump to __vtv_verify_fail above.
+ prev_failures = failures;
+ dp->inc();
+ // this code may be executed by multiple threads at the same time. So, just verify the number of failures has
+ // increased as opposed to check for increase by 1.
+ assert(failures > prev_failures);
+ assert(counter == (prev_counter + 10*TPID + TPID));
+ // printf("TPDI=%d counter %d\n", TPID, counter);
+ // printf("Pass second attack!\n");
+
+ // restore the vtable pointers to the original state.
+ // This is very important. For some reason the dlclose is not "really" closing the library so when we reopen it we are
+ // getting the old memory state.
+ exchange_vtptr(bp, dp);
+}
diff --git a/libvtv/testsuite/temp_deriv.cc b/libvtv/testsuite/temp_deriv.cc
new file mode 100644
index 00000000000..ca360c0bc91
--- /dev/null
+++ b/libvtv/testsuite/temp_deriv.cc
@@ -0,0 +1,67 @@
+// Compile with /home/llozano/local2/proj/vtable/gcc-root/usr/local/bin/g++ -m32 -fvtable-verify=std -fpic -rdynamic -Wl,-R,/home/llozano/local2/proj/vtable/gcc-root/usr/local/lib32:./lib32 -I/home/llozano/local2/proj/vtable/vt2/gcc-4_6-mobile-vtable-security//libstdc++-v3/libsupc++ temp_deriv.cc -O0 -ldl -lpthread -Wl,--whole-archive,-lvtv_init,--no-whole-archive,-z,relro -DTPID=0 -g
+// Look at assembly with: objdump -drl a.out
+
+#include <dlfcn.h>
+#include <assert.h>
+
+extern "C" int printf(const char *, ...);
+
+static int counter = 0;
+
+template <int i> struct base
+{
+ virtual void inc() { counter += i; }
+};
+
+template <int i> struct derived: base<i>
+{
+ virtual void inc() { counter += (10*i); }
+};
+
+// We don't use this class. It is just here so that the
+// compiler does not devirtualize calls to derived::inc()
+template <int i> struct derived2: derived<i>
+{
+ virtual void inc() { counter += (20*i); }
+};
+
+static base<TPID> * bp = new base<TPID>();
+static derived<TPID> * dp = new derived<TPID>();
+static base<TPID> * dbp = new derived<TPID>();
+
+// Given 2 pointers to C++ objects (non PODs), exchange the pointers to vtable
+void exchange_vtptr(void * object1_ptr, void * object2_ptr)
+{
+ void ** object1_vtptr_ptr = (void **)object1_ptr;
+ void ** object2_vtptr_ptr = (void **)object2_ptr;
+ void * object1_vtptr = *object1_vtptr_ptr;
+ void * object2_vtptr = *object2_vtptr_ptr;
+ *object1_vtptr_ptr = object2_vtptr;
+ *object2_vtptr_ptr = object1_vtptr;
+}
+
+main()
+{
+ int prev_counter;
+
+ exchange_vtptr(bp, dp);
+ exchange_vtptr(bp, dp);
+ exchange_vtptr(bp, dbp);
+ exchange_vtptr(bp, dbp);
+
+ counter = 0;
+ bp->inc();
+ dp->inc();
+ dbp->inc();
+ assert(counter == (TPID + 10*TPID + 10*TPID));
+
+ prev_counter = counter;
+ exchange_vtptr(bp, dp);
+ bp->inc(); // This one should succeed but it is calling the wrong member
+ assert(counter == (prev_counter + 10*TPID));
+ printf("Pass first attack!\n");
+ dp->inc();
+ printf("TPDI=%d counter %d\n", TPID, counter);
+ printf("Pass second attack!\n");
+
+}
diff --git a/libvtv/testsuite/temp_deriv2.cc b/libvtv/testsuite/temp_deriv2.cc
new file mode 100644
index 00000000000..78b43f8b08b
--- /dev/null
+++ b/libvtv/testsuite/temp_deriv2.cc
@@ -0,0 +1,69 @@
+// Compile with /home/llozano/local2/proj/vtable/gcc-root/usr/local/bin/g++ -m32 -fvtable-verify=std -fpic -rdynamic -Wl,-R,/home/llozano/local2/proj/vtable/gcc-root/usr/local/lib32:./lib32 -I/home/llozano/local2/proj/vtable/vt2/gcc-4_6-mobile-vtable-security//libstdc++-v3/libsupc++ temp_deriv.cc -O0 -ldl -lpthread -Wl,--whole-archive,-lvtv_init,--no-whole-archive,-z,relro -DTPID=0 -g
+// Look at assembly with: objdump -drl a.out
+
+#include <dlfcn.h>
+#include <assert.h>
+
+extern "C" int printf(const char *, ...);
+
+static int counter = 0;
+
+int i = TPID;
+struct base
+{
+ virtual void inc() { counter += i; }
+};
+
+struct derived: public base
+{
+ virtual void inc() { counter += (10*i); }
+};
+
+// We don't use this class. It is just here so that the
+// compiler does not devirtualize calls to derived::inc()
+struct derived2: public derived
+{
+ virtual void inc() { counter += (20*i); }
+};
+
+static base * bp = new base();
+static derived * dp = new derived();
+static base * dbp = new derived();
+
+// Given 2 pointers to C++ objects (non PODs), exchange the pointers to vtable
+void exchange_vtptr(void * object1_ptr, void * object2_ptr)
+{
+ typedef void * vtptr;
+ vtptr * object1_vtptr_ptr = (vtptr *)object1_ptr;
+ vtptr * object2_vtptr_ptr = (vtptr *)object2_ptr;
+ vtptr object1_vtptr = *object1_vtptr_ptr;
+ vtptr object2_vtptr = *object2_vtptr_ptr;
+ *object1_vtptr_ptr = object2_vtptr;
+ *object2_vtptr_ptr = object1_vtptr;
+}
+
+main()
+{
+ int prev_counter;
+
+ exchange_vtptr(bp, dp);
+ exchange_vtptr(bp, dp);
+ exchange_vtptr(bp, dbp);
+ exchange_vtptr(bp, dbp);
+
+ counter = 0;
+ bp->inc();
+ dp->inc();
+ dbp->inc();
+ assert(counter == (TPID + 10*TPID + 10*TPID));
+
+ prev_counter = counter;
+ exchange_vtptr(bp, dp);
+ bp->inc(); // This one should succeed but it is calling the wrong member
+ assert(counter == (prev_counter + 10*TPID));
+ printf("Pass first attack!\n");
+ dp->inc();
+ printf("TPDI=%d counter %d\n", TPID, counter);
+ printf("Pass second attack!\n");
+
+}
diff --git a/libvtv/testsuite/temp_deriv3.cc b/libvtv/testsuite/temp_deriv3.cc
new file mode 100644
index 00000000000..924c47e9628
--- /dev/null
+++ b/libvtv/testsuite/temp_deriv3.cc
@@ -0,0 +1,79 @@
+// Compile with /home/llozano/local2/proj/vtable/gcc-root/usr/local/bin/g++ -m32 -fvtable-verify=std -fpic -rdynamic -Wl,-R,/home/llozano/local2/proj/vtable/gcc-root/usr/local/lib32:./lib32 -I/home/llozano/local2/proj/vtable/vt2/gcc-4_6-mobile-vtable-security//libstdc++-v3/libsupc++ temp_deriv.cc -O0 -ldl -lpthread -Wl,--whole-archive,-lvtv_init,--no-whole-archive,-z,relro -DTPID=0 -g
+// Look at assembly with: objdump -drl a.out
+
+#include <dlfcn.h>
+#include <assert.h>
+#include <stdlib.h>
+
+extern "C" int printf(const char *, ...);
+
+static int counter = 0;
+
+int i = TPID;
+struct base
+{
+ virtual void inc() { counter += i; }
+};
+
+struct derived: public base
+{
+ virtual void inc() { counter += (10*i); }
+};
+
+// We don't use this class. It is just here so that the
+// compiler does not devirtualize calls to derived::inc()
+struct derived2: public derived
+{
+ virtual void inc() { counter += (20*i); }
+};
+
+static base * bp = new base();
+static derived * dp = new derived();
+static base * dbp = new derived();
+
+typedef void * vtptr;
+
+vtptr get_vtptr(void * object_ptr)
+{
+ vtptr * object_vtptr_ptr = (vtptr *)object_ptr;
+ return *object_vtptr_ptr;
+}
+
+void set_vptr(void * object_ptr, vtptr vtp)
+{
+ vtptr * object_vtptr_ptr = (vtptr *)object_ptr;
+ *object_vtptr_ptr = vtp;
+}
+
+// Given 2 pointers to C++ objects (non PODs), exchange the pointers to vtable
+void exchange_vtptr(void * object1_ptr, void * object2_ptr)
+{
+ vtptr object1_vtptr = get_vtptr(object1_ptr);
+ vtptr object2_vtptr = get_vtptr(object2_ptr);
+ set_vptr(object1_ptr, object2_vtptr);
+ set_vptr(object2_ptr, object1_vtptr);
+}
+
+main()
+{
+ int prev_counter;
+
+ counter = 0;
+ bp->inc();
+ dp->inc();
+ dbp->inc();
+ assert(counter == (TPID + 10*TPID + 10*TPID));
+
+ prev_counter = counter;
+ printf("before ex bp vptr=%x dp vptr=%x\n", get_vtptr(bp), get_vtptr(dp));
+ exchange_vtptr(bp, dp);
+ printf("after ex bp vptr=%x dp vptr=%x\n", get_vtptr(bp), get_vtptr(dp));
+ bp->inc(); // This one should not abort but it is calling the wrong member
+ assert(counter == (prev_counter + 10*TPID));
+ printf("Pass first attack! Expected!\n");
+ printf("TPDI=%d counter %d\n", TPID, counter);
+ dp->inc();
+ printf("Pass second attack! SHOULD NOT BE HERE!\n");
+ printf("TPDI=%d counter %d\n", TPID, counter);
+ exit(1);
+}
diff --git a/libvtv/testsuite/template-list-iostream.cc b/libvtv/testsuite/template-list-iostream.cc
new file mode 100644
index 00000000000..a35fd308382
--- /dev/null
+++ b/libvtv/testsuite/template-list-iostream.cc
@@ -0,0 +1,118 @@
+#include <assert.h>
+#include <iostream>
+#include <fstream>
+
+using std::ofstream;
+using std::ifstream;
+using std::ios;
+
+extern "C" int printf(const char *, ...);
+
+class Subscriptor
+{
+ public:
+
+ Subscriptor() : counter(1) {}
+
+ virtual ~Subscriptor()
+ {
+ counter--;
+ assert(counter == 0);
+ }
+
+ private:
+ mutable int counter;
+};
+
+template <int dim> struct Function
+{
+ Function(int i): value(dim + i) {}
+ int value;
+};
+
+template <int dim> struct Triangulation
+{
+
+};
+
+template <int dim> struct Exercise_2_3
+{
+ enum { DIM = dim };
+};
+
+ template <int dim>
+ struct SetUpBase : public Subscriptor
+ {
+ virtual
+ const Function<dim> get_boundary_values () const = 0;
+
+ virtual
+ const Function<dim> get_right_hand_side () const = 0;
+
+ // virtual
+ // void create_coarse_grid (Triangulation<dim> &coarse_grid) const = 0;
+ };
+
+ template <class Traits, int dim>
+ struct SetUp : public SetUpBase<dim>
+ {
+ SetUp () {};
+
+ virtual
+ const Function<dim> get_boundary_values () const
+ { return Function<dim>(Traits::DIM); }
+
+ virtual
+ const Function<dim> get_right_hand_side () const
+ { return Function<dim>(Traits::DIM); }
+
+ // virtual
+ // void create_coarse_grid (Triangulation<dim> &coarse_grid) const;
+
+ // static const typename Traits::BoundaryValues boundary_values;
+ // static const typename Traits::RightHandSide right_hand_side;
+ };
+
+
+void myread(std::istream * in)
+{
+ char input_str[50] = "\0";
+ if (in->good())
+ (*in) >> input_str;
+ std::cout << input_str << std::endl;
+ delete in;
+}
+
+
+
+int main()
+{
+ /*
+
+ SetUp<Exercise_2_3<1000>, 2> s1a;
+ SetUp<Exercise_2_3<2000>, 1> s2;
+ SetUp<Exercise_2_3<2000>, 2> s2a;
+ return s1->get_boundary_values().value + s1a.get_boundary_values().value +
+ s2.get_boundary_values().value + s2a.get_boundary_values().value +
+ s1->get_right_hand_side().value + s1a.get_right_hand_side().value +
+ s2.get_right_hand_side().value + s2a.get_right_hand_side().value;
+ */
+
+ SetUp<Exercise_2_3<1000>, 1> * s1 = new SetUp<Exercise_2_3<1000>, 1>();
+
+ printf("%d\n", s1->get_boundary_values().value);
+
+ ifstream * infile = new ifstream("./template-list-iostream.cc");
+
+ myread(infile);
+
+ ofstream * outfile = new ofstream("/tmp/xxx.txt");
+
+ if (outfile->good())
+ (*outfile) << "hello there" << std::endl;
+ std::cerr << "Reached End" << std::endl;
+
+ delete outfile;
+
+ return 0;
+}
diff --git a/libvtv/testsuite/template-list.cc b/libvtv/testsuite/template-list.cc
new file mode 100644
index 00000000000..95233f87765
--- /dev/null
+++ b/libvtv/testsuite/template-list.cc
@@ -0,0 +1,92 @@
+#include <assert.h>
+
+extern "C" int printf(const char *, ...);
+
+class Subscriptor
+{
+ public:
+
+ Subscriptor() : counter(1) {}
+
+ virtual ~Subscriptor()
+ {
+ counter--;
+ assert(counter == 0);
+ }
+
+ private:
+ mutable int counter;
+};
+
+template <int dim> struct Function
+{
+ Function(int i): value(dim + i) {}
+ int value;
+};
+
+template <int dim> struct Triangulation
+{
+
+};
+
+template <int dim> struct Exercise_2_3
+{
+ enum { DIM = dim };
+};
+
+ template <int dim>
+ struct SetUpBase : public Subscriptor
+ {
+ virtual
+ const Function<dim> get_boundary_values () const = 0;
+
+ virtual
+ const Function<dim> get_right_hand_side () const = 0;
+
+ // virtual
+ // void create_coarse_grid (Triangulation<dim> &coarse_grid) const = 0;
+ };
+
+ template <class Traits, int dim>
+ struct SetUp : public SetUpBase<dim>
+ {
+ SetUp () {};
+
+ virtual
+ const Function<dim> get_boundary_values () const
+ { return Function<dim>(Traits::DIM); }
+
+ virtual
+ const Function<dim> get_right_hand_side () const
+ { return Function<dim>(Traits::DIM); }
+
+ // virtual
+ // void create_coarse_grid (Triangulation<dim> &coarse_grid) const;
+
+ // static const typename Traits::BoundaryValues boundary_values;
+ // static const typename Traits::RightHandSide right_hand_side;
+ };
+
+
+int main()
+{
+ /*
+
+ SetUp<Exercise_2_3<1000>, 2> s1a;
+ SetUp<Exercise_2_3<2000>, 1> s2;
+ SetUp<Exercise_2_3<2000>, 2> s2a;
+ return s1->get_boundary_values().value + s1a.get_boundary_values().value +
+ s2.get_boundary_values().value + s2a.get_boundary_values().value +
+ s1->get_right_hand_side().value + s1a.get_right_hand_side().value +
+ s2.get_right_hand_side().value + s2a.get_right_hand_side().value;
+ */
+#ifndef NFAIL
+ SetUp<Exercise_2_3<1000>, 1> * s1 = new SetUp<Exercise_2_3<1000>, 1>();
+ printf("%d\n", s1->get_boundary_values().value);
+ return 0;
+#else
+ SetUp<Exercise_2_3<1000>, 1> s1;
+ printf("%d\n", s1.get_boundary_values().value);
+ return 0;
+#endif
+}
diff --git a/libvtv/testsuite/template-list2.cc b/libvtv/testsuite/template-list2.cc
new file mode 100644
index 00000000000..f8ec739b6d5
--- /dev/null
+++ b/libvtv/testsuite/template-list2.cc
@@ -0,0 +1,44 @@
+#include <assert.h>
+
+extern "C" int printf(const char *, ...);
+
+class Subscriptor
+{
+ public:
+
+ Subscriptor()
+ { counter = 1;}
+
+ virtual ~Subscriptor()
+ {
+ counter--;
+ assert(counter == 0);
+ }
+
+ private:
+ static int counter;
+};
+
+int Subscriptor::counter;
+
+template <typename number>
+class Polynomial : public Subscriptor
+{
+};
+
+class LagrangeEquidistant: public Polynomial<double>
+{
+};
+
+template<typename _Tp>
+inline void
+_MyDestroy(_Tp* __pointer)
+ { __pointer->~_Tp(); }
+
+int main()
+{
+ LagrangeEquidistant * s1 = new LagrangeEquidistant;
+ _MyDestroy(s1);
+
+ return 0;
+}
diff --git a/libvtv/testsuite/thunk.cc b/libvtv/testsuite/thunk.cc
new file mode 100644
index 00000000000..6ab81a0dfd4
--- /dev/null
+++ b/libvtv/testsuite/thunk.cc
@@ -0,0 +1,35 @@
+#include <assert.h>
+struct A {
+ A():value(123) {}
+ int value;
+ virtual int access() { return this->value; }
+};
+struct B {
+ B():value(456) {}
+ int value;
+ virtual int access() { return this->value; }
+};
+struct C : public A, public B {
+ C():better_value(789) {}
+ int better_value;
+ virtual int access() { return this->better_value; }
+};
+struct D: public C {
+ D():other_value(987) {}
+ int other_value;
+ virtual int access() { return this->other_value; }
+};
+
+int use(B *b)
+{
+ return b->access();
+}
+
+int main()
+{
+ C c;
+ assert(use(&c) == 789);
+ D d;
+ assert(use(&d) == 987);
+ return 0;
+}
diff --git a/libvtv/testsuite/thunk_vtable_map_attack.cc b/libvtv/testsuite/thunk_vtable_map_attack.cc
new file mode 100644
index 00000000000..84d4bbf3257
--- /dev/null
+++ b/libvtv/testsuite/thunk_vtable_map_attack.cc
@@ -0,0 +1,111 @@
+#include <assert.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <stdio.h>
+
+#include <iostream>
+#include <fstream>
+
+using std::ofstream;
+using std::ifstream;
+using std::ios;
+
+struct A {
+ A():value(123) {}
+ int value;
+ virtual int access() { return this->value; }
+};
+struct B {
+ B():value(456) {}
+ int value;
+ virtual int access() { return this->value; }
+};
+struct C : public A, public B {
+ C():better_value(789) {}
+ int better_value;
+ virtual int access() { return this->better_value; }
+};
+struct D: public C {
+ D():other_value(987) {}
+ int other_value;
+ virtual int access() { return this->other_value; }
+};
+
+volatile static int signal_count = 0;
+
+sigjmp_buf before_segv;
+
+static void
+handler(int sig, siginfo_t *si, void *unused)
+{
+ /*
+ printf("Got SIGSEGV at address: 0x%lx\n",
+ (long) si->si_addr);
+ */
+
+ signal_count++;
+ /* You are not supposed to longjmp out of a signal handler but it seems
+ to work for this test case and it simplifies it */
+ siglongjmp(before_segv, 1);
+ /* exit(1); */
+}
+
+/* Access one of the vtable_map variables generated by this .o */
+extern void * _ZN4_VTVI1BE12__vtable_mapE;
+
+/* Access one of the vtable_map variables generated by libstdc++ */
+extern void * _ZN4_VTVISt8ios_baseE12__vtable_mapE;
+
+int use(B *b)
+{
+ int ret;
+
+ ret = sigsetjmp(before_segv, 1);
+ if (ret == 0)
+ {
+ /* This should generate a segmentation violation. ie: at this point it should
+ be protected */
+ _ZN4_VTVI1BE12__vtable_mapE = 0;
+ }
+ assert(ret == 1 && signal_count == 1);
+
+ ret = sigsetjmp(before_segv, 1);
+ if (ret == 0)
+ {
+ /* Try to modify one of the vtable_map variables in the stdc++ library.
+ This should generate a segmentation violation. ie: at this point it
+ should be protected */
+ _ZN4_VTVISt8ios_baseE12__vtable_mapE = 0;
+ }
+ assert(ret == 1 && signal_count == 2);
+
+ return b->access();
+}
+
+void myread(std::istream * in)
+{
+ char input_str[50] = "\0";
+ if (in->good())
+ (*in) >> input_str;
+ std::cout << input_str << std::endl;
+ delete in;
+}
+
+int main()
+{
+ ifstream * infile = new ifstream("./thunk_vtable_map_attack.cpp");
+ myread(infile);
+
+ /* Set up handler for SIGSEGV. */
+ struct sigaction sa;
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = handler;
+ if (sigaction(SIGSEGV, &sa, NULL) == -1)
+ assert(0);
+
+ C c;
+ assert(use(&c) == 789);
+
+ return 0;
+}
diff --git a/libvtv/testsuite/virtual_inheritance.cc b/libvtv/testsuite/virtual_inheritance.cc
new file mode 100644
index 00000000000..89fe388a856
--- /dev/null
+++ b/libvtv/testsuite/virtual_inheritance.cc
@@ -0,0 +1,46 @@
+#include <assert.h>
+struct V {
+ V(): virtual_value(-123) {}
+ int virtual_value;
+ virtual int access_vv() { return virtual_value; }
+};
+
+struct A: virtual public V {
+ A():value(123) {}
+ int value;
+ virtual int access() { return value; }
+};
+struct B: virtual public V {
+ B():value(456) {}
+ int value;
+ virtual int access() { return value; }
+};
+struct C : public A, public B {
+ C():better_value(789) {}
+ int better_value;
+ virtual int access() { return better_value; }
+};
+struct D: public A, public B {
+ D():better_virtual_value(-345) {}
+ int better_virtual_value;
+ virtual int access_vv() { return better_virtual_value; }
+};
+
+int use(B *b)
+{
+ return b->access();
+}
+
+int v_use(V * v)
+{
+ return v->access_vv();
+}
+
+int main()
+{
+ C c;
+ assert(v_use(&c) == -123);
+ D d;
+ assert(v_use(&d) == -345);
+ return 0;
+}