diff options
Diffstat (limited to 'libvtv/testsuite')
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; +} |