This commit was manufactured by cvs2svn to create tag 'MainlineMerge'. llvm-svn: 87542
diff --git a/safecode/autoconf/configure.ac b/safecode/autoconf/configure.ac index a132049..0de9cb0 100755 --- a/safecode/autoconf/configure.ac +++ b/safecode/autoconf/configure.ac
@@ -57,7 +57,6 @@ dnl ************************************************************************** dnl * Checks for library functions. dnl ************************************************************************** -AC_CHECK_FUNCS([posix_memalign ]) dnl ************************************************************************** dnl * Enable various compile-time options
diff --git a/safecode/configure b/safecode/configure index 56440a8..e46f950 100755 --- a/safecode/configure +++ b/safecode/configure
@@ -274,7 +274,7 @@ PACKAGE_BUGREPORT='dhurjati@cs.uiuc.edu' ac_unique_file=""Makefile.common.in"" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS LLVM_SRC LLVM_OBJ OMEGA CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT poolallocsrcdir poolallocobjdir LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS LLVM_SRC LLVM_OBJ OMEGA poolallocsrcdir poolallocobjdir LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -715,22 +715,6 @@ ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS # # Report the --help message. @@ -814,17 +798,6 @@ --with-poolalloc-srcdir Specify location of Pool Allocation source code --with-poolalloc-objdir Specify location of Pool Allocation object code -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a - nonstandard directory <lib dir> - CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have - headers in a nonstandard directory <include dir> - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - Report bugs to <dhurjati@cs.uiuc.edu>. _ACEOF fi @@ -1407,1039 +1380,6 @@ -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CC" && break -done - - CC=$ac_ct_CC -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 - (eval $ac_compiler --version </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 - (eval $ac_compiler -v </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 - (eval $ac_compiler -V </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. - -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; - * ) - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 - -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cc_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_stdc=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <stdarg.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext -done -rm -f conftest.$ac_ext conftest.$ac_objext -CC=$ac_save_CC - -fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; - *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; -esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include <stdlib.h> -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -for ac_func in posix_memalign -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. - For example, HP-UX 11i <limits.h> declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - <limits.h> exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != $ac_func; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_var=no" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - # Check whether --enable-kernel or --disable-kernel was given. @@ -3111,13 +2051,6 @@ s,@LLVM_SRC@,$LLVM_SRC,;t t s,@LLVM_OBJ@,$LLVM_OBJ,;t t s,@OMEGA@,$OMEGA,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t -s,@LDFLAGS@,$LDFLAGS,;t t -s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t s,@poolallocsrcdir@,$poolallocsrcdir,;t t s,@poolallocobjdir@,$poolallocobjdir,;t t s,@LIBOBJS@,$LIBOBJS,;t t
diff --git a/safecode/include/BottomUpCallGraph.h b/safecode/include/BottomUpCallGraph.h index c6fe913..497888e 100755 --- a/safecode/include/BottomUpCallGraph.h +++ b/safecode/include/BottomUpCallGraph.h
@@ -1,8 +1,8 @@ #ifndef BOTTOMUP_CALLGRAPH_H #define BOTTOMUP_CALLGRAPH_H -#include "dsa/DataStructure.h" -#include "dsa/DSSupport.h" #include "llvm/Pass.h" +#include "llvm/Analysis/DataStructure/DataStructure.h" +#include "llvm/Analysis/DataStructure/DSSupport.h" #include "llvm/Function.h" #include "llvm/Module.h"
diff --git a/safecode/include/InsertPoolChecks.h b/safecode/include/InsertPoolChecks.h index 4dddf88..a85eed2 100755 --- a/safecode/include/InsertPoolChecks.h +++ b/safecode/include/InsertPoolChecks.h
@@ -2,121 +2,27 @@ #define INSERT_BOUNDS_H #include "safecode/Config/config.h" -#include "ConvertUnsafeAllocas.h" -#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Pass.h" +#include "ConvertUnsafeAllocas.h" #ifndef LLVA_KERNEL #include "SafeDynMemAlloc.h" #include "poolalloc/PoolAllocate.h" #endif -#include <map> -#include <set> - -#ifdef LLVA_KERNEL -#define LLVA_ICONTEXT_SIZE (18*4) -#define LLVA_INTEGERSTATE_SIZE (18*4) -#define LLVA_FPSTATE_SIZE (27*4) -#endif namespace llvm { ModulePass *creatInsertPoolChecks(); using namespace CUA; -struct PreInsertPoolChecks : public ModulePass { - public: - virtual bool runOnModule (Module & M); - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - // Required passes - AU.addRequired<ConvertUnsafeAllocas>(); - AU.addRequired<TDDataStructures>(); - AU.addRequired<TargetData>(); - - // Preserved passes - AU.addPreserved<ConvertUnsafeAllocas>(); - AU.addPreserved<TDDataStructures>(); - } - - bool nodeNeedsAlignment (DSNode * Node) { - return ((AlignmentNodes.find (Node)) != (AlignmentNodes.end())); - } - private: -#ifndef LLVA_KERNEL - PoolAllocate * paPass; - EquivClassGraphs *equivPass; - EmbeCFreeRemoval *efPass; -#endif - - // Private variables - CUA::ConvertUnsafeAllocas * cuaPass; - TDDataStructures * TDPass; - TargetData * TD; - - // Set of DSNodes that require alignment checks - std::set<DSNode *> AlignmentNodes; - - // External functions in the SAFECode run-time library - Function *PoolCheck; - Function *PoolCheckArray; - Function *PoolCheckIArray; - Function *ExactCheck; - Function *FunctionCheck; - Function *FunctionCheckT; - Function *FunctionCheckG; - Function *ICCheck; - Function *BoundsCheck; - Function *UIBoundsCheck; - Function *getBounds; - Function *UIgetBounds; - Function *ExactCheck2; - Function *ExactCheck3; - Function *GetActualValue; - Function *PoolRegister; - Function *StackRegister; - Function *ObjFree; - Function *StackFree; - Function *FuncRegister; - Function *PoolRegMP; - Function *PoolFindMP; - Function *getBegin; - Function *getEnd; - - // Private methods - void addPoolCheckProto(Module &M); - void registerGlobalArraysWithGlobalPools(Module &M); - void addLinksNeedingAlignment (DSNode * Node); -#ifndef LLVA_KERNEL - Value * getPoolHandle(const Value *V, Function *F, PA::FuncInfo &FI, bool collapsed = false); -#endif - Value * createPoolHandle (const Value * V, Function * F); - Value * createPoolHandle (Module & M, DSNode * Node); - DSGraph & getDSGraph (Function & F); - Value* getPD(DSNode* N, Module& M) { - if (!N) return 0; - createPoolHandle (M, N); - if (N->getMP()) - return N->getMP()->getMetaPoolValue(); - else - return 0; - } -}; - -struct InsertPoolChecks : public FunctionPass { - public : +struct InsertPoolChecks : public ModulePass { + public : const char *getPassName() const { return "Inserting pool checks for array bounds "; } - virtual bool doInitialization (Module &M); - virtual bool doFinalization (Module &M); - virtual bool runOnFunction (Function & F); + virtual bool runOnModule(Module &M); virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<PreInsertPoolChecks>(); AU.addRequired<ConvertUnsafeAllocas>(); - AU.addRequired<ScalarEvolution>(); - AU.addRequired<LoopInfo>(); -#if 0 - AU.addRequired<CompleteBUDataStructures>(); - AU.addRequired<TDDataStructures>(); -#endif +// AU.addRequired<CompleteBUDataStructures>(); +// AU.addRequired<TDDataStructures>(); #ifndef LLVA_KERNEL AU.addRequired<EquivClassGraphs>(); AU.addRequired<PoolAllocate>(); @@ -124,107 +30,38 @@ AU.addRequired<TargetData>(); #else AU.addRequired<TDDataStructures>(); - AU.addRequired<TargetData>(); #endif + }; - - private : - // Prerequisite passes - PreInsertPoolChecks * preSCPass; - CUA::ConvertUnsafeAllocas * cuaPass; - ScalarEvolution * scevPass; - LoopInfo *LI; - TargetData * TD; + private : + CUA::ConvertUnsafeAllocas * cuaPass; #ifndef LLVA_KERNEL - PoolAllocate * paPass; - EquivClassGraphs *equivPass; - EmbeCFreeRemoval *efPass; + PoolAllocate * paPass; + EquivClassGraphs *equivPass; + EmbeCFreeRemoval *efPass; + TargetData * TD; #else - TDDataStructures * TDPass; + TDDataStructures * TDPass; #endif - - // Map of DSNode to Function List Global Variables - std::map<Value *, GlobalVariable *> FuncListMap; - - // Set of DSNodes for which we do full bounds checks - std::set<DSNode *> PHNeeded; - - // Functions - Function *PoolCheck; - Function *PoolCheckAlign; - Function *PoolCheckUI; - Function *PoolCheckAlignUI; - Function *PoolCheckArray; - Function *PoolCheckIArray; - Function *ExactCheck; - Function *FunctionCheck; - Function *FunctionCheckT; - Function *FunctionCheckG; - Function *ICCheck; - Function *BoundsCheck; - Function *UIBoundsCheck; - Function *getBounds; - Function *UIgetBounds; - Function *ExactCheck2; - Function *ExactCheck3; - Function *GetActualValue; - Function *PoolRegister; - Function *StackRegister; - Function *ObjFree; - Function *StackFree; - Function *FuncRegister; - Function *KmemCachegetSize; - Function *PoolRegMP; - Function *PoolFindMP; - Function *getBegin; - Function *getEnd; - - void simplifyGEPList(); - void addObjFrees(Module& M); - void addMetaPools(Module& M, MetaPool* MP, DSNode* N); - void addPoolCheckProto(Module &M); - void addPoolChecks(Module &M); - void addGetElementPtrChecks(Module &M); - DSGraph & getDSGraph (Function & F); - DSNode* getDSNode(const Value *V, Function *F); - unsigned getDSNodeOffset(const Value *V, Function *F); - void addLoadStoreChecks (Function & F); - void insertAlignmentCheck (LoadInst * LI); - void TransformFunction(Function &F); - void handleCallInst(CallInst *CI); - void handleGetElementPtr(GetElementPtrInst *MAI); - void addGetActualValue(SetCondInst *SCI, unsigned operand); - void registerAllocaInst(AllocaInst *AI, AllocaInst *AIOrig); - GlobalVariable * getOrCreateFunctionTable (DSNode * Node, Value * PH, Module * M); - void addExactCheck (Instruction * GEP, Value * Index, Value * Bound); - void addExactCheck (Value * Pointer, Value * Index, Value * Bound, Instruction * InsertPt); - void addExactCheck2 (Value * Base, Value * Result, Value * Bound, Instruction * InsertPt); - Value * addExactCheck3 (Value * Source, Value * Result, Value * Bound, Instruction * Next); - bool insertExactCheck (GetElementPtrInst * GEP); - bool insertExactCheck (Instruction * , Value *, Value *, Instruction *); - void insertFunctionCheck(CallInst* CI); - void insertICCheck (Value * Pointer, Instruction * InsertPt); - Value * insertBoundsCheck (Instruction * , Value *, Value *, Instruction *); - bool AggregateGEPs (GetElementPtrInst * GEP, std::set<Instruction *> & GEPs); - bool findCheckedPointer (Value * PointerOperand); - void addHeapRegs (Module & M); - + Function *PoolCheck; + Function *PoolCheckArray; + Function *ExactCheck; + Function *FunctionCheck; + void addPoolCheckProto(Module &M); + void addPoolChecks(Module &M); + void addGetElementPtrChecks(Module &M); + DSNode* getDSNode(const Value *V, Function *F); + unsigned getDSNodeOffset(const Value *V, Function *F); + void addLoadStoreChecks(Module &M); #ifndef LLVA_KERNEL - void addLSChecks(Value *Vnew, const Value *V, Instruction *I, Function *F); - Value * getPoolHandle(const Value *V, Function *F, PA::FuncInfo &FI, bool collapsed = false); - Value * getPoolHandle(const Value *V, Function *F, bool collapsed = false); + void addLSChecks(Value *Vnew, const Value *V, Instruction *I, Function *F); + Value * getPoolHandle(const Value *V, Function *F, PA::FuncInfo &FI, bool collapsed = false); + void registerGlobalArraysWithGlobalPools(Module &M); #else - Value* getPD(DSNode* N, Module& M) { - if (!N) return 0; - addMetaPools(M, N->getMP(), N); - if (N->getMP()) - return N->getMP()->getMetaPoolValue(); - else - return 0; - } - void addLSChecks(Value *V, Instruction *I, Function *F); - Value * getPoolHandle(const Value *V, Function *F); + void addLSChecks(Value *V, Instruction *I, Function *F); + Value * getPoolHandle(const Value *V, Function *F); #endif + }; } #endif
diff --git a/safecode/include/ProofWrap/ProofWrap.h b/safecode/include/ProofWrap/ProofWrap.h deleted file mode 100755 index 40b47b1..0000000 --- a/safecode/include/ProofWrap/ProofWrap.h +++ /dev/null
@@ -1,79 +0,0 @@ -#include <map> -#include <set> -#include <iterator> -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/Instructions.h" - -using namespace llvm; - -namespace { - struct ProofStrip : public ModulePass { - const Value* getProof(const Value* V) { - return stuff[V]; - } - - virtual bool runOnModule(Module &M); - - private: - void setProof(const Value* V, const Value* P) { - stuff[V] = P; - } - - std::map<const Value*, const Value*> stuff; - }; - - - - // call AddProof until you are done annotating - // then call Finalize - struct ProofPlace { - std::map<Value*, Value*> stuff; - - void AddProof(Value* V, Value* P) { - assert(isa<PointerType>(V->getType())); - assert(isa<ConstantInt>(P)); - stuff[V] = P; - } - - void AddProof(Value* V, unsigned P) { - AddProof(V, ConstantInt::get(Type::LongTy,P)); - } - - void Finalize(Module& M) { - //try to be semi clever - //find homes for values - BasicBlock* SomeBB; - std::map<std::pair<BasicBlock*, Value*>, std::set<Value*> > homes; - for (std::map<Value*, Value*>::iterator ii = stuff.begin(), - ee = stuff.end(); ii != ee; ++ii) { - Value* V = ii->first; - if (isa<GlobalValue>(V)) { - homes[std::make_pair((BasicBlock*)0, ii->second)].insert(V); - } else if (isa<Instruction>(V)) { - homes[std::make_pair(cast<Instruction>(V)->getParent(), ii->second)].insert(V); - SomeBB = cast<Instruction>(V)->getParent(); - } else { - V->dump(); - assert(0 && "Not supported"); - } - } - - //get proof function - std::vector<const Type * > FTV; - FTV.push_back(Type::LongTy); - FunctionType* FT = FunctionType::get(Type::VoidTy, FTV, true); - Function* F = M.getOrInsertFunction("llvm.proof.ptr", FT); - - //insert at end of BBs - for (std::map<std::pair<BasicBlock*, Value*>, std::set<Value*> >::iterator - ii = homes.begin(), ee = homes.end(); ii != ee; ++ii) { - BasicBlock* BB = ii->first.first ? ii->first.first : SomeBB; - std::vector<Value*> Args; - Args.push_back(ii->first.second); - std::copy(ii->second.begin(), ii->second.end(), std::back_insert_iterator<std::vector<Value*> > (Args)); - new CallInst(F, Args, "", BB->getTerminator()); - } - } - }; -}
diff --git a/safecode/include/SafeDynMemAlloc.h b/safecode/include/SafeDynMemAlloc.h index 3df7fcf..bd865e0 100755 --- a/safecode/include/SafeDynMemAlloc.h +++ b/safecode/include/SafeDynMemAlloc.h
@@ -9,8 +9,6 @@ #define LLVM_EMBEC_H -#include "dsa/DataStructure.h" -#include "dsa/DSGraph.h" #include "safecode/Config/config.h" #include "llvm/Pass.h" #include "poolalloc/PoolAllocate.h" @@ -21,6 +19,8 @@ #include "llvm/Support/CFG.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/ADT/VectorExtras.h" +#include "llvm/Analysis/DataStructure/DataStructure.h" +#include "llvm/Analysis/DataStructure/DSGraph.h" #include "llvm/Support/Debug.h" #include <set> #include <map>
diff --git a/safecode/include/StackSafety.h b/safecode/include/StackSafety.h index e9469da..56fbe0e 100755 --- a/safecode/include/StackSafety.h +++ b/safecode/include/StackSafety.h
@@ -7,10 +7,10 @@ #ifndef LLVM_STACKSAFETY_H #define LLVM_STACKSAFETY_H -#include "dsa/DataStructure.h" -#include "dsa/DSGraph.h" -#include "dsa/DSNode.h" #include "llvm/Pass.h" +#include "llvm/Analysis/DataStructure/DataStructure.h" +#include "llvm/Analysis/DataStructure/DSGraph.h" +#include "llvm/Analysis/DataStructure/DSNode.h" #include <set> namespace llvm {
diff --git a/safecode/include/safecode/Config/config.h.in b/safecode/include/safecode/Config/config.h.in index 419e798..ffe008e 100755 --- a/safecode/include/safecode/Config/config.h.in +++ b/safecode/include/safecode/Config/config.h.in
@@ -1,8 +1,5 @@ /* include/llvm/Config/config.h.in. Generated from autoconf/configure.ac by autoheader. */ -/* Define to 1 if you have the 'posix_memalign' function. */ -#undef HAVE_POSIX_MEMALIGN - /* Define if dlopen(0) will open the symbols of the program */ #undef CAN_DLOPEN_SELF
diff --git a/safecode/lib/InsertPoolChecks/Makefile b/safecode/lib/InsertPoolChecks/Makefile index 903a11d..788eac8 100755 --- a/safecode/lib/InsertPoolChecks/Makefile +++ b/safecode/lib/InsertPoolChecks/Makefile
@@ -2,6 +2,7 @@ LEVEL = ../../ SHARED_LIBRARY=1 +DONT_BUILD_RELINKED=1 LIBRARYNAME=addchecks include $(LEVEL)/Makefile.common
diff --git a/safecode/lib/InsertPoolChecks/insert.cpp b/safecode/lib/InsertPoolChecks/insert.cpp index 18418f5..95c0ed1 100755 --- a/safecode/lib/InsertPoolChecks/insert.cpp +++ b/safecode/lib/InsertPoolChecks/insert.cpp
@@ -1,62 +1,28 @@ -//===-- insert.cpp - Insert SAFECode Run-time Checks ----------------------===// -// -// SAFECode -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the insertion of SAFECode's run-time checks. -// -//===----------------------------------------------------------------------===// - #include "safecode/Config/config.h" #include "InsertPoolChecks.h" -#include "SCUtils.h" #include "llvm/Instruction.h" #include "llvm/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InstIterator.h" +#include <iostream> #include "llvm/ADT/VectorExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ConstantRange.h" -#include "llvm/Analysis/ScalarEvolutionExpander.h" -#include "llvm/Analysis/LoopInfo.h" -#include <iostream> -#include <vector> -#include <set> using namespace llvm; - extern Value *getRepresentativeMetaPD(Value *); +RegisterPass<InsertPoolChecks> ipc("safecode", "insert runtime checks"); -RegisterPass<PreInsertPoolChecks> pipc ("presafecode", "prepare for SAFECode"); -RegisterPass<InsertPoolChecks> ipc ("safecode", "insert runtime checks"); - -cl::opt<bool> EnableSplitChecks ("enable-splitchecks", cl::Hidden, - cl::init(false), - cl::desc("Split lookup and checks")); - -cl::opt<bool> InsertPoolChecksForArrays("boundschecks-usepoolchecks", - cl::Hidden, cl::init(false), - cl::desc("Insert pool checks instead of exact bounds checks")); - // Options for Enabling/Disabling the Insertion of Various Checks -cl::opt<bool> EnableUnknownChecks ("enable-unknownchecks", cl::Hidden, - cl::init(false), - cl::desc("Enable Checks on Incomplete/Unknown Nodes")); +cl::opt<bool> EnableIncompleteChecks ("enable-incompletechecks", cl::Hidden, + cl::init(false), + cl::desc("Enable Checks on Incomplete Nodes")); cl::opt<bool> EnableNullChecks ("enable-nullchecks", cl::Hidden, cl::init(false), cl::desc("Enable Checks on NULL Pools")); -cl::opt<bool> DisableRegisterGlobals ("disable-regglobals", cl::Hidden, - cl::init(false), - cl::desc("Do not register globals")); - cl::opt<bool> DisableLSChecks ("disable-lschecks", cl::Hidden, cl::init(false), cl::desc("Disable Load/Store Checks")); @@ -65,22 +31,10 @@ cl::init(false), cl::desc("Disable GetElementPtr(GEP) Checks")); -cl::opt<bool> DisableStackChecks ("disable-stackchecks", cl::Hidden, - cl::init(false), - cl::desc("Disable Stack Checks")); - -cl::opt<bool> DisableFuncChecks ("disable-funcchecks", cl::Hidden, - cl::init(false), - cl::desc("Disable Function Call Checks")); - cl::opt<bool> DisableIntrinsicChecks ("disable-intrinchecks", cl::Hidden, cl::init(false), cl::desc("Disable Intrinsic Checks")); -cl::opt<bool> EnableMonotonicOptimisation("enable-monotonic", cl::Hidden, - cl::init(false), - cl::desc("Enable LICM for bounds checks on monotonic loops")); - // Options for where to insert various initialization code cl::opt<string> InitFunctionName ("initfunc", cl::desc("Specify name of initialization " @@ -95,485 +49,49 @@ static Statistic<> MissChecks ("safecode", "Poolchecks omitted due to bad pool descriptor"); static Statistic<> PoolChecks ("safecode", "Poolchecks Added"); - -static Statistic<> FuncChecks ("safecode", "Indirect Call Checks Added"); -static Statistic<> MissedFuncChecks ("safecode", "Indirect Call Checks Missed"); -static Statistic<> SavedPoolChecks ("safecode", "Pool Checks Performed on Checked Pointers"); -static Statistic<> AlignChecks ("safecode", "Number of alignment checks required"); -static Statistic<> AlignLSChecks ("safecode", "Number of alignment on load/store checks required"); - -// Bounds Check Statistics -static Statistic<> BoundsChecks ("safecode", - "Total bounds checks inserted"); -static Statistic<> IBoundsChecks ("safecode", - "Bounds checks with incomplete DSNode"); -static Statistic<> UBoundsChecks ("safecode", - "Bounds checks with unknown DSNode"); -static Statistic<> ABoundsChecks ("safecode", - "Bounds checks with stack DSNode"); -static Statistic<> NullBoundsChecks ("safecode", - "Missed bounds checks - NULL pool handle"); -static Statistic<> NoSHGBoundsChecks ("safecode", - "Missed bounds checks - no SHG DSNode"); - +static Statistic<> BoundChecks("safecode", + "Bounds checks inserted"); static Statistic<> MissedIncompleteChecks ("safecode", "Poolchecks missed because of incompleteness"); static Statistic<> MissedMultDimArrayChecks ("safecode", "Multi-dimensional array checks"); +static Statistic<> MissedStackChecks ("safecode", "Missed stack checks"); static Statistic<> MissedGlobalChecks ("safecode", "Missed global checks"); static Statistic<> MissedNullChecks ("safecode", "Missed PD checks"); -// Exact Check Statistics -static Statistic<> ExactChecks ("safecode", "Exactchecks inserted"); -static Statistic<> ConstExactChecks ("safecode", "Omitted Exactchecks with constant arguments"); -static Statistic<> ZeroFuncChecks ("safecode", "Indirect Call Checks with Zero Targets"); - -// Object registration statistics -static Statistic<> StackRegisters ("safecode", "Stack registrations"); -static Statistic<> SavedRegAllocs ("safecode", "Stack registrations avoided"); +bool InsertPoolChecks::runOnModule(Module &M) { + cuaPass = &getAnalysis<ConvertUnsafeAllocas>(); + // budsPass = &getAnalysis<CompleteBUDataStructures>(); +#ifndef LLVA_KERNEL + paPass = &getAnalysis<PoolAllocate>(); + equivPass = &(paPass->getECGraphs()); + efPass = &getAnalysis<EmbeCFreeRemoval>(); + TD = &getAnalysis<TargetData>(); +#else + TDPass = &getAnalysis<TDDataStructures>(); +#endif -// Other statistics -static Statistic<> StructGEPsRemoved ("safecode", "Structure GEP Checks Removed"); + //add the new poolcheck prototype + addPoolCheckProto(M); +#ifndef LLVA_KERNEL + //register global arrays and collapsed nodes with global pools + registerGlobalArraysWithGlobalPools(M); +#endif + //Replace old poolcheck with the new one + addPoolChecks(M); -//MonotonicOpts -static Statistic<> MonotonicOpts ("safecode", "Number of monotonic LICM bounds check optimisations"); - -// The set of values that already have run-time checks -static std::set<Value *> CheckedValues; - -//////////////////////////////////////////////////////////////////////////// -// Static Functions -//////////////////////////////////////////////////////////////////////////// - -static inline bool -isNodeRegistered (DSNode * Node) { - // Do not perform checks on the pointer if its DSNode does not have a known - // allocation site. - if (!((Node->isAllocaNode()) || - (Node->isHeapNode()) || - (Node->isGlobalNode()))) { - ++NoSHGBoundsChecks; - return false; - } - + // + // Update the statistics. + // + PoolChecks = NullChecks + FullChecks; + return true; } -//Do not replace these with check results -static std::set<Value*> AddedValues; - -static GlobalVariable* -makeMetaPool(Module* M, DSNode* N) { - //Here we insert a global meta pool - //Now create a meta pool for this value, DSN Node - const Type * VoidPtrType = PointerType::get(Type::SByteTy); - std::vector<const Type*> MPTV; - for (int x = 0; x < 9; ++x) - MPTV.push_back(VoidPtrType); - // Add the types for the hit cache - MPTV.push_back(Type::UIntTy); - MPTV.push_back(ArrayType::get (Type::UIntTy, 4)); - MPTV.push_back(ArrayType::get (Type::UIntTy, 4)); - MPTV.push_back(ArrayType::get (VoidPtrType, 4)); - - const StructType* MPT = StructType::get(MPTV); - - static int x = 0; - std::string Name = "_metaPool_"; - - unsigned Flags = N ? N->getMP()->getFlags() : 0; - if(Flags & DSNode::Incomplete) - Name += "I"; - if(Flags & DSNode::UnknownNode) - Name += "U"; - if(Flags & DSNode::AllocaNode) - Name += "A"; - if(Flags & DSNode::GlobalNode) - Name += "G"; - if(Flags & DSNode::HeapNode) - Name += "H"; - if( N && N->isNodeCompletelyFolded()) - Name += "F"; - Name += "_"; - char c[100]; - snprintf(c, sizeof(c), "%d", x); - Name += c; - Name += "_"; - ++x; - - return new GlobalVariable( - /*type=*/ MPT, - /*isConstant=*/ false, - /*Linkage=*/ GlobalValue::InternalLinkage, - /*initializer=*/ Constant::getNullValue(MPT), - /*name=*/ Name, - /*parent=*/ M ); -} - #ifndef LLVA_KERNEL -Value * -PreInsertPoolChecks::getPoolHandle(const Value *V, Function *F, PA::FuncInfo &FI, bool collapsed) { - DSGraph &TDG = getDSGraph(*F); - const DSNode *Node = TDG.getNodeForValue((Value *)V).getNode(); - // Get the pool handle for this DSNode... - // assert(!Node->isUnknownNode() && "Unknown node \n"); - Type *VoidPtrType = PointerType::get(Type::SByteTy); - Type *PoolDescType = ArrayType::get(VoidPtrType, 50); - Type *PoolDescPtrTy = PointerType::get(PoolDescType); - if (!Node) { - return 0; //0 means there is no isse with the value, otherwise there will be a callnode - } - if (Node->isUnknownNode()) { - //FIXME this should be in a top down pass or propagated like collapsed pools below - if (!collapsed) { - unsigned offset = TDG.getNodeForValue((Value *)V).getOffset(); - assert((!offset) && " we don't handle middle of structs yet\n"); - return Constant::getNullValue(PoolDescPtrTy); - } - } - std::map<const DSNode*, Value*>::iterator I = FI.PoolDescriptors.find(Node); - map <Function *, set<Value *> > & - CollapsedPoolPtrs = efPass->CollapsedPoolPtrs; - - if (I != FI.PoolDescriptors.end()) { - // Check that the node pointed to by V in the TD DS graph is not - // collapsed - - if (!collapsed && CollapsedPoolPtrs.count(F)) { - Value *v = I->second; - if (CollapsedPoolPtrs[F].find(I->second) != CollapsedPoolPtrs[F].end()) { -#ifdef DEBUG - std::cerr << "Collapsed pools \n"; -#endif - return Constant::getNullValue(PoolDescPtrTy); - } else { - return v; - } - } else { - return I->second; - } - } - return 0; -} -#endif - -Value * -PreInsertPoolChecks::createPoolHandle (Module & M, DSNode * Node) { - // If there is no node, return NULL. - if (!Node) return 0; - - // Get the DSNode's MetaPool. If it doesn't have one, return NULL. - MetaPool * MP = Node->getMP(); - if (!MP) return 0; - - // If the MetaPool global variable has already been created, then simply - // return it. Otherwise, create one. - if (!(MP->getMetaPoolValue())) - MP->setMetaPoolValue (makeMetaPool (&M, Node)); - return (MP->getMetaPoolValue()); -} - - -Value * -PreInsertPoolChecks::createPoolHandle (const Value * V, Function * F) { - // - // Get the DSNode from the Top Down DSGraph. - // - DSGraph &TDG = getDSGraph(*F); - DSNode *Node = TDG.getNodeForValue((Value *)V).getNode(); - - // If there is no node, return NULL. - if (!Node) return 0; - - // Get the DSNode's MetaPool. If it doesn't have one, return NULL. - MetaPool * MP = Node->getMP(); - if (!MP) return 0; - - // If the MetaPool global variable has already been created, then simply - // return it. Otherwise, create one. - if (!(MP->getMetaPoolValue())) - MP->setMetaPoolValue (makeMetaPool (F->getParent(), Node)); - return (MP->getMetaPoolValue()); -} - -static void -AddCallToRegFunc (Function* F, GlobalVariable* GV, Function* PR, Value* PH, - Value* AllocSize) { - // - // First, make sure that we're not registering an external zero-sized global. - // These are caused by the following C construct and should never be checked: - // extern variable[]; - // - ConstantInt * C; - if (GV->isExternal()) - if ((C = dyn_cast<ConstantInt>(AllocSize)) && (!(C->getZExtValue()))) - return; - - const Type *VoidPtrType = PointerType::get(Type::SByteTy); - - assert(PH && "No PoolHandle for Global!"); - - BasicBlock::iterator InsertPt = F->getEntryBlock().begin(); - Instruction *GVCasted = new CastInst(GV, VoidPtrType, GV->getName()+"casted",InsertPt); - Value *PHCasted = new CastInst(PH, VoidPtrType, PH->getName()+"casted",InsertPt); - AllocSize = castTo (AllocSize, Type::UIntTy, InsertPt); - std::vector<Value *> args (1, PHCasted); - args.push_back (GVCasted); - args.push_back (AllocSize); - new CallInst(PR, args, "", InsertPt); -} - -//////////////////////////////////////////////////////////////////////////// -// Class: PreInsertPoolChecks -//////////////////////////////////////////////////////////////////////////// - -// -// Method: runOnModule() -// -// Description: -// This method is called by the pass manager. The job of this class is to -// create any global variables and inter-procedural changes that cannot be -// done in the doInitialization() method of the InsertPoolChecks class. -// -bool -PreInsertPoolChecks::runOnModule (Module & M) { - // Retrieve the analysis results from other passes - cuaPass = &getAnalysis<ConvertUnsafeAllocas>(); - TDPass = &getAnalysis<TDDataStructures>(); - TD = &getAnalysis<TargetData>(); - - // Add prototypes for the run-time checks to the module - addPoolCheckProto (M); - - // Register global arrays and collapsed nodes with global pools - if (!DisableRegisterGlobals) registerGlobalArraysWithGlobalPools(M); - - // - // Create a MetaPool global variable for every DSNode that we might - // encounter. - // - Module::iterator mI = M.begin(), mE = M.end(); - for ( ; mI != mE; ++mI) { - Function *F = mI; - - // Skip functions that are external - if (F->isExternal()) continue; - - // Skip the poolcheckglobals() function because it won't have a DSGraph - if (F->getName() == "poolcheckglobals") continue; - - // Create a MetaPool variable for each DSNode in the DSGraph. - DSGraph & TDG = getDSGraph(*F); - DSGraph::node_iterator NI = TDG.node_begin(), NE = TDG.node_end(); - while (NI != NE) { - addLinksNeedingAlignment (NI); - createPoolHandle (M, NI); - ++NI; - } - } -} - -// -// Method: getDSGraph() -// -// Description: -// Return the DSGraph for the given function. This method automatically -// selects the correct pass to query for the graph based upon whether we're -// doing user-space or kernel analysis. -// -DSGraph & -PreInsertPoolChecks::getDSGraph(Function & F) { -#ifndef LLVA_KERNEL - return equivPass->getDSGraph(F); -#else - return TDPass->getDSGraph(F); -#endif -} - -// -// Method: addLinksNeedingAlignment() -// -// Description: -// Determine if this DSNode has any pointers to DSNodes which will require -// alignment checks. If so, add those DSNodes to the set of DSNodes needing -// alignment checks. Note that we do not determine if the *given* node needs -// alignment checks. -// -void -PreInsertPoolChecks::addLinksNeedingAlignment (DSNode * Node) { - // - // Determine whether an alignment check is needed. This occurs when a DSNode - // is type unknown (collapsed) but has pointers to type known (uncollapsed) - // DSNodes. - // - if ((Node) && (Node->isNodeCompletelyFolded())) { - for (unsigned i = 0 ; i < Node->getNumLinks(); ++i) { - DSNode * LinkNode = Node->getLink(i).getNode(); - if (LinkNode && (!(LinkNode->isNodeCompletelyFolded()))) { - AlignmentNodes.insert (LinkNode); - } - } - } -} - -void -PreInsertPoolChecks::addPoolCheckProto(Module &M) { - const Type * VoidPtrType = PointerType::get(Type::SByteTy); -#if 0 - const Type *PoolDescType = ArrayType::get(VoidPtrType, 50); - // StructType::get(make_vector<const Type*>(VoidPtrType, VoidPtrType, - // Type::UIntTy, Type::UIntTy, 0)); - const Type * PoolDescTypePtr = PointerType::get(PoolDescType); -#endif - - std::vector<const Type *> Arg(1, VoidPtrType); - Arg.push_back(VoidPtrType); - FunctionType *PoolCheckTy = - FunctionType::get(Type::VoidTy,Arg, false); - PoolCheck = M.getOrInsertFunction("poolcheck", PoolCheckTy); - - std::vector<const Type *> Arg2(1, VoidPtrType); - Arg2.push_back(VoidPtrType); - Arg2.push_back(VoidPtrType); - FunctionType *PoolCheckArrayTy = - FunctionType::get(Type::VoidTy,Arg2, false); - PoolCheckArray = M.getOrInsertFunction("poolcheckarray", PoolCheckArrayTy); - PoolCheckIArray = M.getOrInsertFunction("poolcheckarray_i", PoolCheckArrayTy); - - - std::vector<const Type *> Arg3(1, VoidPtrType); - Arg3.push_back(VoidPtrType); //for output - Arg3.push_back(VoidPtrType); //for referent - FunctionType *BoundsCheckTy = FunctionType::get(VoidPtrType,Arg3, false); - BoundsCheck = M.getOrInsertFunction("pchk_bounds", BoundsCheckTy); - UIBoundsCheck = M.getOrInsertFunction("pchk_bounds_i", BoundsCheckTy); - - std::vector<const Type *> Arg4(1, VoidPtrType); - Arg4.push_back(VoidPtrType); - FunctionType *getBoundsTy = FunctionType::get(VoidPtrType,Arg4, false); - getBounds = M.getOrInsertFunction("getBounds", getBoundsTy); - UIgetBounds = M.getOrInsertFunction("getBounds_i", getBoundsTy); - - //Get the poolregister function - PoolRegister = M.getOrInsertFunction("pchk_reg_obj", Type::VoidTy, VoidPtrType, - VoidPtrType, Type::UIntTy, NULL); - StackRegister = M.getOrInsertFunction("pchk_reg_stack", Type::VoidTy, VoidPtrType, - VoidPtrType, Type::UIntTy, NULL); - ObjFree = M.getOrInsertFunction("pchk_drop_obj", Type::VoidTy, VoidPtrType, - VoidPtrType, NULL); - StackFree = M.getOrInsertFunction("pchk_drop_stack", Type::VoidTy, VoidPtrType, - VoidPtrType, NULL); - - FuncRegister = M.getOrInsertFunction("pchk_reg_func", Type::VoidTy, VoidPtrType, Type::UIntTy, PointerType::get(VoidPtrType), NULL); - - PoolFindMP = M.getOrInsertFunction("pchk_getLoc", VoidPtrType, VoidPtrType, NULL); - PoolRegMP = M.getOrInsertFunction("pchk_reg_pool", Type::VoidTy, VoidPtrType, VoidPtrType, VoidPtrType, NULL); - - std::vector<const Type *> FArg2(1, Type::IntTy); - FArg2.push_back(Type::IntTy); - FArg2.push_back(VoidPtrType); - FunctionType *ExactCheckTy = FunctionType::get(VoidPtrType, FArg2, false); - ExactCheck = M.getOrInsertFunction("exactcheck", ExactCheckTy); - - std::vector<const Type *> FArg3(1, Type::UIntTy); - FArg3.push_back(VoidPtrType); - FArg3.push_back(VoidPtrType); - FArg3.push_back(VoidPtrType); - FArg3.push_back(VoidPtrType); - FArg3.push_back(VoidPtrType); - FArg3.push_back(VoidPtrType); - FArg3.push_back(VoidPtrType); - FunctionType *FunctionCheckTy = FunctionType::get(Type::VoidTy, FArg3, true); - FunctionCheck = M.getOrInsertFunction("funccheck", FunctionCheckTy); - - std::vector<const Type *> FArg6(1, VoidPtrType); - FArg6.push_back(VoidPtrType); - FunctionType *FunctionCheckGTy = FunctionType::get(Type::VoidTy, FArg6, true); - FunctionCheckG = M.getOrInsertFunction("funccheck_g", FunctionCheckGTy); - - std::vector<const Type *> FArg9(1, Type::UIntTy); - FArg9.push_back(VoidPtrType); - FArg9.push_back(PointerType::get(VoidPtrType)); - FunctionType *FunctionCheckTTy = FunctionType::get(Type::VoidTy, FArg9, true); - FunctionCheckT = M.getOrInsertFunction("funccheck_t", FunctionCheckTTy); - - FArg9.clear(); - FArg9.push_back(VoidPtrType); - FunctionType *ICCheckTy = FunctionType::get(Type::VoidTy, FArg9, true); - ICCheck = M.getOrInsertFunction("pchk_iccheck", ICCheckTy); - - std::vector<const Type*> FArg5(1, VoidPtrType); - FArg5.push_back(VoidPtrType); - FunctionType *GetActualValueTy = FunctionType::get(VoidPtrType, FArg5, false); - GetActualValue = M.getOrInsertFunction("pchk_getActualValue", GetActualValueTy); - - std::vector<const Type*> FArg4(1, VoidPtrType); //base - FArg4.push_back(VoidPtrType); //result - FArg4.push_back(Type::UIntTy); //size - FunctionType *ExactCheck2Ty = FunctionType::get(VoidPtrType, FArg4, false); - ExactCheck2 = M.getOrInsertFunction("exactcheck2", ExactCheck2Ty); - - std::vector<const Type*> FArg7(1, VoidPtrType); //base - FArg7.push_back(VoidPtrType); //result - FArg7.push_back(VoidPtrType); //end - FunctionType *ExactCheck3Ty = FunctionType::get(VoidPtrType, FArg7, false); - ExactCheck3 = M.getOrInsertFunction("exactcheck3", ExactCheck3Ty); - - std::vector<const Type*> FArg8(1, VoidPtrType); //base - FunctionType *getBeginEndTy = FunctionType::get(VoidPtrType, FArg8, false); - getBegin = M.getOrInsertFunction("getBegin", getBeginEndTy); - getEnd = M.getOrInsertFunction("getEnd", getBeginEndTy); -} - -void -PreInsertPoolChecks::registerGlobalArraysWithGlobalPools(Module &M) { -#ifdef LLVA_KERNEL - - const Type *VoidPtrType = PointerType::get(Type::SByteTy); - const Type *PoolDescType = ArrayType::get(VoidPtrType, 50); - const Type *PoolDescPtrTy = PointerType::get(PoolDescType); - const Type* csiType = Type::getPrimitiveType(Type::UIntTyID); - - //Get the registration function - std::vector<const Type*> Vt; - const FunctionType* RFT = FunctionType::get(Type::VoidTy, Vt, false); - Function* RegFunc = M.getOrInsertFunction("poolcheckglobals", RFT); - if (RegFunc->empty()) { - BasicBlock* BB = new BasicBlock("reg", RegFunc); - new ReturnInst(BB); - } - - //Now iterate over globals and register all the arrays - DSGraph &G = TDPass->getGlobalsGraph(); - Module::global_iterator GI = M.global_begin(), GE = M.global_end(); - for ( ; GI != GE; ++GI) { - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GI)) { - if (GV->getType() != PoolDescPtrTy) { - GlobalValue * GVLeader = G.getScalarMap().getLeaderForGlobal(GV); - DSNode *DSN = G.getNodeForValue(GVLeader).getNode(); - if (((isa<ArrayType>(GV->getType()->getElementType())) || - (DSN && DSN->isNodeCompletelyFolded())) - && !isa<OpaqueType>(GV->getType()) - && !(isa<PointerType>(GV->getType()) && - isa<OpaqueType>(cast<PointerType>(GV->getType())->getElementType()))) { - Value * AllocSize; - if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) { - //std::cerr << "found global" << *GI << std::endl; - AllocSize = ConstantInt::get(csiType, - (AT->getNumElements() * TD->getTypeSize(AT->getElementType()))); - } else { - AllocSize = ConstantInt::get(csiType, TD->getTypeSize(GV->getType()->getElementType())); - } - Value* PH = getPD(DSN, M); - if (PH) - AddCallToRegFunc(RegFunc, GV, PoolRegister, PH, AllocSize); - } - } - } - } -#else +void InsertPoolChecks::registerGlobalArraysWithGlobalPools(Module &M) { Function *MainFunc = M.getMainFunction(); if (MainFunc == 0 || MainFunc->isExternal()) { std::cerr << "Cannot do array bounds check for this program" @@ -611,2764 +129,56 @@ } } - //Now iterate over globals and register all the arrays - Module::global_iterator GI = M.global_begin(), GE = M.global_end(); - for ( ; GI != GE; ++GI) { - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GI)) { - Type *VoidPtrType = PointerType::get(Type::SByteTy); - Type *PoolDescType = ArrayType::get(VoidPtrType, 50); - Type *PoolDescPtrTy = PointerType::get(PoolDescType); - if (GV->getType() != PoolDescPtrTy) { - DSGraph &G = equivPass->getGlobalsGraph(); - DSNode *DSN = G.getNodeForValue(GV).getNode(); - if ((isa<ArrayType>(GV->getType()->getElementType())) || - DSN->isNodeCompletelyFolded()) { - Value * AllocSize; - const Type* csiType = Type::getPrimitiveType(Type::UIntTyID); - if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) { - //std::cerr << "found global" << *GI << std::endl; - AllocSize = ConstantInt::get(csiType, - (AT->getNumElements() * TD->getTypeSize(AT->getElementType()))); - } else { - AllocSize = ConstantInt::get(csiType, TD->getTypeSize(GV->getType())); - } - Function *PoolRegister = paPass->PoolRegister; - BasicBlock::iterator InsertPt = MainFunc->getEntryBlock().begin(); - //skip the calls to poolinit - while ((isa<CallInst>(InsertPt)) || - isa<CastInst>(InsertPt) || - isa<AllocaInst>(InsertPt) || - isa<BinaryOperator>(InsertPt)) ++InsertPt; - - std::map<const DSNode *, Value *>::iterator I = paPass->GlobalNodes.find(DSN); - if (I != paPass->GlobalNodes.end()) { - Value *PH = I->second; - Instruction *GVCasted = new CastInst(GV, - VoidPtrType, GV->getName()+"casted",InsertPt); - new CallInst(PoolRegister, - make_vector(PH, AllocSize, GVCasted, 0), - "", InsertPt); - } else { - std::cerr << "pool descriptor not present \n "; - abort(); - } - } - } - } - } -#endif -} - -//////////////////////////////////////////////////////////////////////////// -// Class: InsertPoolChecks -//////////////////////////////////////////////////////////////////////////// - -void -InsertPoolChecks::addPoolCheckProto(Module &M) { - const Type * VoidPtrType = PointerType::get(Type::SByteTy); -#if 0 - const Type *PoolDescType = ArrayType::get(VoidPtrType, 50); - // StructType::get(make_vector<const Type*>(VoidPtrType, VoidPtrType, - // Type::UIntTy, Type::UIntTy, 0)); - const Type * PoolDescTypePtr = PointerType::get(PoolDescType); -#endif - - std::vector<const Type *> Arg(1, VoidPtrType); - Arg.push_back(VoidPtrType); - FunctionType *PoolCheckTy = - FunctionType::get(Type::VoidTy,Arg, false); - PoolCheck = M.getOrInsertFunction("poolcheck", PoolCheckTy); - PoolCheckUI = M.getOrInsertFunction("poolcheck_i", PoolCheckTy); - - Arg.clear(); - Arg.push_back(VoidPtrType); - Arg.push_back(VoidPtrType); - Arg.push_back(Type::UIntTy); - PoolCheckTy = FunctionType::get(Type::VoidTy,Arg, false); - PoolCheckAlign = M.getOrInsertFunction("poolcheckalign", PoolCheckTy); - PoolCheckAlignUI = M.getOrInsertFunction("poolcheckalign_i", PoolCheckTy); - - std::vector<const Type *> Arg2(1, VoidPtrType); - Arg2.push_back(VoidPtrType); - Arg2.push_back(VoidPtrType); - FunctionType *PoolCheckArrayTy = - FunctionType::get(Type::VoidTy,Arg2, false); - PoolCheckArray = M.getOrInsertFunction("poolcheckarray", PoolCheckArrayTy); - PoolCheckIArray = M.getOrInsertFunction("poolcheckarray_i", PoolCheckArrayTy); - - - std::vector<const Type *> Arg3(1, VoidPtrType); - Arg3.push_back(VoidPtrType); //for output - Arg3.push_back(VoidPtrType); //for referent - FunctionType *BoundsCheckTy = FunctionType::get(VoidPtrType,Arg3, false); - BoundsCheck = M.getOrInsertFunction("pchk_bounds", BoundsCheckTy); - UIBoundsCheck = M.getOrInsertFunction("pchk_bounds_i", BoundsCheckTy); - - std::vector<const Type *> Arg4(1, VoidPtrType); - Arg4.push_back(VoidPtrType); - FunctionType *getBoundsTy = FunctionType::get(VoidPtrType,Arg4, false); - getBounds = M.getOrInsertFunction("getBounds", getBoundsTy); - UIgetBounds = M.getOrInsertFunction("getBounds_i", getBoundsTy); - - //Get the poolregister function - PoolRegister = M.getOrInsertFunction("pchk_reg_obj", Type::VoidTy, VoidPtrType, - VoidPtrType, Type::UIntTy, NULL); - StackRegister = M.getOrInsertFunction("pchk_reg_stack", Type::VoidTy, VoidPtrType, - VoidPtrType, Type::UIntTy, NULL); - ObjFree = M.getOrInsertFunction("pchk_drop_obj", Type::VoidTy, VoidPtrType, - VoidPtrType, NULL); - StackFree = M.getOrInsertFunction("pchk_drop_stack", Type::VoidTy, VoidPtrType, - VoidPtrType, NULL); - - FuncRegister = M.getOrInsertFunction("pchk_reg_func", Type::VoidTy, VoidPtrType, Type::UIntTy, PointerType::get(VoidPtrType), NULL); - - PoolFindMP = M.getOrInsertFunction("pchk_getLoc", VoidPtrType, VoidPtrType, NULL); - PoolRegMP = M.getOrInsertFunction("pchk_reg_pool", Type::VoidTy, VoidPtrType, VoidPtrType, VoidPtrType, NULL); - - // Function *KmemCacheAlloc = M.getNamedFunction("kmem_cache_alloc"); - // assert(KmemCacheAlloc->arg_size() == 2 &&"Kmem_cache_alloc number of arguments != 2"); - // Function::arg_iterator kcai = KmemCacheAlloc->arg_begin(); - // Type *kmem_cache_t = kcai->getType(); - // kcai++; - // Type *kem_cache_size_t = kcai->getType(); - // We'll use Void * instead of the above - KmemCachegetSize = M.getOrInsertFunction("kmem_cache_size", Type::UIntTy, VoidPtrType, NULL); - - std::vector<const Type *> FArg2(1, Type::IntTy); - FArg2.push_back(Type::IntTy); - FArg2.push_back(VoidPtrType); - FunctionType *ExactCheckTy = FunctionType::get(VoidPtrType, FArg2, false); - ExactCheck = M.getOrInsertFunction("exactcheck", ExactCheckTy); - - std::vector<const Type *> FArg3(1, Type::UIntTy); - FArg3.push_back(VoidPtrType); - FArg3.push_back(VoidPtrType); - FunctionType *FunctionCheckTy = FunctionType::get(Type::VoidTy, FArg3, true); - FunctionCheck = M.getOrInsertFunction("funccheck", FunctionCheckTy); - - std::vector<const Type *> FArg6(1, VoidPtrType); - FArg6.push_back(VoidPtrType); - FunctionType *FunctionCheckGTy = FunctionType::get(Type::VoidTy, FArg6, true); - FunctionCheckG = M.getOrInsertFunction("funccheck_g", FunctionCheckGTy); - - std::vector<const Type *> FArg9(1, Type::UIntTy); - FArg9.push_back(VoidPtrType); - FArg9.push_back(PointerType::get(VoidPtrType)); - FunctionType *FunctionCheckTTy = FunctionType::get(Type::VoidTy, FArg9, true); - FunctionCheckT = M.getOrInsertFunction("funccheck_t", FunctionCheckTTy); - - FArg9.clear(); - FArg9.push_back(VoidPtrType); - FunctionType *ICCheckTy = FunctionType::get(Type::VoidTy, FArg9, true); - ICCheck = M.getOrInsertFunction("pchk_iccheck", ICCheckTy); - - std::vector<const Type*> FArg5(1, VoidPtrType); - FArg5.push_back(VoidPtrType); - FunctionType *GetActualValueTy = FunctionType::get(VoidPtrType, FArg5, false); - GetActualValue = M.getOrInsertFunction("pchk_getActualValue", GetActualValueTy); - - std::vector<const Type*> FArg4(1, VoidPtrType); //base - FArg4.push_back(VoidPtrType); //result - FArg4.push_back(Type::UIntTy); //size - FunctionType *ExactCheck2Ty = FunctionType::get(VoidPtrType, FArg4, false); - ExactCheck2 = M.getOrInsertFunction("exactcheck2", ExactCheck2Ty); - - std::vector<const Type*> FArg7(1, VoidPtrType); //base - FArg7.push_back(VoidPtrType); //result - FArg7.push_back(VoidPtrType); //end - FunctionType *ExactCheck3Ty = FunctionType::get(VoidPtrType, FArg7, false); - ExactCheck3 = M.getOrInsertFunction("exactcheck3", ExactCheck3Ty); - - std::vector<const Type*> FArg8(1, VoidPtrType); //base - FunctionType *getBeginEndTy = FunctionType::get(VoidPtrType, FArg8, false); - getBegin = M.getOrInsertFunction("getBegin", getBeginEndTy); - getEnd = M.getOrInsertFunction("getEnd", getBeginEndTy); -} - - -void -InsertPoolChecks::addHeapRegs (Module & M) { - DSNode * Node; - MetaPool * MP; - const Type * VoidPtrType = PointerType::get(Type::SByteTy); - std::set<Value *> ProcessedMetaPools; - std::vector<Value *> args; - - while (PHNeeded.size()) { - Node = *(PHNeeded.begin()); - PHNeeded.erase(Node); - MP = Node->getMP(); - Value* MPV = MP->getMetaPoolValue(); - - // - // Determine if we have already processed this MetaPool. If we have, then - // just go on to the next DSNode. - if (ProcessedMetaPools.find (MPV) == ProcessedMetaPools.end()) - ProcessedMetaPools.insert (MPV); - else - continue; - - // Add registers in front of every allocation - for (std::list<CallSite>::iterator i = MP->allocs.begin(), - e = MP->allocs.end(); i != e; ++i) { - args.clear(); - std::string name = i->getCalledFunction()->getName(); - if (name == "kmem_cache_alloc") { - Instruction * InsertPt = i->getInstruction(); - //insert a register before - Value* VP = castTo (i->getArgument(0), VoidPtrType, InsertPt); - Value* VMP = castTo (MPV, VoidPtrType, InsertPt); - Value* VMPP = new CallInst(PoolFindMP, VP, "", InsertPt); - - args.push_back (VMP); - args.push_back (VP); - args.push_back (VMPP); - new CallInst (PoolRegMP, args, "", i->getInstruction()); - - //Insert Obj reg using kmem_cache_size after - Instruction* IP = i->getInstruction()->getNext(); - Value* VRP = castTo (i->getInstruction(), VoidPtrType, IP); - CallInst *len = new CallInst(KmemCachegetSize, VP, "", IP); - - args.clear(); - args.push_back (VMP); //MetaPool - args.push_back (VRP); //object - args.push_back (len); //len - new CallInst(PoolRegister, args, "", IP); - -#if 0 - } else if ((name == "kmalloc") || -#else - } else if ( -#endif - (name == "__vmalloc") || - (name == "__alloc_bootmem")) { - //inser obj register after - Instruction* IP = i->getInstruction()->getNext(); - Value* VP = castTo (i->getInstruction(), VoidPtrType, IP); - Value* VMP = castTo (MPV, VoidPtrType, IP); - Value* len = castTo (i->getArgument(0), Type::UIntTy, IP); - - args.push_back (VMP); - args.push_back (VP); - args.push_back (len); - new CallInst(PoolRegister, args, "", IP); - } else - assert(0 && "unknown alloc"); - } - } -} - -void InsertPoolChecks::addMetaPools(Module& M, MetaPool* MP, DSNode* N) { - if (!MP || MP->getMetaPoolValue()) return; - MP->setMetaPoolValue(makeMetaPool(&M, N)); - Value* MPV = MP->getMetaPoolValue(); - //added registers in front of every allocation - for(std::list<CallSite>::iterator i = MP->allocs.begin(), - e = MP->allocs.end(); i != e; ++i) { - std::string name = i->getCalledFunction()->getName(); - if (name == "kmem_cache_alloc") { - //insert a register before - Value* VP = new CastInst(i->getArgument(0), PointerType::get(Type::SByteTy), "", i->getInstruction()); - Value* VMP = new CastInst(MPV, PointerType::get(Type::SByteTy), "MP", i->getInstruction()); - Value* VMPP = new CallInst(PoolFindMP, make_vector(VP, 0), "", i->getInstruction()); - new CallInst(PoolRegMP, make_vector(VMP, VP, VMPP, 0), "", i->getInstruction()); -#if 0 - } else if ((name == "kmalloc") || -#else - } else if ( -#endif - (name == "__vmalloc") || - (name == "__alloc_bootmem")) { - //inser obj register after - Instruction* IP = i->getInstruction()->getNext(); - Value* VP = new CastInst(i->getInstruction(), PointerType::get(Type::SByteTy), "", IP); - Value* VMP = new CastInst(MPV, PointerType::get(Type::SByteTy), "MP", IP); - Value* len = new CastInst(i->getArgument(0), Type::UIntTy, "len", IP); - new CallInst(PoolRegister, make_vector(VMP, VP, len, 0), "", IP); - } else - assert(0 && "unknown alloc"); - } -} - -void InsertPoolChecks::addObjFrees(Module& M) { -#ifdef LLVA_KERNEL -#if 0 - Function* KMF = M.getNamedFunction("kfree"); -#endif - Function* VMF = M.getNamedFunction("vfree"); - std::list<Function*> L; -#if 0 - if (KMF) L.push_back(KMF); -#endif - if (VMF) L.push_back(VMF); - for (std::list<Function*>::iterator ii = L.begin(), ee = L.end(); - ii != ee; ++ii) { - Function* F = *ii; - for (Value::use_iterator ii = F->use_begin(), ee = F->use_end(); - ii != ee; ++ii) { - if (CallInst* CI = dyn_cast<CallInst>(*ii)) { - if (CI->getCalledFunction() == F) { - Value* Ptr = CI->getOperand(1); - Value* MP = getPD(getDSNode(Ptr, CI->getParent()->getParent()), M); - if (MP) { - MP = new CastInst(MP, PointerType::get(Type::SByteTy), "MP", CI); - Ptr = new CastInst(Ptr, PointerType::get(Type::SByteTy), "ADDR", CI); - new CallInst(ObjFree, make_vector(MP, Ptr, 0), "", CI); - } - } - } - } - } -#endif -} - -// -// Method: insertICCheck() -// -// Description: -// Perform a run-time check to ensure that this pointer points to the -// beginning of an interrupt context. -// -void -InsertPoolChecks::insertICCheck (Value * IC, Instruction * InsertPt) { - const Type * VoidPtrType = PointerType::get(Type::SByteTy); - Value * CastPointer = castTo (IC, VoidPtrType, InsertPt); - new CallInst (ICCheck, CastPointer, "", InsertPt); -} - -// -// Return value: -// Returns the inserted boundscheck call instruction. This can be used to -// replace the destination instruction if desired. -// If no instruction was inserted, it returns Dest. -// -Value * -InsertPoolChecks::insertBoundsCheck (Instruction * I, - Value * Src, - Value * Dest, - Instruction * InsertPt) { - // Enclosing function - Function * F = I->getParent()->getParent(); - Function *Fnew = F; - - // Source node on which we will look up the pool handle - Value *newSrc = Src; - -#ifndef LLVA_KERNEL -#ifdef NOEQUIV - // Some times the ECGraphs doesnt contain F for newly created cloned - // functions - if (!equivPass->ContainsDSGraphFor(*F)) { - PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F); - newSrc = FI->MapValueToOriginal(Src); - Instruction * Inew = FI->MapValueToOriginal(I); - assert(newSrc && " Instruction not in value map (clone)\n"); - } - Fnew = Inew->getParent()->getParent(); -#endif -#endif - - // - // Get the pool handle for the source pointer. - // - Value *PH = getPoolHandle(newSrc, Fnew); - if (!PH) { - // Update statistics - ++NullBoundsChecks; - return Dest; - } - - // - // Get the DSGraph of the enclosing function and get the corresponding - // DSNode. - // - DSGraph & TDG = getDSGraph(*F); - DSNode * Node = TDG.getNodeForValue(I).getNode(); - - // - // Determine whether an alignment check is needed. This occurs when a DSNode - // is type unknown (collapsed) but has pointers to type known (uncollapsed) - // DSNodes. - // - if (preSCPass->nodeNeedsAlignment (Node)) { - ++AlignChecks; - } - - // If there is no DSNode, do not perform a check - if (!Node) return Dest; - - // If we do not know the allocation site, don't bother checking it - if (!(isNodeRegistered (Node))) - return Dest; - - // Record statistics on the incomplete checks we do. Note that a node may - // be counted more than once. - if (Node->isIncomplete()) - ++IBoundsChecks; - if (Node->isUnknownNode()) - ++UBoundsChecks; - if (Node->isAllocaNode()) - ++ABoundsChecks; - - // - // Cast the pool handle, source and destination pointers into the correct - // type for the call instruction. - // - Value * SrcCast = Src; - Value * DestCast = Dest; - if (Src->getType() != PointerType::get(Type::SByteTy)) - SrcCast = new CastInst (Src, PointerType::get(Type::SByteTy), - "castsrc", InsertPt); - if (Dest->getType() != PointerType::get(Type::SByteTy)) - DestCast = new CastInst (Dest, PointerType::get(Type::SByteTy), - "castdst", InsertPt); - if (PH->getType() != PointerType::get(Type::SByteTy)) - PH = new CastInst (PH, PointerType::get(Type::SByteTy), - "castph", InsertPt); - - AddedValues.insert(DestCast); - - // - // Insert the bounds check. - // - Value * CI; - if (EnableSplitChecks) { - std::vector<Value *> args(1, PH); - args.push_back (SrcCast); - if ((Node == 0) || - (Node->isAllocaNode()) || - (Node->isIncomplete()) || - (Node->isUnknownNode())) - CI = new CallInst(UIgetBounds, args, "uibc",InsertPt); - else - CI = new CallInst(getBounds, args, "bc", InsertPt); - std::vector<Value *> boundsargs(1, CI); - Instruction * LowerBound = new CallInst(getBegin, boundsargs, "gb", InsertPt); - Instruction * UpperBound = new CallInst(getEnd, boundsargs, "ge", InsertPt); - Value * EC3 = addExactCheck3 (LowerBound, DestCast, UpperBound, InsertPt); - AddedValues.insert(EC3); - if (EC3->getType() != Dest->getType()) - EC3 = new CastInst(EC3, Dest->getType(), EC3->getName(), InsertPt); - AddedValues.insert(EC3); - // Replace all uses of the original pointer with the result of the exactcheck. - // This ensures that the check will not get dead code eliminated. - Value::use_iterator UI = Dest->use_begin(); - for (; UI != Dest->use_end(); ++UI) { - if (AddedValues.find(*UI) == AddedValues.end()) - UI->replaceUsesOfWith (Dest,EC3); - } - CI = EC3; - } else { - std::vector<Value *> args(1, PH); - args.push_back (SrcCast); - args.push_back (DestCast); - if ((Node == 0) || - (Node->isAllocaNode()) || - (Node->isIncomplete()) || - (Node->isUnknownNode())) - CI = new CallInst(UIBoundsCheck, args, "uibc",InsertPt); - else - CI = new CallInst(BoundsCheck, args, "bc", InsertPt); - } - - // - // Record that this value was checked. - // - CheckedValues.insert (Dest); - CheckedValues.insert (CI); - - // Update statistics - ++BoundsChecks; - return CI; -} - -// -// Method: getOrCreateFunctionTable() -// -// Description: -// Given a DSNode, return a global variable containing an array of the -// function pointers within that DSNode. If this global variable does not -// exist, create it and modify poolcheckglobals() to register it with its -// MetaPool. -// -GlobalVariable * -InsertPoolChecks::getOrCreateFunctionTable (DSNode * Node, Value * PH, - Module * M) { - // Determine if we have already created such a global. - if (FuncListMap.count (PH)) { - return FuncListMap[PH]; - } - - // Get the globals list corresponding to the node - std::vector<Function *> FuncList; - Node->addFullFunctionList(FuncList); - unsigned num = FuncList.size(); - - // Create a global array of void pointers containing the list of possible - // function targets. - std::vector<Function *>::iterator flI= FuncList.begin(), flE = FuncList.end(); - const Type* csiType = Type::getPrimitiveType(Type::UIntTyID); - Value *NumArg = ConstantInt::get(csiType, num); - Type *VoidPtrType = PointerType::get(Type::SByteTy); - std::vector<Constant *> Targets; - - for (; flI != flE ; ++flI) { - Function *func = *flI; - Constant *CastfuncI = ConstantExpr::getCast (func, VoidPtrType); - Targets.push_back(CastfuncI); - } - - ArrayType * TableType = ArrayType::get (VoidPtrType, num); - Constant * TableInit = ConstantArray::get (TableType, Targets); - GlobalVariable * Table = new GlobalVariable (TableType, true, GlobalValue::InternalLinkage, TableInit, "functargets", M); - Value * TableCast = ConstantExpr::getCast (Table, PointerType::get(VoidPtrType)); - - // - // Add an instruction to poolcheckglobals() to register this table of - // functions with the MetaPool. - // - std::vector<const Type*> Vt; - const FunctionType* RFT = FunctionType::get(Type::VoidTy, Vt, false); - Function * RegFunc = M->getOrInsertFunction("poolcheckglobals", RFT); - BasicBlock* BB; - if (RegFunc->empty()) { - BasicBlock* BB = new BasicBlock("reg", RegFunc); - new ReturnInst(BB); - } else { - BB = &(RegFunc->getEntryBlock()); - } - - Instruction * InsertPt = BB->getTerminator(); - Value * CastPH = new CastInst(PH, VoidPtrType, "casted", InsertPt); - std::vector<Value *> args; - args.push_back (CastPH); - args.push_back (NumArg); - args.push_back (TableCast); - new CallInst(FuncRegister, args, "", InsertPt); - - // - // Insert the DSNode and Table into the map. - // - FuncListMap.insert (make_pair(PH,Table)); - return Table; -} - -// -// Method: insertFunctionCheck() -// -// Description: -// Insert a run-time check on the argument to an indirect call instruction. -// -void -InsertPoolChecks::insertFunctionCheck (CallInst * CI) { - if (DisableFuncChecks) - return; - - // Get the containing function and the function pointer. - Function * F = CI->getParent()->getParent(); - Value * FuncPointer = CI->getCalledValue(); - - // Try to remove any encapsulating casts to get to the original instruction - ConstantExpr *cExpr; - while ((cExpr = dyn_cast<ConstantExpr>(FuncPointer)) && - (cExpr->getOpcode() == Instruction::Cast)) - FuncPointer = cExpr->getOperand(0); - - // - // Determine if the function pointer came from a load instruction that loaded - // its value from a type known pool. If it is, it does not need a check. - // - if (LoadInst * LI = dyn_cast<LoadInst>(FuncPointer)) { - DSNode * LoadNode = getDSNode (LI->getPointerOperand(), F); - if ((LoadNode) && (!(LoadNode->isNodeCompletelyFolded()))) - return; - } - - // - // Get the DSNode and Pool handle for the call instruction. - // - Value *PH = getPoolHandle (FuncPointer, F); - if (!PH) { - // Update statistics - ++NullBoundsChecks; - return; - } - DSNode* Node = getDSNode(FuncPointer, F); - - // - // If the node is incomplete, then the call targets associated with the - // DSNode may be missing valid function targets. In that case, do not - // insert a check. - // - if ((!EnableUnknownChecks) && (Node->isIncomplete())) { - ++MissedFuncChecks; - return; - } - - // Get the globals list corresponding to the node - std::vector<Function *> FuncList; - Node->addFullFunctionList(FuncList); - unsigned num = FuncList.size(); - - // - // Insert a call to one of the function check functions, depending upon - // the number of functions we must check against. - // - if (num == 0) { - ++ZeroFuncChecks; - return; - } - - // Update statistics on the number of indirect call checks. - ++FuncChecks; - - std::vector<Function *>::iterator flI= FuncList.begin(), flE = FuncList.end(); - const Type* csiType = Type::getPrimitiveType(Type::UIntTyID); - Value *NumArg = ConstantInt::get(csiType, num); - Type *VoidPtrType = PointerType::get(Type::SByteTy); - - if (num < 7) { - const Type* csiType = Type::getPrimitiveType(Type::UIntTyID); - Value *NumArg = ConstantInt::get(csiType, num); - - CastInst *CastVI = - new CastInst(FuncPointer, VoidPtrType, "casted", (Instruction *)(CI)); - - std::vector<Value *> args(1, NumArg); - args.push_back(CastVI); - for (; flI != flE ; ++flI) { - Function *func = *flI; - CastInst *CastfuncI = - new CastInst(func, VoidPtrType, "casted", (Instruction *)(CI)); - args.push_back(CastfuncI); - } - for (unsigned index = num; index < 7; ++index) - args.push_back (ConstantPointerNull::get (PointerType::get (Type::SByteTy))); - new CallInst(FunctionCheck, args,"", (Instruction *)(CI)); - } else if (num < 21) { - // Create the first two arguments for the function check call - std::vector<Value *> args(1, NumArg); - CastInst *CastVI = - new CastInst(FuncPointer, VoidPtrType, "casted", (Instruction *)(CI)); - args.push_back(CastVI); - - // Create a global array of void pointers containing the list of possible - // function targets. - GlobalVariable * Table = getOrCreateFunctionTable (Node, PH, F->getParent()); - - CastInst *CastTable = - new CastInst(Table, - PointerType::get(VoidPtrType), "casted", (Instruction *)(CI)); - - args.push_back(CastTable); - new CallInst(FunctionCheckT, args, "", (Instruction *)(CI)); - } else { - // Create a global array of void pointers containing the list of possible - // function targets. - getOrCreateFunctionTable (Node, PH, F->getParent()); - - // Create the first two arguments for the function check call - PH = new CastInst (PH, VoidPtrType, "casted", (Instruction *)(CI)); - CastInst *CastVI = - new CastInst(FuncPointer, VoidPtrType, "casted", (Instruction *)(CI)); - std::vector<Value *> args(1, PH); - args.push_back(CastVI); - - new CallInst(FunctionCheckG, args,"", (Instruction *)(CI)); - } -} - -// -// Function: addExactCheck2() -// -// Description: -// Utility routine that inserts a call to exactcheck2(). -// -// Inputs: -// BasePointer - An LLVM Value representing the base of the object to check. -// Result - An LLVM Value representing the pointer to check. -// Bounds - An LLVM Value representing the bounds of the check. -// InsertPt - The instruction before which to insert the check. -// -void -InsertPoolChecks::addExactCheck2 (Value * BasePointer, - Value * Result, - Value * Bounds, - Instruction * InsertPt) { - Value * ResultPointer = Result; - - // The LLVM type for a void * - Type *VoidPtrType = PointerType::get(Type::SByteTy); - - // - // Cast the operands to the correct type. - // - if (BasePointer->getType() != VoidPtrType) - BasePointer = new CastInst(BasePointer, VoidPtrType, - BasePointer->getName()+".ec2.casted", - InsertPt); - - if (ResultPointer->getType() != VoidPtrType) - ResultPointer = new CastInst(ResultPointer, VoidPtrType, - ResultPointer->getName()+".ec2.casted", - InsertPt); - - Value * CastBounds = Bounds; - if (Bounds->getType() != Type::UIntTy) - CastBounds = new CastInst(Bounds, Type::UIntTy, - Bounds->getName()+".ec.casted", InsertPt); - - // - // Create the call to exactcheck2(). - // - std::vector<Value *> args(1, BasePointer); - args.push_back(ResultPointer); - args.push_back(CastBounds); - Instruction * CI; - CI = new CallInst(ExactCheck2, args, "", InsertPt); - - // - // Record that this value was checked. - // - CheckedValues.insert (Result); - -#if 0 - // - // Replace the old pointer with the return value of exactcheck2(); this - // prevents GCC from removing it completely. - // - if (CI->getType() != GEP->getType()) - CI = new CastInst (CI, GEP->getType(), GEP->getName(), InsertPt); - - Value::use_iterator UI = GEP->use_begin(); - for (; UI != GEP->use_end(); ++UI) { - if (((*UI) != CI) && ((*UI) != ResultPointer)) - UI->replaceUsesOfWith (GEP, CI); - } -#endif - - // Update statistics - ++ExactChecks; - return; -} - -// -// Function: addExactCheck3() -// -// Description: -// Utility routine that inserts a call to exactcheck3(). -// -// Inputs: -// Source - The pointer that is the lower bound of the array. -// Result - The pointer that we wish to check. -// Bounds - The length of the array in bytes. -// InsertPt - The instruction before which to insert the check. -// -Value * -InsertPoolChecks::addExactCheck3 (Value * Source, - Value * Result, - Value * Bounds, - Instruction * InsertPt) { - // The LLVM type for a void * - Type *VoidPtrType = PointerType::get(Type::SByteTy); - - // Update statistics - ++ExactChecks; - - // - // Cast the operands to the correct type. - // - Value * BasePointer = Source; - if (BasePointer->getType() != VoidPtrType) - BasePointer = new CastInst(BasePointer, VoidPtrType, - BasePointer->getName()+".ec3.base.casted", - InsertPt); - - Value * ResultPointer = Result; - if (ResultPointer->getType() != VoidPtrType) - ResultPointer = new CastInst(Result, VoidPtrType, - Result->getName()+".ec3.result.casted", - InsertPt); - - Value * CastBounds = Bounds; - if (Bounds->getType() != VoidPtrType) - CastBounds = new CastInst(Bounds, VoidPtrType, - Bounds->getName()+".ec3.end.casted", InsertPt); - - std::vector<Value *> args(1, BasePointer); - args.push_back(ResultPointer); - args.push_back(CastBounds); - - // - // Record that this value was checked. - // - CheckedValues.insert (Result); - return new CallInst(ExactCheck3, args, "ec3", InsertPt); -} - -// -// Function: addExactCheck() -// -// Description: -// Utility routine that inserts a call to exactcheck(). This function can -// perform some optimization be determining if the arguments are constant. -// If they are, we can forego inserting the call. -// -// Inputs: -// Index - An LLVM Value representing the index of the access. -// Bounds - An LLVM Value representing the bounds of the check. -// -void -InsertPoolChecks::addExactCheck (Value * Pointer, - Value * Index, Value * Bounds, - Instruction * InsertPt) { - // - // Record that this value was checked. - // - CheckedValues.insert (Pointer); - - // - // Attempt to determine statically if this check will always pass; if so, - // then don't bother doing it at run-time. - // - ConstantInt * CIndex = dyn_cast<ConstantInt>(Index); - ConstantInt * CBounds = dyn_cast<ConstantInt>(Bounds); - if (CIndex && CBounds) { - int index = CIndex->getSExtValue(); - int bounds = CBounds->getSExtValue(); - assert ((index >= 0) && "exactcheck: const negative index"); - assert ((index < bounds) && "exactcheck: const out of range"); - - // Update stats and return - ++ConstExactChecks; - return; - } - - // - // Second, cast the operands to the correct type. - // - Value * CastIndex = Index; - if (Index->getType() != Type::IntTy) - CastIndex = new CastInst(Index, Type::IntTy, - Index->getName()+".ec.casted", InsertPt); - - Value * CastBounds = Bounds; - if (Bounds->getType() != Type::IntTy) - CastBounds = new CastInst(Bounds, Type::IntTy, - Bounds->getName()+".ec.casted", InsertPt); - - const Type *VoidPtrType = PointerType::get(Type::SByteTy); - Value * CastResult = Pointer; - if (CastResult->getType() != VoidPtrType) - CastResult = new CastInst(CastResult, VoidPtrType, - CastResult->getName()+".ec.casted", InsertPt); - - std::vector<Value *> args(1, CastIndex); - args.push_back(CastBounds); - args.push_back(CastResult); - Instruction * CI = new CallInst(ExactCheck, args, "ec", InsertPt); - -#if 0 - // - // Replace the old index with the return value of exactcheck(); this - // prevents GCC from removing it completely. - // - Value * CastCI = CI; - if (CI->getType() != GEP->getType()) - CastCI = new CastInst (CI, GEP->getType(), GEP->getName(), InsertPt); - - Value::use_iterator UI = GEP->use_begin(); - for (; UI != GEP->use_end(); ++UI) { - if (((*UI) != CI) && ((*UI) != CastResult)) - UI->replaceUsesOfWith (GEP, CastCI); - } -#endif - - // Update statistics - ++ExactChecks; - return; -} - -// -// Function: addExactCheck() -// -// Description: -// Utility routine that inserts a call to exactcheck(). This function can -// perform some optimization be determining if the arguments are constant. -// If they are, we can forego inserting the call. -// -// Inputs: -// GEP - The GEP for which the check will be done. -// Index - An LLVM Value representing the index of the access. -// Bounds - An LLVM Value representing the bounds of the check. -// -void -InsertPoolChecks::addExactCheck (Instruction * GEP, - Value * Index, Value * Bounds) { - // - // Record that this value was checked. - // - CheckedValues.insert (GEP); - - // Upper and lower values on the index and bounds - int index_lower; - int index_upper; - int bounds_lower; - int bounds_upper; - - // - // First, attempt to determine statically whether the check will always pass. - // If so, then don't bother doing it at run-time. - // - ConstantInt * CIndex = dyn_cast<ConstantInt>(Index); - ConstantInt * CBounds = dyn_cast<ConstantInt>(Bounds); - if (CIndex && CBounds) { - int index = CIndex->getSExtValue(); - int bounds = CBounds->getSExtValue(); - assert ((index >= 0) && "exactcheck: const negative index"); - assert ((index < bounds) && "exactcheck: const out of range"); - - // Update stats and return - ++ConstExactChecks; - return; - } else if (CBounds) { - int bounds = CBounds->getSExtValue(); - SCEVHandle SCEVIndex = scevPass->getSCEV (Index); - ConstantRange IndexRange = SCEVIndex->getValueRange(); - if (!(IndexRange.isWrappedSet())) { - int index_lower = IndexRange.getLower()->getSExtValue(); - int index_upper = IndexRange.getUpper()->getSExtValue(); - int bounds_lower = bounds; - int bounds_upper = bounds; - - if ((index_lower >= 0) && (index_upper < bounds_lower)) { - ++ConstExactChecks; - return; - } - } - } - - SCEVHandle SCEVIndex = scevPass->getSCEV (Index); - SCEVHandle SCEVBounds = scevPass->getSCEV (Bounds); - ConstantRange BoundsRange = SCEVBounds->getValueRange(); - ConstantRange IndexRange = SCEVIndex->getValueRange(); - if ((!(IndexRange.isWrappedSet())) && (!(BoundsRange.isWrappedSet()))) { - int index_lower = IndexRange.getLower()->getSExtValue(); - int index_upper = IndexRange.getUpper()->getSExtValue(); - int bounds_lower = BoundsRange.getLower()->getSExtValue(); - int bounds_upper = BoundsRange.getUpper()->getSExtValue(); - - if ((index_lower >= 0) && (index_upper < bounds_lower)) { - ++ConstExactChecks; - return; - } - } - - // - // Cast the operands to the correct type. - // - Instruction * InsertPt = GEP->getNext(); - - Value * CastIndex = Index; - if (Index->getType() != Type::IntTy) - CastIndex = new CastInst(Index, Type::IntTy, - Index->getName()+".ec.casted", InsertPt); - - Value * CastBounds = Bounds; - if (Bounds->getType() != Type::IntTy) - CastBounds = new CastInst(Bounds, Type::IntTy, - Bounds->getName()+".ec.casted", InsertPt); - - const Type *VoidPtrType = PointerType::get(Type::SByteTy); - Value * CastResult = GEP; - if (CastResult->getType() != VoidPtrType) - CastResult = new CastInst(CastResult, VoidPtrType, - CastResult->getName()+".ec.casted", InsertPt); - - std::vector<Value *> args(1, CastIndex); - args.push_back(CastBounds); - args.push_back(CastResult); - Instruction * CI = new CallInst(ExactCheck, args, "ec", InsertPt); - - // - // Replace the old index with the return value of exactcheck(); this - // prevents GCC from removing it completely. - // -#if 0 - Value * CastCI = CI; - if (CI->getType() != GEP->getType()) - CastCI = new CastInst (CI, GEP->getType(), GEP->getName(), InsertPt); - - Value::use_iterator UI = GEP->use_begin(); - for (; UI != GEP->use_end(); ++UI) { - if (((*UI) != CI) && ((*UI) != CastResult)) - UI->replaceUsesOfWith (GEP, CastCI); - } -#endif - - // Update statistics - ++ExactChecks; - return; -} - -// -// Function: isEligableForExactCheck() -// -// Return value: -// true - This value is eligable for an exactcheck. -// false - This value is not eligable for an exactcheck. -// -static inline bool -isEligableForExactCheck (Value * Pointer) { - if ((isa<AllocaInst>(Pointer)) || (isa<GlobalVariable>(Pointer))) - return true; - - if (CallInst* CI = dyn_cast<CallInst>(Pointer)) { - if (CI->getCalledFunction() && - (CI->getCalledFunction()->getName() == "__vmalloc" || - CI->getCalledFunction()->getName() == "kmalloc" || - CI->getCalledFunction()->getName() == "kmem_cache_alloc" || - CI->getCalledFunction()->getName() == "__alloc_bootmem")) { - return true; - } - } - - return false; -} - -// -// Function: findCheckedPointer() -// -// Description: -// Given a pointer value, attempt to determine whether the pointer or all of -// the instructions that created it have been checked. -// -bool -InsertPoolChecks::findCheckedPointer (Value * PointerOperand) { - Value * SourcePointer = PointerOperand; - - while (CheckedValues.find (SourcePointer) == CheckedValues.end()) { - // Check for cast constant expressions and instructions - if (ConstantExpr * cExpr = dyn_cast<ConstantExpr>(SourcePointer)) { - if (cExpr->getOpcode() == Instruction::Cast) { - if (isa<PointerType>(cExpr->getOperand(0)->getType())) { - SourcePointer = cExpr->getOperand(0); - continue; - } - } - // We cannot handle this expression; break out of the loop - break; - } - - if (CastInst * CastI = dyn_cast<CastInst>(SourcePointer)) { - if (isa<PointerType>(CastI->getOperand(0)->getType())) { - SourcePointer = CastI->getOperand(0); - continue; - } - break; - } - - // We can't scan through any more instructions; give up - break; - } - - // - // If the pointer is a GEP, then as long as it has a DSNode, it has been - // checked or proven safe. - // - Instruction * I; - if ((I = dyn_cast<GetElementPtrInst>(SourcePointer)) && - (getDSNode (I, I->getParent()->getParent())) && - (getPoolHandle(I, I->getParent()->getParent()))) { - return true; - } -#if 0 - return (CheckedValues.find (SourcePointer) != CheckedValues.end()); -#else - // Return false; check must dominate load/store. - return false; -#endif -} - -// -// Function: findSourcePointer() -// -// Description: -// Given a pointer value, attempt to find a source of the pointer that can -// be used in an exactcheck(). -// -// Outputs: -// indexed - Flags whether the data flow went through a indexing operation -// (i.e. a GEP). This value is always written. -// -static Value * -findSourcePointer (Value * PointerOperand, bool & indexed) { - // - // Attempt to look for the originally allocated object by scanning the data - // flow up. - // - indexed = false; - Value * SourcePointer = PointerOperand; - Value * OldSourcePointer = 0; - while (!isEligableForExactCheck (SourcePointer)) { - assert (OldSourcePointer != SourcePointer); - OldSourcePointer = SourcePointer; - // Check for GEP and cast constant expressions - if (ConstantExpr * cExpr = dyn_cast<ConstantExpr>(SourcePointer)) { - if ((cExpr->getOpcode() == Instruction::Cast) || - (cExpr->getOpcode() == Instruction::GetElementPtr)) { - if (isa<PointerType>(cExpr->getOperand(0)->getType())) { - SourcePointer = cExpr->getOperand(0); - continue; - } - } - // We cannot handle this expression; break out of the loop - break; - } - - // Check for GEP and cast instructions - if (GetElementPtrInst * G = dyn_cast<GetElementPtrInst>(SourcePointer)) { - SourcePointer = G->getPointerOperand(); - indexed = true; - continue; - } - - if (CastInst * CastI = dyn_cast<CastInst>(SourcePointer)) { - if (isa<PointerType>(CastI->getOperand(0)->getType())) { - SourcePointer = CastI->getOperand(0); - continue; - } - break; - } - - // Check for call instructions to exact checks. - CallInst * CI1; - if ((CI1 = dyn_cast<CallInst>(SourcePointer)) && - (CI1->getCalledFunction()) && - (CI1->getCalledFunction()->getName() == "exactcheck3")) { - SourcePointer = CI1->getOperand (2); - continue; - } - - // We can't scan through any more instructions; give up - break; - } - - if (isEligableForExactCheck (SourcePointer)) - PointerOperand = SourcePointer; - - return PointerOperand; -} - -// -// Function: insertExactCheck() -// -// Description: -// Attepts to insert an efficient, accurate array bounds check for the given -// GEP instruction; this check will not use Pools are MetaPools. -// -// Return value: -// true - An exactcheck() was successfully added. -// false - An exactcheck() could not be added; a more extensive check will be -// needed. -// -bool -InsertPoolChecks::insertExactCheck (GetElementPtrInst * GEP) { - // The GEP instruction casted to the correct type - Instruction *Casted = GEP; - - // The pointer operand of the GEP expression - Value * PointerOperand = GEP->getPointerOperand(); - - // - // Get the DSNode for the instruction - // - Function *F = GEP->getParent()->getParent(); - DSGraph & TDG = getDSGraph(*F); - DSNode * Node = TDG.getNodeForValue(GEP).getNode(); - assert (Node && "boundscheck: DSNode is NULL!"); - - // - // Determine whether an alignment check is needed. This occurs when a DSNode - // is type unknown (collapsed) but has pointers to type known (uncollapsed) - // DSNodes. - // - if (preSCPass->nodeNeedsAlignment (Node)) { - ++AlignChecks; - } - -#if 0 - // Debugging: See if we're missing exactcheck opportunities - if (isa<SelectInst>(PointerOperand)) - std::cerr << "LLVA: EC: Select Inst\n"; - - if (isa<GetElementPtrInst>(PointerOperand)) - std::cerr << "LLVA: EC: GEP: In " << F->getName() << "\n"; - - CallInst * CI1; - if ((CI1 = dyn_cast<CallInst>(PointerOperand)) && - (CI1->getCalledFunction()) && - (CI1->getCalledFunction()->getName() == "exactcheck3")) - std::cerr << "LLVA: EC: GEP: Hidden by ec3: In " << F->getName() << "\n"; - - PHINode * PN = 0; - if (PN = dyn_cast<PHINode>(PointerOperand)) { - std::cerr << "LLVA: EC: PHI\n"; - for (unsigned index = 0; index < PN->getNumIncomingValues(); ++index) { - std::cerr << "LLVA: " << *(PN->getIncomingValue(index)) << std::endl; - } - } -#endif - - // - // Attempt to find the object which we need to check. - // - bool WasIndexed = true; - PointerOperand = findSourcePointer (PointerOperand, WasIndexed); - - // - // Ensure the pointer operand really is a pointer. - // - if (!isa<PointerType>(PointerOperand->getType())) - return false; - - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) { - // - // Attempt to remove checks on GEPs that only index into structures. - // These criteria must be met: - // 1) The pool must be Type-Homogoneous. - // -#if 0 - if ((!(Node->isNodeCompletelyFolded())) && - (indexesStructsOnly (GEP))) { - ++StructGEPsRemoved; - return true; - } -#endif - - // - // Attempt to use a call to exactcheck() to check this value if it is a - // global array with a non-zero size. We do not check zero length arrays - // because in C they are often used to declare an external array of unknown - // size as follows: - // extern struct foo the_array[]; - // - const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType()); - if ((!WasIndexed) && AT && (AT->getNumElements())) { - // we need to insert an actual check - // It could be a select instruction - // First get the size - // This only works for one or two dimensional arrays - if (GEP->getNumOperands() == 2) { - Value *secOp = GEP->getOperand(1); - - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - ConstantInt * Bounds = ConstantInt::get(csiType,AT->getNumElements()); - addExactCheck (GEP, secOp, Bounds); - return true; - } else if (GEP->getNumOperands() == 3) { - if (ConstantInt *COP = dyn_cast<ConstantInt>(GEP->getOperand(1))) { - //FIXME assuming that the first array index is 0 - assert((COP->getZExtValue() == 0) && "non zero array index\n"); - - Value * secOp = GEP->getOperand(2); - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - ConstantInt * Bounds = ConstantInt::get(csiType,AT->getNumElements()); - addExactCheck (GEP, secOp, Bounds); - return true; - } else { - // TODO: - // Handle non constant index two dimensional arrays later - Value* Size=ConstantInt::get(Type::IntTy, TD->getTypeSize(GV->getType())); - addExactCheck2 (PointerOperand, GEP, Size, GEP->getNext()); - return true; - } - } else { - // Handle Multi dimensional cases later - Value* AllocSize=ConstantInt::get(Type::IntTy, TD->getTypeSize(GV->getType()->getElementType())); - addExactCheck2 (PointerOperand, GEP, AllocSize, GEP->getNext()); - return true; - GEP->dump(); - ++MissedMultDimArrayChecks; - } - DEBUG(std::cerr << " Global variable ok \n"); - } else { - Value* Size=ConstantInt::get(Type::IntTy, TD->getTypeSize(GV->getType())); - addExactCheck2 (PointerOperand, GEP, Size, GEP->getNext()); - return true; - } - } - - // - // If the pointer was generated by a dominating alloca instruction, we can - // do an exactcheck on it, too. - // - if (AllocaInst *AI = dyn_cast<AllocaInst>(PointerOperand)) { - // - // Attempt to remove checks on GEPs that only index into structures. - // These criteria must be met: - // 1) The pool must be Type-Homogoneous. - // -#if 0 - if ((!(Node->isNodeCompletelyFolded())) && - (indexesStructsOnly (GEP))) { - ++StructGEPsRemoved; - return true; - } -#endif - - const Type * AllocaType = AI->getAllocatedType(); - Value *AllocSize=ConstantInt::get(Type::IntTy, TD->getTypeSize(AllocaType)); - - if (AI->isArrayAllocation()) - AllocSize = BinaryOperator::create(Instruction::Mul, - AllocSize, - AI->getOperand(0), "sizetmp", GEP); - - addExactCheck2 (PointerOperand, GEP, AllocSize, GEP->getNext()); - return true; - } - - // - // If the pointer was an allocation, we should be able to do exact checks - // - CallInst* CI = dyn_cast<CallInst>(PointerOperand); - if (CI && (CI->getCalledFunction())) { - if ((CI->getCalledFunction()->getName() == "__vmalloc") || - (CI->getCalledFunction()->getName() == "kmalloc") || - (CI->getCalledFunction()->getName() == "__alloc_bootmem")) { - // - // Attempt to remove checks on GEPs that only index into structures. - // These criteria must be met: - // 1) The pool must be Type-Homogoneous. - // -#if 0 - if ((!(Node->isNodeCompletelyFolded())) && - (indexesStructsOnly (GEP))) { - ++StructGEPsRemoved; - return true; - } -#endif - - Value* Cast = new CastInst(CI->getOperand(1), Type::IntTy, "", GEP); - addExactCheck2(PointerOperand, GEP, Cast, GEP->getNext()); - return true; - } else if (CI->getCalledFunction()->getName() == "kmem_cache_alloc") { - // Insert a call to kmem_get_cachesize() to determine the size of the - // allocated object - const Type * VoidPtrType = PointerType::get(Type::SByteTy); - Value* VP = castTo (CI->getOperand(1), VoidPtrType, GEP); - CallInst *len = new CallInst(KmemCachegetSize, VP, "", GEP); - - // Add the exactcheck - Value* CastLen = castTo (len, Type::IntTy, GEP); - addExactCheck2(PointerOperand, GEP, CastLen, GEP->getNext()); - } - } - - // - // If the pointer is to a structure, we may be able to perform a simple - // exactcheck on it, too, unless the array is at the end of the structure. - // Then, we assume it's a variable length array and must be full checked. - // -#if 0 - if (const PointerType * PT = dyn_cast<PointerType>(PointerOperand->getType())) - if (const StructType *ST = dyn_cast<StructType>(PT->getElementType())) { - const Type * CurrentType = ST; - ConstantInt * C; - for (unsigned index = 2; index < GEP->getNumOperands() - 1; ++index) { - // - // If this GEP operand is a constant, index down into the next type. - // - if (C = dyn_cast<ConstantInt>(GEP->getOperand(index))) { - if (const StructType * ST2 = dyn_cast<StructType>(CurrentType)) { - CurrentType = ST2->getElementType(C->getZExtValue()); - continue; - } - - if (const ArrayType * AT = dyn_cast<ArrayType>(CurrentType)) { - CurrentType = AT->getElementType(); - continue; - } - - // We don't know how to handle this type of element - break; - } - - // - // If the GEP operand is not constant and points to an array type, - // then try to insert an exactcheck(). - // - const ArrayType * AT; - if ((AT = dyn_cast<ArrayType>(CurrentType)) && (AT->getNumElements())) { - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - ConstantInt * Bounds = ConstantInt::get(csiType,AT->getNumElements()); - addExactCheck (GEP, GEP->getOperand (index), Bounds); - return true; - } - } - } -#endif - - /* - * We were not able to insert a call to exactcheck(). - */ - return false; -} - -// -// Function: insertExactCheck() -// -// Description: -// Attepts to insert an efficient, accurate array bounds check for the given -// GEP instruction; this check will not use Pools are MetaPools. -// -// Inputs: -// I - The instruction for which we are adding the check. -// Src - The pointer that needs to be checked. -// Size - The size, in bytes, that will be read/written by instruction I. -// InsertPt - The instruction before which the check should be inserted. -// -// Return value: -// true - An exactcheck() was successfully added. -// false - An exactcheck() could not be added; a more extensive check will be -// needed. -// -bool -InsertPoolChecks::insertExactCheck (Instruction * I, - Value * Src, - Value * Size, - Instruction * InsertPt) { - // The pointer operand of the GEP expression - Value * PointerOperand = Src; - - // - // Get the DSNode for the instruction - // -#if 1 - Function *F = I->getParent()->getParent(); - DSGraph & TDG = getDSGraph(*F); - DSNode * Node = TDG.getNodeForValue(I).getNode(); - if (!Node) - return false; -#endif - - // - // Determine whether an alignment check is needed. This occurs when a DSNode - // is type unknown (collapsed) but has pointers to type known (uncollapsed) - // DSNodes. - // - if (preSCPass->nodeNeedsAlignment (Node)) { - ++AlignChecks; - } - - // - // Attempt to find the original object for which this check applies. - // This involves unpeeling casts, GEPs, etc. - // - bool WasIndexed = true; - PointerOperand = findSourcePointer (PointerOperand, WasIndexed); - - // - // Ensure the pointer operand really is a pointer. - // - if (!isa<PointerType>(PointerOperand->getType())) - { - return false; - } - - // - // Attempt to use a call to exactcheck() to check this value if it is a - // global array with a non-zero size. We do not check zero length arrays - // because in C they are often used to declare an external array of unknown - // size as follows: - // extern struct foo the_array[]; - // - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) { - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - unsigned int arraysize = TD->getTypeSize(GV->getType()->getElementType()); - ConstantInt * Bounds = ConstantInt::get(csiType, arraysize); - if (WasIndexed) - addExactCheck2 (PointerOperand, Src, Bounds, InsertPt); - else - addExactCheck (Src, Size, Bounds, InsertPt); - return true; - } - - // - // If the pointer was generated by a dominating alloca instruction, we can - // do an exactcheck on it, too. - // - if (AllocaInst *AI = dyn_cast<AllocaInst>(PointerOperand)) { - const Type * AllocaType = AI->getAllocatedType(); - Value *AllocSize=ConstantInt::get(Type::IntTy, TD->getTypeSize(AllocaType)); - - if (AI->isArrayAllocation()) - AllocSize = BinaryOperator::create(Instruction::Mul, - AllocSize, - AI->getOperand(0), "allocsize", InsertPt); - - if (WasIndexed) - addExactCheck2 (PointerOperand, Src, AllocSize, InsertPt); - else - addExactCheck (Src, Size, AllocSize, InsertPt); - return true; - } - - // - // If the pointer was an allocation, we should be able to do exact checks - // - if(CallInst* CI = dyn_cast<CallInst>(PointerOperand)) { - if (CI->getCalledFunction() && ( - CI->getCalledFunction()->getName() == "__vmalloc" || - CI->getCalledFunction()->getName() == "kmalloc")) { - Value* Cast = new CastInst(CI->getOperand(1), Type::IntTy, "allocsize", InsertPt); - if (WasIndexed) - addExactCheck2 (PointerOperand, Src, Cast, InsertPt); - else - addExactCheck (Src, Size, Cast, InsertPt); - return true; - } - } - - // - // We were not able to insert a call to exactcheck(). - // - return false; -} - -bool -InsertPoolChecks::doInitialization (Module & M) { - // Add the new poolcheck prototype - addPoolCheckProto (M); - - return true; -} - -bool -InsertPoolChecks::doFinalization (Module & M) { - // Insert code to register heap allocations with the correct MetaPool - // and to register kernel pools with the correct MetaPool - addHeapRegs (M); - - // Insert code to drop objects from MetaPools when they are freed by the - // kernel allocators - addObjFrees (M); - - return true; -} - -bool -InsertPoolChecks::runOnFunction (Function & F) { - // - // Retrieve references to all of the passes from which we will gather - // information. - // - preSCPass = &getAnalysis<PreInsertPoolChecks>(); - cuaPass = &getAnalysis<ConvertUnsafeAllocas>(); - TD = &getAnalysis<TargetData>(); - scevPass = &getAnalysis<ScalarEvolution>(); - LI = &getAnalysis<LoopInfo>(); -#ifdef LLVA_KERNEL - TDPass = &getAnalysis<TDDataStructures>(); -#else - paPass = &getAnalysis<PoolAllocate>(); - equivPass = &(paPass->getECGraphs()); - efPass = &getAnalysis<EmbeCFreeRemoval>(); - TD = &getAnalysis<TargetData>(); -#endif - -#if 1 - // Transform the function - if (!(F.isExternal())) TransformFunction (F); - if (!DisableLSChecks) addLoadStoreChecks(F); -#endif - - // - // Update the statistics. - // - PoolChecks = NullChecks + FullChecks; - - return true; -} - -void InsertPoolChecks::handleCallInst(CallInst *CI) { - // - // Determine if this is an indirect call. If so, insert a run-time check for - // it. - // - if (!(CI->getCalledFunction())) - insertFunctionCheck (CI); - - // - // Check for intrinsic functions and add checks as necessary. - // - if (CI && (!DisableIntrinsicChecks)) { - Value *Fop = CI->getOperand(0); - Function *F = CI->getParent()->getParent(); -#ifdef LLVA_KERNEL - std::string FuncName = Fop->getName(); - if ((FuncName == "llvm.memcpy.i32") || - (FuncName == "llvm.memcpy.i64") || - (FuncName == "llvm.memset.i32") || - (FuncName == "llvm.memset.i64") || - (FuncName == "llvm.memmove.i32") || - (FuncName == "llvm.memmove.i64") || - (FuncName == "llva_memcpy") || - (FuncName == "llva_memset") || - (FuncName == "llva_strncpy") || - (FuncName == "llva_invokememcpy") || - (FuncName == "llva_invokestrncpy") || - (FuncName == "llva_invokememset") || - (FuncName == "memcmp")) { - // - // Create a call to an accurate bounds check for each string parameter. - // - Instruction *InsertPt = CI; - Value * CastPointer1 = castTo (CI->getOperand(1), Type::UIntTy, InsertPt); - Value * CastPointer2 = castTo (CI->getOperand(2), Type::UIntTy, InsertPt); - Value * CastCIOp3 = castTo (CI->getOperand(3), Type::UIntTy, InsertPt); - - Instruction *Bop1 = BinaryOperator::create(Instruction::Add, CastPointer1, - CastCIOp3, "mcadd",InsertPt); - Instruction *Bop2 = BinaryOperator::create(Instruction::Add, CastPointer2, - CastCIOp3, "mcadd",InsertPt); - Instruction *Finalp1 = BinaryOperator::create(Instruction::Sub, Bop1, - ConstantInt::get (Type::UIntTy, 1), "mcsub",InsertPt); - Instruction *Finalp2 = BinaryOperator::create(Instruction::Sub, Bop2, - ConstantInt::get (Type::UIntTy, 1), "mcsub",InsertPt); - - Instruction *Length = BinaryOperator::create(Instruction::Sub, CastCIOp3, - ConstantInt::get (Type::UIntTy, 1), "mclen",InsertPt); - AddedValues.insert(CastPointer1); - AddedValues.insert(CastPointer2); - AddedValues.insert(CastCIOp3); - AddedValues.insert(Bop1); - AddedValues.insert(Bop2); - AddedValues.insert(Finalp1); - AddedValues.insert(Finalp2); - AddedValues.insert(Length); - - // Create the call to do an accurate bounds check - if (!insertExactCheck(CI, CI->getOperand(1), Length, InsertPt)) - insertBoundsCheck (CI, CI->getOperand(1), Bop1, InsertPt); - if (!insertExactCheck(CI, CI->getOperand(2), Length, InsertPt)) - insertBoundsCheck (CI, CI->getOperand(2), Bop2, InsertPt); -#if 0 - } else if ((FuncName == "llva_load_integer") || - (FuncName == "llva_save_integer") || - (FuncName == "llva_load_integer_stackp") || - (FuncName == "llva_save_integer_stackp") || - (FuncName == "llva_push_function1")) { - // - // Create a call to an accurate bounds check for the integer state - // pointer. - // - Instruction *InsertPt = CI; - Value * CastPointer1 = castTo (CI->getOperand(1), Type::UIntTy, InsertPt); - Value * CastLength = ConstantInt::get (Type::UIntTy, LLVA_INTEGERSTATE_SIZE); - - Instruction *Bop1 = BinaryOperator::create(Instruction::Add, CastPointer1, - CastLength, "mcadd",InsertPt); - Value *Length = ConstantInt::get (Type::UIntTy, LLVA_INTEGERSTATE_SIZE - 1); - - // Create the call to do an accurate bounds check - if (!insertExactCheck(CI, CI->getOperand(1), Length, InsertPt)) - insertBoundsCheck (CI, CI->getOperand(1), Bop1, InsertPt); - } else if ((FuncName == "llva_load_icontext") || - (FuncName == "llva_save_icontext")) { - // - // Perform a check on the interrupt context. - // - Instruction *InsertPt = CI; - insertICCheck (CI->getOperand(1), InsertPt); - - // - // Create a call to an accurate bounds check for the integer state. - // - Value * CastPointer1 = castTo (CI->getOperand(2), Type::UIntTy, InsertPt); - Value * CastLength = ConstantInt::get (Type::UIntTy, LLVA_ICONTEXT_SIZE); - - Instruction *Bop1 = BinaryOperator::create(Instruction::Add, CastPointer1, - CastLength, "mcadd",InsertPt); - Value *Length = ConstantInt::get (Type::UIntTy, LLVA_ICONTEXT_SIZE - 1); - - // Create the call to do an accurate bounds check - if (!insertExactCheck(CI, CI->getOperand(2), Length, InsertPt)) - insertBoundsCheck (CI, CI->getOperand(1), Bop1, InsertPt); - } else if ((FuncName == "llva_load_fp") || (FuncName == "llva_save_fp")) { - // - // Create a call to an accurate bounds check for the FP state - // pointer. - // - Instruction *InsertPt = CI; - Value * CastPointer1 = castTo (CI->getOperand(1), Type::UIntTy, InsertPt); - Value * CastLength = ConstantInt::get (Type::UIntTy, LLVA_FPSTATE_SIZE); - - Instruction *Bop1 = BinaryOperator::create(Instruction::Add, CastPointer1, - CastLength, "mcadd",InsertPt); - Value *Length = ConstantInt::get (Type::UIntTy, LLVA_FPSTATE_SIZE - 1); - - // Create the call to do an accurate bounds check - if (!insertExactCheck(CI, CI->getOperand(1), Length, InsertPt)) - insertBoundsCheck (CI, CI->getOperand(1), Bop1, InsertPt); - } else if (FuncName == "llva_push_syscall") { - // - // Create a call to an accurate bounds check for the interrupt context - // pointer. - // - Instruction *InsertPt = CI; - Value * CastPointer1 = castTo (CI->getOperand(2), Type::UIntTy, InsertPt); - Value * CastLength = ConstantInt::get (Type::UIntTy, LLVA_ICONTEXT_SIZE); - - Instruction *Bop1 = BinaryOperator::create(Instruction::Add, CastPointer1, - CastLength, "mcadd",InsertPt); - Value *Length = ConstantInt::get (Type::UIntTy, LLVA_ICONTEXT_SIZE - 1); - - // Create the call to do an accurate bounds check - if (!insertExactCheck(CI, CI->getOperand(1), Length, InsertPt)) - insertBoundsCheck (CI, CI->getOperand(1), Bop1, InsertPt); - } else if ((FuncName == "llva_init_icontext") || - (FuncName == "llva_clear_icontext") || - (FuncName == "llva_was_privileged") || - (FuncName == "llva_icontext_lif") || - (FuncName == "llva_ipop_function0") || - (FuncName == "llva_ipush_function0") || - (FuncName == "llva_ipush_function1") || - (FuncName == "llva_ipush_function3") || - (FuncName == "llva_ialloca") || - (FuncName == "llva_unwind") || - (FuncName == "llva_icontext_load_retvalue") || - (FuncName == "llva_icontext_save_retvalue") || - (FuncName == "llva_get_icontext_stackp") || - (FuncName == "llva_set_icontext_stackp") || - (FuncName == "llva_iset_privileged")) { - // - // Create a call to an accurate bounds check for the interrupt context - // pointer. - // - Instruction *InsertPt = CI; - insertICCheck (CI->getOperand(1), InsertPt); -#endif - } -#endif - } -} - -void InsertPoolChecks::simplifyGEPList() { -#if 0 - std::set<Instruction *> & UnsafeGetElemPtrs = cuaPass->getUnsafeGetElementPtrsFromABC(); - std::map< std::pair<Value*, BasicBlock*>, std::set<Instruction*> > m; - for (std::set<Instruction *>::iterator ii = UnsafeGetElemPtrs.begin(), ee = UnsafeGetElemPtrs.end(); - ii != ee; ++ii) { - GetElementPtrInst* GEP = cast<GetElementPtrInst>(*ii); - m[std::make_pair(GEP->getOperand(0), GEP->getParent())].insert(GEP); - } - - unsigned singletons; - unsigned multi; - for (std::map< std::pair<Value*,BasicBlock*>, std::set<Instruction*> >::iterator ii = m.begin(), ee = m.end(); - ii != ee; ++ii) { - if (ii->second.size() > 1) { - std::cerr << "##############\n"; - for (std::set<Instruction *>::iterator i = ii->second.begin(), e = ii->second.end(); - i != e; ++i) { - (*i)->dump(); - } - std::cerr << "##############\n"; - ++multi; - } else - ++singletons; - } - - std::cerr << "Singletons: " << singletons << " Multitons: " << multi << "\n"; - -#endif -} - -// -// Function: compatibleGEPs() -// -// Description: -// Determine whether two GEPs address the same memory and have the (save the -// for last) same arguments. -// -// Return value: -// true - All arguments (except possibly the last) are identical. -// false - One or more arguments besides the last argument are different. -// -static inline bool -identicalGEPs (GetElementPtrInst * GEP1, GetElementPtrInst * GEP2) { - if (GEP1->getPointerOperand() != GEP2->getPointerOperand()) return false; - if (GEP1->getNumOperands() != GEP2->getNumOperands()) return false; - for (unsigned index = 0; index < GEP1->getNumOperands() - 1; ++index) { - if (GEP1->getOperand(index) != GEP2->getOperand(index)) { - return false; - break; - } - } - - return true; -} - -bool -InsertPoolChecks::AggregateGEPs (GetElementPtrInst * MAI, - std::set<Instruction *> & RelatedGEPs) { - // Get the set of unsafe GEPs for this instruction's basic block - std::set<Instruction *> * UnsafeGetElemPtrs = cuaPass->getUnsafeGetElementPtrsFromABC(MAI->getParent()); - if (!UnsafeGetElemPtrs) { - RelatedGEPs.insert (MAI); - return true; - } - - // If this GEP has already been deemed safe, then return; - std::set<Instruction *>::const_iterator iCurrent = UnsafeGetElemPtrs->find(MAI); - if (iCurrent == UnsafeGetElemPtrs->end()) { - return true; - } - - // Determine whether the GEP has a constant as its last index. - // If so, search for all other GEPs that have, save for the last index, - // identical operands. Then select the two with the higest and lowest - // indices; we will perform our run-time checks on these. - std::set<Instruction *>::iterator UGI = UnsafeGetElemPtrs->begin(), - UGE = UnsafeGetElemPtrs->end(); - Instruction * MinGEP = MAI; - Instruction * MaxGEP = MAI; - if (isa<ConstantInt>(MAI->getOperand((MAI->getNumOperands() - 1)))) { - - for (;UGI != UGE; ++UGI) { - Instruction * I = *UGI; - GetElementPtrInst * GEP = dyn_cast<GetElementPtrInst>(I); - if (!GEP) continue; - if (!(isa<ConstantInt>(GEP->getOperand((GEP->getNumOperands() - 1))))) continue; - if (identicalGEPs (GEP, MAI)) { - ConstantInt * GEPLastIndex; - ConstantInt * MinLastIndex; - ConstantInt * MaxLastIndex; - GEPLastIndex = dyn_cast<ConstantInt>(GEP->getOperand(GEP->getNumOperands() - 1)); - MinLastIndex = dyn_cast<ConstantInt>(MinGEP->getOperand(MinGEP->getNumOperands() - 1)); - MaxLastIndex = dyn_cast<ConstantInt>(MaxGEP->getOperand(MaxGEP->getNumOperands() - 1)); - if (GEPLastIndex->getSExtValue() < MinLastIndex->getSExtValue()) { - UnsafeGetElemPtrs->erase (MinGEP); - MinGEP = GEP; - } - if (GEPLastIndex->getSExtValue() > MaxLastIndex->getSExtValue()) { - UnsafeGetElemPtrs->erase (MaxGEP); - MaxGEP = GEP; - } - } - } - - // - // Find the first compatible GEP in the basic block. - // - Instruction * Ins = MAI->getParent()->getFirstNonPHI(); - GetElementPtrInst * FirstGEP = 0; - while (!(Ins->isTerminator())) { - if (FirstGEP = dyn_cast<GetElementPtrInst>(Ins)) { - if (identicalGEPs (MAI, FirstGEP)) - break; - } - Ins = Ins->getNext(); - } - - // - // Move the minimum and maximum GEPs to before the first identical GEP. - // - if (FirstGEP != MinGEP) { - MinGEP->moveBefore (FirstGEP); - } - if (FirstGEP != MaxGEP) { - MaxGEP->moveBefore (FirstGEP); - } - } - - RelatedGEPs.insert (MinGEP); - if (MinGEP != MaxGEP) RelatedGEPs.insert (MaxGEP); - - return true; -} - -void InsertPoolChecks::handleGetElementPtr(GetElementPtrInst *MAI) { - // Get the set of unsafe GEP instructions from the array bounds check pass - // If this instruction is not within that set, then the result of the GEP - // instruction has been proven safe, and there is no need to insert a check. - std::set<Instruction *> * UnsafeGetElemPtrs = cuaPass->getUnsafeGetElementPtrsFromABC(MAI->getParent()); - if (!UnsafeGetElemPtrs) return; - std::set<Instruction *>::const_iterator iCurrent = UnsafeGetElemPtrs->find(MAI); - if (iCurrent == UnsafeGetElemPtrs->end()) { -#if 0 - std::cerr << "statically proved safe : Not inserting checks " << *MAI << "\n"; -#endif - return; - } - -#if 0 - // Find all unsafe GEPs within the basic block that are identical save for - // their last index - std::set<Instruction *> RelatedGEPs; - std::set<Instruction *>::iterator UGI = UnsafeGetElemPtrs->begin(), - UGE = UnsafeGetElemPtrs->end(); - if (isa<ConstantInt>(MAI->getOperand((MAI->getNumOperands() - 1)))) - for (;UGI != UGE; ++UGI) { - Instruction * I = *UGI; - GetElementPtrInst * GEP = dyn_cast<GetElementPtrInst>(I); - if (!GEP) continue; - if (GEP->getPointerOperand() != MAI->getPointerOperand()) continue; - if (GEP->getNumOperands() != MAI->getNumOperands()) continue; - if (!(isa<ConstantInt>(GEP->getOperand((GEP->getNumOperands() - 1))))) continue; - bool identical = true; - for (unsigned index = 0; index < GEP->getNumOperands() - 1; ++index) { - if (GEP->getOperand(index) != MAI->getOperand(index)) { - identical = false; - break; - } - } - if (identical) - RelatedGEPs.insert (GEP); - } - - std::cerr << "LLVA: RelatedGEP: " << RelatedGEPs.size() << std::endl; -#endif - - if (InsertPoolChecksForArrays) { - Function *F = MAI->getParent()->getParent(); - GetElementPtrInst *GEP = MAI; - // Now we need to decide if we need to pass in the alignmnet - //for the poolcheck - // if (getDSNodeOffset(GEP->getPointerOperand(), F)) { - // std::cerr << " we don't handle middle of structs yet\n"; - //assert(!getDSNodeOffset(GEP->getPointerOperand(), F) && " we don't handle middle of structs yet\n"); - // ++MissChecks; - // continue; - // } - -#ifndef LLVA_KERNEL - PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F); - Instruction *Casted = GEP; - if (!FI->ValueMap.empty()) { - assert(FI->ValueMap.count(GEP) && "Instruction not in the value map \n"); - Instruction *temp = dyn_cast<Instruction>(FI->ValueMap[GEP]); - assert(temp && " Instruction not there in the Value map"); - Casted = temp; - } - if (GetElementPtrInst *GEPNew = dyn_cast<GetElementPtrInst>(Casted)) { - Value *PH = getPoolHandle(GEP, F, *FI); - if (PH && isa<ConstantPointerNull>(PH)) return; - if (!PH) { - Value *PointerOperand = GEPNew->getPointerOperand(); - if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(PointerOperand)) { - if (cExpr->getOpcode() == Instruction::Cast) - PointerOperand = cExpr->getOperand(0); - } - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) { - if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) { - // We need to insert an actual check. It could be a select - // instruction. - // First get the size. - // This only works for one or two dimensional arrays. - if (GEPNew->getNumOperands() == 2) { - Value *secOp = GEPNew->getOperand(1); - if (secOp->getType() != Type::IntTy) { - secOp = new CastInst(secOp, Type::IntTy, - secOp->getName()+".ec.casted", Casted); - } - - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - std::vector<Value *> args(1,secOp); - args.push_back(ConstantInt::get(csiType,AT->getNumElements())); - new CallInst(ExactCheck,args,"", Casted); - DEBUG(std::cerr << "Inserted exact check call Instruction \n"); - return; - } else if (GEPNew->getNumOperands() == 3) { - if (ConstantInt *COP = dyn_cast<ConstantInt>(GEPNew->getOperand(1))) { - // FIXME: assuming that the first array index is 0 - assert((COP->getZExtValue() == 0) && "non zero array index\n"); - Value * secOp = GEPNew->getOperand(2); - if (secOp->getType() != Type::IntTy) { - secOp = new CastInst(secOp, Type::IntTy, - secOp->getName()+".ec2.casted", Casted); - } - std::vector<Value *> args(1,secOp); - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - args.push_back(ConstantInt::get(csiType,AT->getNumElements())); - new CallInst(ExactCheck, args, "", Casted->getNext()); - return; - } else { - // Handle non constant index two dimensional arrays later - abort(); - } - } else { - // Handle Multi dimensional cases later - DEBUG(std::cerr << "WARNING: Handle multi dimensional globals later\n"); - (*iCurrent)->dump(); - } - } - DEBUG(std::cerr << " Global variable ok \n"); - } - - // These must be real unknowns and they will be handled anyway - // std::cerr << " WARNING, DID NOT HANDLE \n"; - // (*iCurrent)->dump(); - return; - } else { - if (Casted->getType() != PointerType::get(Type::SByteTy)) { - Casted = new CastInst(Casted,PointerType::get(Type::SByteTy), - (Casted)->getName()+".pc.casted", - (Casted)->getNext()); - } - std::vector<Value *> args(1, PH); - args.push_back(Casted); - // Insert it - new CallInst(PoolCheck,args, "",Casted->getNext()); - DEBUG(std::cerr << "inserted instrcution \n"); - } - } -#else - // - // Get the pool handle associated with the pointer operand. - // - Value *PH = getPoolHandle(GEP->getPointerOperand(), F); - GetElementPtrInst *GEPNew = GEP; - Instruction *Casted = GEP; - - DSGraph & TDG = getDSGraph(*F); - DSNode * Node = TDG.getNodeForValue(GEP).getNode(); - - DEBUG(std::cerr << "LLVA: addGEPChecks: Pool " << PH << " Node "); - DEBUG(std::cerr << Node << std::endl); - - Value *PointerOperand = GEPNew->getPointerOperand(); - if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(PointerOperand)) { - if (cExpr->getOpcode() == Instruction::Cast) - PointerOperand = cExpr->getOperand(0); - } - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) { - if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) { - // we need to insert an actual check - // It could be a select instruction - // First get the size - // This only works for one or two dimensional arrays - if (GEPNew->getNumOperands() == 2) { - Value *secOp = GEPNew->getOperand(1); -#ifdef LLVA_KERNEL - // - // Determine whether the exactcheck() will have constant integer - // arguments. If so, then we can evaluate them statically and avoid - // inserting the run-time check. - // - if (ConstantInt * Index = dyn_cast<ConstantInt>(secOp)) { - int index = Index->getSExtValue(); - assert ((index < 0) && "exactcheck will fail at runtime"); - if (index < AT->getNumElements()) - return; - assert (0 && "exactcheck out of range"); - } -#endif - if (secOp->getType() != Type::IntTy) { - secOp = new CastInst(secOp, Type::IntTy, - secOp->getName()+".ec3.casted", Casted); - } - - std::vector<Value *> args(1,secOp); - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - args.push_back(ConstantInt::get(csiType,AT->getNumElements())); - new CallInst(ExactCheck,args,"", Casted); - // DEBUG(std::cerr << "Inserted exact check call Instruction \n"); - return; - } else if (GEPNew->getNumOperands() == 3) { - if (ConstantInt *COP = dyn_cast<ConstantInt>(GEPNew->getOperand(1))) { - //FIXME assuming that the first array index is 0 - assert((COP->getZExtValue() == 0) && "non zero array index\n"); - Value * secOp = GEPNew->getOperand(2); -#ifdef LLVA_KERNEL - // - // Determine whether the exactcheck() will have constant integer - // arguments. If so, then we can evaluate them statically and avoid - // inserting the run-time check. - // - if (ConstantInt * Index = dyn_cast<ConstantInt>(secOp)) { - int index = Index->getSExtValue(); - assert ((index < 0) && "exactcheck will fail at runtime"); - if (index < AT->getNumElements()) - return; - assert (0 && "exactcheck out of range"); - } -#endif - if (secOp->getType() != Type::IntTy) { - secOp = new CastInst(secOp, Type::IntTy, - secOp->getName()+".ec4.casted", Casted); - } - std::vector<Value *> args(1,secOp); - const Type* csiType = Type::getPrimitiveType(Type::IntTyID); - args.push_back(ConstantInt::get(csiType,AT->getNumElements())); - new CallInst(ExactCheck,args,"", Casted->getNext()); - return; - } else { - //Handle non constant index two dimensional arrays later - abort(); - } - } else { - //Handle Multi dimensional cases later - std::cerr << "WARNING: Handle multi dimensional globals later\n"; - (*iCurrent)->dump(); - ++MissedMultDimArrayChecks; - } - DEBUG(std::cerr << " Global variable ok \n"); - } - } - - // - // We cannot insert an exactcheck(). Insert a pool check. - // - // - if (!PH) { -#if 0 - std::cerr << "missing a GEP check for" << *MAI << "alloca case?\n"; -#endif - ++NullChecks; - if (!PH) ++MissedNullChecks; - // Don't bother to insert the NULL check unless the user asked - if (!EnableNullChecks) - return; - PH = Constant::getNullValue(PointerType::get(Type::SByteTy)); - } else { - assert ((isa<GlobalValue>(PH)) && "MetaPool Handle is not a global!"); - } - - // - // If this is a complete node, insert a poolcheck. - // If this is an icomplete node, insert a poolcheckarray. - // - Instruction *InsertPt = Casted->getNext(); - if (Casted->getType() != PointerType::get(Type::SByteTy)) { - Casted = new CastInst(Casted,PointerType::get(Type::SByteTy), - (Casted)->getName()+".pc2.casted",InsertPt); - } - Instruction *CastedPointerOperand = new CastInst(PointerOperand, - PointerType::get(Type::SByteTy), - PointerOperand->getName()+".casted",InsertPt); - Instruction *CastedPH = new CastInst(PH, - PointerType::get(Type::SByteTy), - "ph",InsertPt); - if (Node->isIncomplete()) { - std::vector<Value *> args(1, CastedPH); - args.push_back(CastedPointerOperand); - args.push_back(Casted); - CallInst(PoolCheckArray,args, "",InsertPt); - } else { - std::vector<Value *> args(1, CastedPH); - args.push_back(Casted); - new CallInst(PoolCheck,args, "",InsertPt); - } -#endif - } else { - // Insert accurate bounds checks for arrays (as opposed to poolchecks) - - // - // Attempt to insert a standard exactcheck() call for the GEP. - // - if (insertExactCheck (MAI)) - return; - - //Exact poolchecks - if (const PointerType *PT = dyn_cast<PointerType>(MAI->getPointerOperand()->getType())) { -#if 0 - if (const StructType *ST = dyn_cast<StructType>(PT->getElementType())) { -#else - const StructType *ST = dyn_cast<StructType>(PT->getElementType()); - if (0) { -#endif - //It is a struct type with pointers - //for each pointer with struct typ - //we need to watchg out for arrays inside structs - if (ConstantInt *COP = dyn_cast<ConstantInt>(MAI->getOperand(1))) { - //FIXME assuming that the first index is safe - //assert((COP->getRawValue() == 0) && "non zero array index\n"); - bool allconstant = true; - for (unsigned i = 2; i < MAI->getNumOperands(); ++i) { - if (!isa<Constant>(MAI->getOperand(i))) { - allconstant = false; - break; - } - } - if (!allconstant) { - if (MAI->getNumOperands() == 4) { - if (ConstantInt *COPi = dyn_cast<ConstantInt>(MAI->getOperand(2))) { - const Type *stel = ST->getElementType(COPi->getZExtValue()); - if (const ArrayType *elAT = dyn_cast<ArrayType>(stel)) { - //Need to factor this in to separate method!!! - Value * secOp = MAI->getOperand(3); - Value *indexTypeSize = ConstantInt::get(Type::UIntTy, TD->getTypeSize(secOp->getType())); -#ifdef LLVA_KERNEL - // - // Determine whether the exactcheck() will have constant integer - // arguments. If so, then we can evaluate them statically and avoid - // inserting the run-time check. - // - if (ConstantInt * Index = dyn_cast<ConstantInt>(secOp)) { - int index = Index->getSExtValue(); - assert ((index < 0) && "exactcheck will fail at runtime"); - if (index < TD->getTypeSize(elAT)) - return; - assert (0 && "exactcheck out of range"); - } -#endif - if (secOp->getType() != Type::IntTy) { - secOp = new CastInst(secOp, Type::IntTy, - secOp->getName()+".casted", MAI); - } - // secOp = BinaryOperator::create(Instruction::Mul, indexTypeSize, secOp,"indextmp", MAI); - std::vector<Value *> args(1,secOp); - Value *AllocSize = - ConstantInt::get(Type::IntTy, TD->getTypeSize(elAT)); - /* - if (AI->isArrayAllocation()) - AllocSize = BinaryOperator::create(Instruction::Mul, - AllocSize, - AI->getOperand(0), "sizetmp", MAI); - */ - // args.push_back(ConstantInt::get(csiType,elAT->getNumElements())); - args.push_back(AllocSize); - new CallInst(ExactCheck,args,"",MAI); - - } else { - //non array, non constant value - abort(); - } - } else { - // non-constant value, not possible - abort(); - } - } else { -#if 0 - //FIXME this is a less precise check than possible - // std::cerr << "WARNING : did not handle array within a struct precisely, num operands != 4\n"; - Instruction *InsertPt = MAI->getNext(); - Type *VoidPtrType = PointerType::get(Type::SByteTy); - Value *MAIPSbyte = new CastInst(MAI->getPointerOperand(), - VoidPtrType, - MAI->getPointerOperand()->getName()+".casted",InsertPt); - - Value *MAISbyte = new CastInst(MAI, - VoidPtrType, - MAI->getName()+".casted",InsertPt); - - std::vector<Value *> args(1,MAIPSbyte); - args.push_back(MAISbyte); - Value *AllocSize = - ConstantInt::get(Type::UIntTy, TD->getTypeSize(ST)); - args.push_back(AllocSize); - new CallInst(ExactCheck2,args,"",InsertPt); -#endif - } - } else { - std::cerr << "Not all args constant: " << *MAI << std::endl; - } - } else { - std::cerr << "HandleLikeArray: " << *MAI << std::endl; - goto HandleThisLikeArray; - } - } else { - HandleThisLikeArray: - if (AllocaInst *AI = dyn_cast<AllocaInst>(MAI->getPointerOperand())) { - //we can put an exact check here - if (1 || (MAI->getNumOperands() == 3)) { - if (ConstantInt *COP = dyn_cast<ConstantInt>(MAI->getOperand(1))) { - //FIXME assuming that the first array index is 0 -#if 0 - assert((COP->getZExtValue() == 0) && "non zero array index\n"); -#else - if (COP->getZExtValue() == 0) { -#endif - Value * secOp = MAI->getOperand(2); - Value *indexTypeSize = ConstantInt::get(Type::UIntTy, TD->getTypeSize(secOp->getType())); -#ifdef LLVA_KERNEL - // - // Determine whether the exactcheck() will have constant integer - // arguments. If so, then we can evaluate them statically and avoid - // inserting the run-time check. - // - if (!(AI->isArrayAllocation())) - if (ConstantInt * Index = dyn_cast<ConstantInt>(secOp)) { - int index = Index->getSExtValue(); - if ((index > 0) && (index < TD->getTypeSize(AI->getAllocatedType()))) - return; - } -#endif - //Convert everything to bytes - if (secOp->getType() != Type::IntTy) { - secOp = new CastInst(secOp, Type::IntTy, secOp->getName()+".casted", - MAI); - } - // secOp = BinaryOperator::create(Instruction::Mul, indexTypeSize, secOp,"indextmp",MAI); - std::vector<Value *> args(1,secOp); - Value *AllocSize = - ConstantInt::get(Type::IntTy, TD->getTypeSize(AI->getAllocatedType())); - - if (AI->isArrayAllocation()) - AllocSize = BinaryOperator::create(Instruction::Mul, - AllocSize, - AI->getOperand(0), "sizetmp", MAI); - - args.push_back(AllocSize); - CallInst *newCI = new CallInst(ExactCheck,args,"", MAI); - } else { - std::cerr << "COP not zero: " << *MAI << std::endl; - } - } else { - std::cerr << "Bad COP: " << *MAI << std::endl; - } - } else { - std::cerr << " num operands != 3: " << *MAI << std::endl; - abort(); - } - } else { - // Now check if the GEP is inside a loop with monotonically increasing - //loop bounds - //We use the LoopInfo Pass this - Loop *L = LI->getLoopFor(MAI->getParent()); - bool monotonicOpt = false; - if (L && (MAI->getNumOperands() == 2)) { - bool HasConstantItCount = isa<SCEVConstant>(scevPass->getIterationCount(L)); - Value *vIndex = MAI->getOperand(1); - if (Instruction *Index = dyn_cast<Instruction>(vIndex)) { - //If it is not an instruction then it must already be loop invariant - if (L->isLoopInvariant(MAI->getPointerOperand())) { - SCEVHandle SH = scevPass->getSCEV(Index); - if (SH->hasComputableLoopEvolution(L) || // Varies predictably - HasConstantItCount) { - if (SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(SH)) - if (AR->isAffine()) { - SCEVHandle EntryValue = AR->getStart(); - // EntryValue->getValueRange().dump(); - // Index->dump(); - SCEVHandle ExitValue = scevPass->getSCEVAtScope(Index, L->getParentLoop()); - BasicBlock *Preheader = L->getLoopPreheader(); - if ((Preheader) && - (!isa<SCEVCouldNotCompute>(ExitValue)) ){ - SCEVExpander Rewriter(*scevPass, *LI); - Instruction *ptIns = Preheader->getTerminator(); - Value *NewVal = Rewriter.expandCodeFor(ExitValue, ptIns, - Index->getType()); - // NewVal->dump(); - if (!isa<SCEVCouldNotCompute>(EntryValue)) { - Value *NewVal2 = Rewriter.expandCodeFor(EntryValue, ptIns, - Index->getType()); - // NewVal2->dump(); - //Inserted the values now insert GEPs and add checks - std::vector<Value *> gepargs1(1,NewVal); - GetElementPtrInst *GEPUpper = - new GetElementPtrInst(MAI->getPointerOperand(), gepargs1, MAI->getName()+"upbc", ptIns); - insertBoundsCheck (MAI, GEPUpper->getPointerOperand(), GEPUpper, ptIns); - std::vector<Value *> gepargs2(1,NewVal2); - GetElementPtrInst *GEPLower = - new GetElementPtrInst(MAI->getPointerOperand(), gepargs2, MAI->getName()+"lobc", ptIns); - insertBoundsCheck (MAI, GEPLower->getPointerOperand(), GEPLower, ptIns); - monotonicOpt = true; - ++MonotonicOpts; - } - } - } - } - } - } - } - if (!monotonicOpt) { - // - // Insert a bounds check and use its return value in all subsequent - // uses. - // - Instruction *nextIns = MAI->getNext(); - insertBoundsCheck (MAI, MAI->getPointerOperand(), MAI, nextIns); - } - } - } - } else { - std::cerr << "GEP does not have pointer type arg" << *MAI << std::endl; - abort(); - } - } -} - - void InsertPoolChecks::addGetActualValue(SetCondInst *SCI, unsigned operand) { - //we know that the operand is a pointer type - Value *op = SCI->getOperand(operand); - Function *F = SCI->getParent()->getParent(); -#ifndef LLVA_KERNEL -#ifdef NOEQUIV - if (!equivPass->ContainsDSGraphFor(*F)) { - //some times the ECGraphs doesnt contain F - //for newly created cloned functions - PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F); - op = FI->MapValueToOriginal(op); - if (!op) return; //abort(); - } -#endif -#endif - Function *Fnew = F; - Value *PH = 0; - if (Argument *arg = dyn_cast<Argument>(op)) { - Fnew = arg->getParent(); - PH = getPoolHandle(op, Fnew); - } else if (Instruction *Inst = dyn_cast<Instruction>(op)) { - Fnew = Inst->getParent()->getParent(); - PH = getPoolHandle(op, Fnew); - } else if (isa<Constant>(op)) { - return; - // abort(); - } else if (!isa<ConstantPointerNull>(op)) { - //has to be a global - abort(); - } - op = SCI->getOperand(operand); - if (!isa<ConstantPointerNull>(op)) { - if (PH) { - if (1) { //HACK fixed - Type *VoidPtrType = PointerType::get(Type::SByteTy); - Value *PHVptr = new CastInst(PH, VoidPtrType, - PH->getName()+".casted", SCI); - Value *OpVptr = op; - if (op->getType() != VoidPtrType) - OpVptr = new CastInst(op, VoidPtrType, - op->getName()+".casted", SCI); - - std::vector<Value *> args = make_vector(PHVptr, OpVptr,0); - CallInst *CI = new CallInst(GetActualValue, args,"getval", SCI); - CastInst *CastBack = new CastInst(CI, op->getType(), op->getName()+".castback",SCI); - SCI->setOperand(operand, CastBack); + Module::global_iterator GI = M.global_begin(), GE = M.global_end(); + for ( ; GI != GE; ++GI) { + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GI)) { + Type *VoidPtrType = PointerType::get(Type::SByteTy); + Type *PoolDescType = ArrayType::get(VoidPtrType, 50); + Type *PoolDescPtrTy = PointerType::get(PoolDescType); + if (GV->getType() != PoolDescPtrTy) { + DSGraph &G = equivPass->getGlobalsGraph(); + DSNode *DSN = G.getNodeForValue(GV).getNode(); + if ((isa<ArrayType>(GV->getType()->getElementType())) || DSN->isNodeCompletelyFolded()) { + Value * AllocSize; + const Type* csiType = Type::getPrimitiveType(Type::UIntTyID); + if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) { + //std::cerr << "found global \n"; + AllocSize = ConstantInt::get(csiType, + (AT->getNumElements() * TD->getTypeSize(AT->getElementType()))); + } else { + AllocSize = ConstantInt::get(csiType, TD->getTypeSize(GV->getType())); + } + Function *PoolRegister = paPass->PoolRegister; + BasicBlock::iterator InsertPt = MainFunc->getEntryBlock().begin(); + //skip the calls to poolinit + while ((isa<CallInst>(InsertPt)) || isa<CastInst>(InsertPt) || isa<AllocaInst>(InsertPt) || isa<BinaryOperator>(InsertPt)) ++InsertPt; + + std::map<const DSNode *, Value *>::iterator I = paPass->GlobalNodes.find(DSN); + if (I != paPass->GlobalNodes.end()) { + Value *PH = I->second; + Instruction *GVCasted = new CastInst(GV, + VoidPtrType, GV->getName()+"casted",InsertPt); + new CallInst(PoolRegister, + make_vector(PH, AllocSize, GVCasted, 0), + "", InsertPt); + } else { + std::cerr << "pool descriptor not present \n "; + abort(); + } + } } - } else { - //It shouldn't work if PH is not null } } } - -void InsertPoolChecks::TransformFunction (Function & F) { -#ifndef LLVA_KERNEL - PA::FuncInfo * PAFI = paPass->getFuncInfoOrClone(F); - if (PAFI->Clone && PAFI->Clone != &F) { - //no need to transform - return; - } -#endif - inst_iterator I = inst_begin(F); - while (I != inst_end(F)) { - Instruction *iLocal = &*I; - if (SetCondInst *SCI = dyn_cast<SetCondInst>(iLocal)) { - //If it is neq, eq, - if ((SCI->getOpcode() == BinaryOperator::SetEQ) || (SCI->getOpcode() == BinaryOperator::SetNE)) { - //for all the pointer operands replace them by the getactualvalue - assert((SCI->getNumOperands() == 2) && "nmber of operands for SCI different from 2 "); - if (isa<PointerType>(SCI->getOperand(0)->getType())) { - //we need to insert a call to getactualvalue - //First get the poolhandle for the pointer - // TODO: We don't have a working getactualvalue(), so don't waste - // time calling it. -#if 0 - if ((!isa<ConstantPointerNull>(SCI->getOperand(0))) && (!isa<ConstantPointerNull>(SCI->getOperand(1)))) { - addGetActualValue(SCI, 0); - addGetActualValue(SCI, 1); - } #endif - } - } - } else if (isa<CastInst>(iLocal)) { - //Some times the getelementptr is an argument of cast instruction - // and we don't want to miss a run-time check there - if (isa<GetElementPtrInst>(iLocal->getOperand(0))) { - iLocal = cast<Instruction>(iLocal->getOperand(0)); - } - } // - // we need to handle - // alloca instructions - // getelement ptrs - // load store checks - if (isa<GetElementPtrInst>(iLocal)) { - GetElementPtrInst *MAI = cast<GetElementPtrInst>(iLocal); - ++I; - std::set<Instruction *> CheckSet; - AggregateGEPs (MAI, CheckSet); - for (std::set<Instruction *>::iterator GEP = CheckSet.begin(); - GEP != CheckSet.end(); ++GEP) { - Instruction * I = *GEP; - GetElementPtrInst * GEPI = dyn_cast<GetElementPtrInst>(I); - handleGetElementPtr(GEPI); - } - continue; - } else if (AllocaInst *AI = dyn_cast<AllocaInst>(iLocal)) { - AllocaInst * AIOrig = AI; - if (!DisableStackChecks) { -#ifndef LLVA_KERNEL -#ifdef NOEQUIV - if (!equivPass->ContainsDSGraphFor(F)) { - //some times the ECGraphs doesnt contain F - //for newly created cloned functions - PA::FuncInfo *FI = paPass->getFuncInfoOrClone(F); - Value *temp = FI->MapValueToOriginal(AI); - if (temp) - AIOrig = dyn_cast<AllocaInst>(temp); - else - continue; - assert(AIOrig && " Instruction not in value map (clone)\n"); - } -#endif -#endif - ++I; - registerAllocaInst(AI, AIOrig); - continue; - } - } else if (CallInst *CI = dyn_cast<CallInst>(iLocal)) { - ++I; - handleCallInst(CI); - continue; - } - - // - // Move to the next instruction. - // - ++I; - } +void InsertPoolChecks::addPoolChecks(Module &M) { + if (!DisableGEPChecks) addGetElementPtrChecks(M); + if (!DisableLSChecks) addLoadStoreChecks(M); } -void InsertPoolChecks::registerAllocaInst(AllocaInst *AI, AllocaInst *AIOrig) { - // - // Get the pool handle for the node that this contributes to... - // - Function *FOrig = AIOrig->getParent()->getParent(); - DSNode *Node = getDSNode(AIOrig, FOrig); - if (!Node) return; - assert ((Node->isAllocaNode()) && "DSNode for alloca is missing stack flag!"); - - // - // Only register the stack allocation if it may be the subject of a run-time - // check. This can only occur when the object is used like an array because: - // 1) GEP checks are only done when accessing arrays. - // 2) Load/Store checks are only done on collapsed nodes (which appear to be - // used like arrays). - // - if (!(Node->isArray())) - return; - - // - // Determine if any use (direct or indirect) escapes this function. If not, - // then none of the checks will consult the MetaPool, and we can forego - // registering the alloca. - // - bool MustRegisterAlloca = false; - std::vector<Value *> AllocaWorkList; - AllocaWorkList.push_back (AI); - while ((!MustRegisterAlloca) && (AllocaWorkList.size())) { - Value * V = AllocaWorkList.back(); - AllocaWorkList.pop_back(); - Value::use_iterator UI = V->use_begin(); - for (; UI != V->use_end(); ++UI) { - // We cannot handle PHI nodes or Select instructions - if (isa<PHINode>(UI) || isa<SelectInst>(UI)) { - MustRegisterAlloca = true; - continue; - } - - // The pointer escapes if it's stored to memory somewhere. - StoreInst * SI; - if ((SI = dyn_cast<StoreInst>(UI)) && (SI->getOperand(0) == V)) { - MustRegisterAlloca = true; - continue; - } - - // GEP instructions are okay, but need to be added to the worklist - if (isa<GetElementPtrInst>(UI)) { - AllocaWorkList.push_back (*UI); - continue; - } - - // Cast instructions are okay as long as they cast to another pointer - // type - if (CastInst * CI = dyn_cast<CastInst>(UI)) { - if (isa<PointerType>(CI->getType())) { - AllocaWorkList.push_back (*UI); - continue; - } else { - MustRegisterAlloca = true; - continue; - } - } - - if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(UI)) { - if (cExpr->getOpcode() == Instruction::Cast) { - AllocaWorkList.push_back (*UI); - continue; - } else { - MustRegisterAlloca = true; - continue; - } - } - - CallInst * CI1; - if (CI1 = dyn_cast<CallInst>(UI)) { - if (!(CI1->getCalledFunction())) { - MustRegisterAlloca = true; - continue; - } - - std::string FuncName = CI1->getCalledFunction()->getName(); - if (FuncName == "exactcheck3") { - AllocaWorkList.push_back (*UI); - continue; - } else if ((FuncName == "llvm.memcpy.i32") || - (FuncName == "llvm.memcpy.i64") || - (FuncName == "llvm.memset.i32") || - (FuncName == "llvm.memset.i64") || - (FuncName == "llvm.memmove.i32") || - (FuncName == "llvm.memmove.i64") || - (FuncName == "llva_memcpy") || - (FuncName == "llva_memset") || - (FuncName == "llva_strncpy") || - (FuncName == "llva_invokememcpy") || - (FuncName == "llva_invokestrncpy") || - (FuncName == "llva_invokememset") || - (FuncName == "memcmp")) { - continue; - } else { - MustRegisterAlloca = true; - continue; - } - } - } - } - - if (!MustRegisterAlloca) { - ++SavedRegAllocs; - return; - } - - // - // Insert the alloca registration. - // - Value *PH = getPoolHandle(AIOrig, FOrig); - if (PH == 0 || isa<ConstantPointerNull>(PH)) return; - - Value *AllocSize = - ConstantInt::get(Type::UIntTy, TD->getTypeSize(AI->getAllocatedType())); - - if (AI->isArrayAllocation()) - AllocSize = BinaryOperator::create(Instruction::Mul, AllocSize, - AI->getOperand(0), "sizetmp", AI); - - // Insert object registration at the end of allocas. - Instruction *iptI = AI->getNext(); - if (AI->getParent() == (&(AI->getParent()->getParent()->getEntryBlock()))) { - BasicBlock::iterator InsertPt = AI->getParent()->begin(); - while (&(*(InsertPt)) != AI) - ++InsertPt; - while (isa<AllocaInst>(InsertPt)) - ++InsertPt; - iptI = InsertPt; - } - - // - // Insert a call to register the object. - // - Instruction *Casted = new CastInst(AI, PointerType::get(Type::SByteTy), - AI->getName()+".casted", iptI); - Value *CastedPH = new CastInst(PH, - PointerType::get(Type::SByteTy), - "allocph",Casted); - new CallInst(StackRegister, - make_vector(CastedPH, Casted, AllocSize,0), - "", iptI); - - // - // Insert a call to unregister the object whenever the function can exit. - // - for (Function::iterator BB = AI->getParent()->getParent()->begin(); - BB != AI->getParent()->getParent()->end(); - ++BB) { - iptI = BB->getTerminator(); - if (isa<ReturnInst>(iptI) || isa<UnwindInst>(iptI)) - new CallInst(StackFree, - make_vector(CastedPH, Casted, 0), - "", iptI); - } - - // Update statistics - ++StackRegisters; -} - -// -// Method: insertAlignmentCheck() -// -// Description: -// Insert an alignment check for the specified value. -// -void -InsertPoolChecks::insertAlignmentCheck (LoadInst * LI) { - // Get the function containing the load instruction - Function * F = LI->getParent()->getParent(); - - // Get the DSNode for the result of the load instruction. If it is type - // unknown, then no alignment check is needed. - DSNode * LoadResultNode = getDSNode (LI,F); - if (!(LoadResultNode && (!(LoadResultNode->isNodeCompletelyFolded())))) { - return; - } - - // - // Get the pool handle for the node. - // - Value *PH = getPoolHandle(LI, F); - if (!PH) return; - - // - // If the node is incomplete or unknown, then only perform the check if - // checks to incomplete or unknown are allowed. - // - Function * ThePoolCheckFunction = PoolCheckAlign; - if ((LoadResultNode->isUnknownNode()) || (LoadResultNode->isIncomplete())) { - if (EnableUnknownChecks) { - ThePoolCheckFunction = PoolCheckAlignUI; - } else { - ++MissedIncompleteChecks; - return; - } - } - - // - // A check is needed. Scan through the links of the DSNode of the load's - // pointer operand; we need to determine the offset for the alignment check. - // - DSNode * Node = getDSNode (LI->getPointerOperand(), F); - if (!Node) return; - for (unsigned i = 0 ; i < Node->getNumLinks(); ++i) { - DSNodeHandle & LinkNode = Node->getLink(i); - if (LinkNode.getNode() == LoadResultNode) { - // Insertion point for this check is *after* the load. - Instruction * InsertPt = LI->getNext(); - - // Create instructions to cast the checked pointer and the checked pool - // into sbyte pointers. - Value *CastVI = castTo (LI, PointerType::get(Type::SByteTy), InsertPt); - Value *CastPHI = castTo (PH, PointerType::get(Type::SByteTy), InsertPt); - - // Create the call to poolcheck - std::vector<Value *> args(1,CastPHI); - args.push_back(CastVI); - args.push_back (ConstantInt::get(Type::UIntTy, LinkNode.getOffset())); - new CallInst (PoolCheckAlign,args, "", InsertPt); - - // Update the statistics - ++AlignLSChecks; - - break; - } - } -} - #ifdef LLVA_KERNEL // // Method: addLSChecks() @@ -3377,111 +187,94 @@ // Insert a poolcheck() into the code for a load or store instruction. // void InsertPoolChecks::addLSChecks(Value *V, Instruction *I, Function *F) { - // Get the DSNode for the pointer to check - DSNode * Node = getDSNode (V,F); - - // - // Do not perform any checks if there is no DSNode, if the node is not folded, - // or if the node is incomplete. - // - if (!(Node && Node->isNodeCompletelyFolded())) - return; - - // - // If the node is not registered, don't bother to check it. - // - if (!(isNodeRegistered (Node))) - return; - - // - // We will perform checks on incomplete or unknown nodes, but we must accept - // the possibility that the object will not be found. - // - Function * ThePoolCheckFunction = PoolCheck; - if ((Node->isUnknownNode()) || (Node->isIncomplete())) { - if (EnableUnknownChecks) { - ThePoolCheckFunction = PoolCheckUI; - } else { - ++MissedIncompleteChecks; - return; + DSGraph & TDG = TDPass->getDSGraph(*F); + DSNode * Node = TDG.getNodeForValue(V).getNode(); + + if (Node && Node->isNodeCompletelyFolded()) { + if (!EnableIncompleteChecks) { + if (Node->isIncomplete()) { + ++MissedIncompleteChecks; + return; + } } + // Get the pool handle associated with this pointer. If there is no pool + // handle, use a NULL pointer value and let the runtime deal with it. + Value *PH = getPoolHandle(V, F); +#ifdef DEBUG +std::cerr << "LLVA: addLSChecks: Pool " << PH << " Node " << Node << std::endl; +#endif + // FIXME: We cannot handle checks to global or stack positions right now. + if ((!PH) || (Node->isAllocaNode()) || (Node->isGlobalNode())) { + ++NullChecks; + if (!PH) ++MissedNullChecks; + if (Node->isAllocaNode()) ++MissedStackChecks; + if (Node->isGlobalNode()) ++MissedGlobalChecks; + + // Don't bother to insert the NULL check unless the user asked + if (!EnableNullChecks) + return; + PH = Constant::getNullValue(PointerType::get(Type::SByteTy)); + } else { + // + // Only add the pool check if the pool is a global value or it + // belongs to the same basic block. + // + if (isa<GlobalValue>(PH)) { + ++FullChecks; + } else if (isa<Instruction>(PH)) { + Instruction * IPH = (Instruction *)(PH); + if (IPH->getParent() == I->getParent()) { + // + // If the instructions belong to the same basic block, ensure that + // the pool dominates the load/store. + // + Instruction * IP = IPH; + for (IP=IPH; (IP->isTerminator()) || (IP == I); IP=IP->getNext()) { + ; + } + if (IP == I) + ++FullChecks; + else { + ++MissChecks; + return; + } + } else { + ++MissChecks; + return; + } + } else { + ++MissChecks; + return; + } + } + // Create instructions to cast the checked pointer and the checked pool + // into sbyte pointers. + CastInst *CastVI = + new CastInst(V, + PointerType::get(Type::SByteTy), "node.lscasted", I); + CastInst *CastPHI = + new CastInst(PH, + PointerType::get(Type::SByteTy), "poolhandle.lscasted", I); + + // Create the call to poolcheck + std::vector<Value *> args(1,CastPHI); + args.push_back(CastVI); + new CallInst(PoolCheck,args,"", I); } - - // - // This may be a load instruction that loads a pointer that: - // 1) Points to a type known pool, and - // 2) Loaded from a type unknown pool - // - // If this is the case, we need to perform an alignment check on the result - // of the load. Do that here. - // - if (LoadInst * LI = dyn_cast<LoadInst>(I)) { - insertAlignmentCheck (LI); - } - - // - // Do not perform a load/store check if the pointer used for this operation - // has already been checked. - // - if (findCheckedPointer(V)) { - ++SavedPoolChecks; - return; - } - - // Get the pool handle associated with this pointer. If there is no pool - // handle, use a NULL pointer value and let the runtime deal with it. - Value *PH = getPoolHandle(V, F); - - if (!PH) { - // Update the number of poolchecks that won't do anything - ++NullChecks; - - // Update the stats on why there will be no check - ++MissedNullChecks; - - // Don't bother to insert the NULL check unless the user requested it - if (!EnableNullChecks) - return; - PH = Constant::getNullValue(PointerType::get(Type::SByteTy)); - } else { - // This will be a full check; update the stats. - assert (isa<GlobalValue>(PH)); - ++FullChecks; - } - - // Create instructions to cast the checked pointer and the checked pool - // into sbyte pointers. - Value *CastVI = castTo (V, PointerType::get(Type::SByteTy), I); - Value *CastPHI = castTo (PH, PointerType::get(Type::SByteTy), I); - - // Create the call to poolcheck - std::vector<Value *> args(1,CastPHI); - args.push_back(CastVI); - new CallInst (ThePoolCheckFunction ,args, "", I); } -void InsertPoolChecks::addLoadStoreChecks (Function & FR) { - Function *F = &FR; - for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { - if (LoadInst *LI = dyn_cast<LoadInst>(&*I)) { - Value *P = LI->getPointerOperand(); - addLSChecks(P, LI, F); - } else if (StoreInst *SI = dyn_cast<StoreInst>(&*I)) { - Value *P = SI->getPointerOperand(); - addLSChecks(P, SI, F); - } else if (CallInst * CI = dyn_cast<CallInst>(&*I)) { - if (Function * CalledFunc = CI->getCalledFunction()) { - if ((CalledFunc->getName() == "llva_atomic_compare_and_swap") || - (CalledFunc->getName() == "llva_atomic_cas_lw") || - (CalledFunc->getName() == "llva_atomic_cas_h") || - (CalledFunc->getName() == "llva_atomic_cas_b") || - (CalledFunc->getName() == "llva_atomic_fetch_add_store") || - (CalledFunc->getName() == "llva_atomic_and") || - (CalledFunc->getName() == "llva_atomic_or")) { - Value * P = CI->getOperand(1); - addLSChecks (P, CI, F); - } - } +void InsertPoolChecks::addLoadStoreChecks(Module &M){ + Module::iterator mI = M.begin(), mE = M.end(); + for ( ; mI != mE; ++mI) { + Function *F = mI; + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (LoadInst *LI = dyn_cast<LoadInst>(&*I)) { + Value *P = LI->getPointerOperand(); + addLSChecks(P, LI, F); + } else if (StoreInst *SI = dyn_cast<StoreInst>(&*I)) { + Value *P = SI->getPointerOperand(); + addLSChecks(P, SI, F); + } } } } @@ -3543,94 +336,480 @@ } } -void InsertPoolChecks::addLoadStoreChecks(Function & Func){ - Function *F = &Func; - //here we check that we only do this on original functions - //and not the cloned functions, the cloned functions may not have the - //DSG - bool isClonedFunc = false; - if (paPass->getFuncInfo(*F)) - isClonedFunc = false; - else - isClonedFunc = true; - Function *Forig = F; - PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F); - if (isClonedFunc) { - Forig = paPass->getOrigFunctionFromClone(F); - } - //we got the original function - for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { - if (LoadInst *LI = dyn_cast<LoadInst>(&*I)) { -//we need to get the LI from the original function -Value *P = LI->getPointerOperand(); -if (isClonedFunc) { - assert(FI->NewToOldValueMap.count(LI) && " not in the value map \n"); - const LoadInst *temp = dyn_cast<LoadInst>(FI->NewToOldValueMap[LI]); - assert(temp && " Instruction not there in the NewToOldValue map"); - const Value *Ptr = temp->getPointerOperand(); - addLSChecks(P, Ptr, LI, Forig); -} else { - addLSChecks(P, P, LI, Forig); -} - } else if (StoreInst *SI = dyn_cast<StoreInst>(&*I)) { -Value *P = SI->getPointerOperand(); -if (isClonedFunc) { - assert(FI->NewToOldValueMap.count(SI) && " not in the value map \n"); - const StoreInst *temp = dyn_cast<StoreInst>(FI->NewToOldValueMap[SI]); - assert(temp && " Instruction not there in the NewToOldValue map"); - const Value *Ptr = temp->getPointerOperand(); - addLSChecks(P, Ptr, SI, Forig); -} else { - addLSChecks(P, P, SI, Forig); -} - } else if (CallInst *CI = dyn_cast<CallInst>(&*I)) { -Value *FunctionOp = CI->getOperand(0); -if (!isa<Function>(FunctionOp)) { - if (isClonedFunc) { - assert(FI->NewToOldValueMap.count(CI) && " not in the value map \n"); - const CallInst *temp = dyn_cast<CallInst>(FI->NewToOldValueMap[CI]); - assert(temp && " Instruction not there in the NewToOldValue map"); - const Value* FunctionOp1 = temp->getOperand(0); - addLSChecks(FunctionOp, FunctionOp1, CI, Forig); - } else { - addLSChecks(FunctionOp, FunctionOp, CI, Forig); - } -} - } +void InsertPoolChecks::addLoadStoreChecks(Module &M){ + Module::iterator mI = M.begin(), mE = M.end(); + for ( ; mI != mE; ++mI) { + Function *F = mI; + //here we check that we only do this on original functions + //and not the cloned functions, the cloned functions may not have the + //DSG + bool isClonedFunc = false; + if (paPass->getFuncInfo(*F)) + isClonedFunc = false; + else + isClonedFunc = true; + Function *Forig = F; + PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F); + if (isClonedFunc) { + Forig = paPass->getOrigFunctionFromClone(F); + } + //we got the original function + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (LoadInst *LI = dyn_cast<LoadInst>(&*I)) { + //we need to get the LI from the original function + Value *P = LI->getPointerOperand(); + if (isClonedFunc) { + assert(FI->NewToOldValueMap.count(LI) && " not in the value map \n"); + const LoadInst *temp = dyn_cast<LoadInst>(FI->NewToOldValueMap[LI]); + assert(temp && " Instruction not there in the NewToOldValue map"); + const Value *Ptr = temp->getPointerOperand(); + addLSChecks(P, Ptr, LI, Forig); + } else { + addLSChecks(P, P, LI, Forig); + } + } else if (StoreInst *SI = dyn_cast<StoreInst>(&*I)) { + Value *P = SI->getPointerOperand(); + if (isClonedFunc) { + assert(FI->NewToOldValueMap.count(SI) && " not in the value map \n"); + const StoreInst *temp = dyn_cast<StoreInst>(FI->NewToOldValueMap[SI]); + assert(temp && " Instruction not there in the NewToOldValue map"); + const Value *Ptr = temp->getPointerOperand(); + addLSChecks(P, Ptr, SI, Forig); + } else { + addLSChecks(P, P, SI, Forig); + } + } else if (CallInst *CI = dyn_cast<CallInst>(&*I)) { + Value *FunctionOp = CI->getOperand(0); + if (!isa<Function>(FunctionOp)) { + if (isClonedFunc) { + assert(FI->NewToOldValueMap.count(CI) && " not in the value map \n"); + const CallInst *temp = dyn_cast<CallInst>(FI->NewToOldValueMap[CI]); + assert(temp && " Instruction not there in the NewToOldValue map"); + const Value* FunctionOp1 = temp->getOperand(0); + addLSChecks(FunctionOp, FunctionOp1, CI, Forig); + } else { + addLSChecks(FunctionOp, FunctionOp, CI, Forig); + } + } + } + } } } #endif -// -// Method: getDSGraph() -// -// Description: -// Return the DSGraph for the given function. This method automatically -// selects the correct pass to query for the graph based upon whether we're -// doing user-space or kernel analysis. -// -DSGraph & -InsertPoolChecks::getDSGraph(Function & F) { -#ifndef LLVA_KERNEL - return equivPass->getDSGraph(F); -#else - return TDPass->getDSGraph(F); -#endif +void InsertPoolChecks::addGetElementPtrChecks(Module &M) { + std::vector<Instruction *> & UnsafeGetElemPtrs = cuaPass->getUnsafeGetElementPtrsFromABC(); + std::vector<Instruction *>::const_iterator iCurrent = UnsafeGetElemPtrs.begin(), iEnd = UnsafeGetElemPtrs.end(); + for (; iCurrent != iEnd; ++iCurrent) { + // We have the GetElementPtr + if (!isa<GetElementPtrInst>(*iCurrent)) { + //Then this must be a function call + //FIXME, get strcpy and others from the backup dir and adjust them for LLVA + //Right now I just add memset &llva_memcpy for LLVA + // std::cerr << " function call \n"; +#ifdef LLVA_KERNEL + CallInst *CI = dyn_cast<CallInst>(*iCurrent); + if (CI && (!DisableIntrinsicChecks)) { + Value *Fop = CI->getOperand(0); + Function *F = CI->getParent()->getParent(); + if (Fop->getName() == "llva_memcpy") { + Value *PH = getPoolHandle(CI->getOperand(1), F); + Instruction *InsertPt = CI; + if (!PH) { + ++NullChecks; + ++MissedNullChecks; + + // Don't bother to insert the NULL check unless the user asked + if (!EnableNullChecks) + continue; + PH = Constant::getNullValue(PointerType::get(Type::SByteTy)); + } + CastInst *CastCIUint = + new CastInst(CI->getOperand(1), Type::UIntTy, "node.lscasted", InsertPt); + CastInst *CastCIOp3 = + new CastInst(CI->getOperand(3), Type::UIntTy, "node.lscasted", InsertPt); + Instruction *Bop = BinaryOperator::create(Instruction::Add, CastCIUint, + CastCIOp3, "memcpyadd",InsertPt); + + // Create instructions to cast the checked pointer and the checked pool + // into sbyte pointers. + CastInst *CastSourcePointer = + new CastInst(CI->getOperand(1), + PointerType::get(Type::SByteTy), "memcpy.1.casted", InsertPt); + CastInst *CastCI = + new CastInst(Bop, + PointerType::get(Type::SByteTy), "mempcy.2.casted", InsertPt); + CastInst *CastPHI = + new CastInst(PH, + PointerType::get(Type::SByteTy), "poolhandle.lscasted", InsertPt); + + // Create the call to poolcheck + std::vector<Value *> args(1,CastPHI); + args.push_back(CastSourcePointer); + args.push_back(CastCI); + new CallInst(PoolCheckArray,args,"", InsertPt); +#if 0 + } else if (Fop->getName() == "memset") { + Value *PH = getPoolHandle(CI->getOperand(1), F); + Instruction *InsertPt = CI->getNext(); + if (!PH) { + NullChecks++; + // Don't bother to insert the NULL check unless the user asked + if (!EnableNullChecks) + continue; + PH = Constant::getNullValue(PointerType::get(Type::SByteTy)); + } + CastInst *CastCIUint = + new CastInst(CI, Type::UIntTy, "node.lscasted", InsertPt); + CastInst *CastCIOp3 = + new CastInst(CI->getOperand(3), Type::UIntTy, "node.lscasted", InsertPt); + Instruction *Bop = BinaryOperator::create(Instruction::Add, CastCIUint, + CastCIOp3, "memsetadd",InsertPt); + + // Create instructions to cast the checked pointer and the checked pool + // into sbyte pointers. + CastInst *CastSourcePointer = + new CastInst(CI->getOperand(1), + PointerType::get(Type::SByteTy), "memset.1.casted", InsertPt); + CastInst *CastCI = + new CastInst(Bop, + PointerType::get(Type::SByteTy), "memset.2.casted", InsertPt); + CastInst *CastPHI = + new CastInst(PH, + PointerType::get(Type::SByteTy), "poolhandle.lscasted", InsertPt); + + // Create the call to poolcheck + std::vector<Value *> args(1,CastPHI); + args.push_back(CastSourcePointer); + args.push_back(CastCI); + new CallInst(PoolCheckArray,args,"", InsertPt); +#endif + } + } +#endif + continue; + } + GetElementPtrInst *GEP = cast<GetElementPtrInst>(*iCurrent); + Function *F = GEP->getParent()->getParent(); + // Now we need to decide if we need to pass in the alignmnet + //for the poolcheck + // if (getDSNodeOffset(GEP->getPointerOperand(), F)) { + // std::cerr << " we don't handle middle of structs yet\n"; + //assert(!getDSNodeOffset(GEP->getPointerOperand(), F) && " we don't handle middle of structs yet\n"); + // ++MissChecks; + // continue; + // } + +#ifndef LLVA_KERNEL + PA::FuncInfo *FI = paPass->getFuncInfoOrClone(*F); + Instruction *Casted = GEP; + if (!FI->ValueMap.empty()) { + assert(FI->ValueMap.count(GEP) && "Instruction not in the value map \n"); + Instruction *temp = dyn_cast<Instruction>(FI->ValueMap[GEP]); + assert(temp && " Instruction not there in the Value map"); + Casted = temp; + } + if (GetElementPtrInst *GEPNew = dyn_cast<GetElementPtrInst>(Casted)) { + Value *PH = getPoolHandle(GEP, F, *FI); + if (PH && isa<ConstantPointerNull>(PH)) continue; + if (!PH) { + Value *PointerOperand = GEPNew->getPointerOperand(); + if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(PointerOperand)) { + if (cExpr->getOpcode() == Instruction::Cast) + PointerOperand = cExpr->getOperand(0); + } + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) { + if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) { + // We need to insert an actual check. It could be a select + // instruction. + // First get the size. + // This only works for one or two dimensional arrays. + if (GEPNew->getNumOperands() == 2) { + Value *secOp = GEPNew->getOperand(1); + if (secOp->getType() != Type::UIntTy) { + secOp = new CastInst(secOp, Type::UIntTy, + secOp->getName()+".ec.casted", Casted); + } + + const Type* csiType = Type::getPrimitiveType(Type::IntTyID); + std::vector<Value *> args(1,secOp); + args.push_back(ConstantInt::get(csiType,AT->getNumElements())); + new CallInst(ExactCheck,args,"", Casted); + DEBUG(std::cerr << "Inserted exact check call Instruction \n"); + continue; + } else if (GEPNew->getNumOperands() == 3) { + if (ConstantInt *COP = dyn_cast<ConstantInt>(GEPNew->getOperand(1))) { + // FIXME: assuming that the first array index is 0 + assert((COP->getZExtValue() == 0) && "non zero array index\n"); + Value * secOp = GEPNew->getOperand(2); + if (secOp->getType() != Type::UIntTy) { + secOp = new CastInst(secOp, Type::UIntTy, + secOp->getName()+".ec2.casted", Casted); + } + std::vector<Value *> args(1,secOp); + const Type* csiType = Type::getPrimitiveType(Type::IntTyID); + args.push_back(ConstantInt::get(csiType,AT->getNumElements())); + new CallInst(ExactCheck, args, "", Casted->getNext()); + continue; + } else { + // Handle non constant index two dimensional arrays later + abort(); + } + } else { + // Handle Multi dimensional cases later + DEBUG(std::cerr << "WARNING: Handle multi dimensional globals later\n"); + (*iCurrent)->dump(); + } + } + DEBUG(std::cerr << " Global variable ok \n"); + } + + // These must be real unknowns and they will be handled anyway + // std::cerr << " WARNING, DID NOT HANDLE \n"; + // (*iCurrent)->dump(); + continue ; + } else { + if (Casted->getType() != PointerType::get(Type::SByteTy)) { + Casted = new CastInst(Casted,PointerType::get(Type::SByteTy), + (Casted)->getName()+".pc.casted", + (Casted)->getNext()); + } + std::vector<Value *> args(1, PH); + args.push_back(Casted); + // Insert it + new CallInst(PoolCheck,args, "",Casted->getNext()); + DEBUG(std::cerr << "inserted instrcution \n"); + } + } +#else + // + // Get the pool handle associated with the pointer operand. + // + Value *PH = getPoolHandle(GEP->getPointerOperand(), F); + GetElementPtrInst *GEPNew = GEP; + Instruction *Casted = GEP; + + DSGraph & TDG = TDPass->getDSGraph(*F); + DSNode * Node = TDG.getNodeForValue(GEP).getNode(); + + DEBUG(std::cerr << "LLVA: addGEPChecks: Pool " << PH << " Node "); + DEBUG(std::cerr << Node << std::endl); + + Value *PointerOperand = GEPNew->getPointerOperand(); + if (ConstantExpr *cExpr = dyn_cast<ConstantExpr>(PointerOperand)) { + if (cExpr->getOpcode() == Instruction::Cast) + PointerOperand = cExpr->getOperand(0); + } + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(PointerOperand)) { + if (const ArrayType *AT = dyn_cast<ArrayType>(GV->getType()->getElementType())) { + // we need to insert an actual check + // It could be a select instruction + // First get the size + // This only works for one or two dimensional arrays + if (GEPNew->getNumOperands() == 2) { + Value *secOp = GEPNew->getOperand(1); + if (secOp->getType() != Type::UIntTy) { + secOp = new CastInst(secOp, Type::UIntTy, + secOp->getName()+".ec3.casted", Casted); + } + + std::vector<Value *> args(1,secOp); + const Type* csiType = Type::getPrimitiveType(Type::IntTyID); + args.push_back(ConstantInt::get(csiType,AT->getNumElements())); + CallInst *newCI = new CallInst(ExactCheck,args,"", Casted); + ++BoundChecks; + // DEBUG(std::cerr << "Inserted exact check call Instruction \n"); + continue; + } else if (GEPNew->getNumOperands() == 3) { + if (ConstantInt *COP = dyn_cast<ConstantInt>(GEPNew->getOperand(1))) { + //FIXME assuming that the first array index is 0 + assert((COP->getZExtValue() == 0) && "non zero array index\n"); + Value * secOp = GEPNew->getOperand(2); + if (secOp->getType() != Type::UIntTy) { + secOp = new CastInst(secOp, Type::UIntTy, + secOp->getName()+".ec4.casted", Casted); + } + std::vector<Value *> args(1,secOp); + const Type* csiType = Type::getPrimitiveType(Type::IntTyID); + args.push_back(ConstantInt::get(csiType,AT->getNumElements())); + CallInst *newCI = new CallInst(ExactCheck,args,"", Casted->getNext()); + ++BoundChecks; + continue; + } else { + //Handle non constant index two dimensional arrays later + abort(); + } + } else { + //Handle Multi dimensional cases later + std::cerr << "WARNING: Handle multi dimensional globals later\n"; + (*iCurrent)->dump(); + ++MissedMultDimArrayChecks; + } + DEBUG(std::cerr << " Global variable ok \n"); + } + } + +#if 0 + //No checks for incomplete nodes + if (!EnableIncompleteChecks) { + if (Node->isIncomplete()) { + ++MissedNullChecks; + continue; + } + } +#endif + + // + // We cannot insert an exactcheck(). Insert a pool check. + // + // FIXME: + // Currently, we cannot register stack or global memory with pools. If + // the node is from alloc() or is a global, do not insert a poolcheck. + // +#if 0 + if ((!PH) || (Node->isAllocaNode()) || (Node->isGlobalNode())) { +#else + if (!PH) { +#endif + ++NullChecks; + if (!PH) ++MissedNullChecks; +#if 0 + if (Node->isAllocaNode()) ++MissedStackChecks; + if (Node->isGlobalNode()) ++MissedGlobalChecks; +#endif + // Don't bother to insert the NULL check unless the user asked + if (!EnableNullChecks) + continue; + PH = Constant::getNullValue(PointerType::get(Type::SByteTy)); + DEBUG(std::cerr << "missing a GEP check for" << GEP << "alloca case?\n"); + } else { + // + // Determine whether the pool handle dominates the pool check. + // If not, then don't insert it. + // + + // + // FIXME: + // This domination check is too restrictive; it eliminates pools that do + // dominate but are outside of the current basic block. + // + // Only add the pool check if the pool is a global value or it belongs + // to the same basic block. + // + if (isa<GlobalValue>(PH)) { + ++FullChecks; + } else if (isa<Instruction>(PH)) { + Instruction * IPH = (Instruction *)(PH); + if (IPH->getParent() == Casted->getParent()) { + // + // If the instructions belong to the same basic block, ensure that + // the pool dominates the load/store. + // + Instruction * IP = IPH; + for (IP=IPH; (IP->isTerminator()) || (IP==Casted); IP=IP->getNext()) { + ; + } + if (IP == Casted) + ++FullChecks; + else { + ++MissChecks; + continue; + } + } else { + ++MissChecks; + continue; + } + } else { + ++MissChecks; + continue; + } + } + + // + // If this is a complete node, insert a poolcheck. + // If this is an icomplete node, insert a poolcheckarray. + // + Instruction *InsertPt = Casted->getNext(); + if (Casted->getType() != PointerType::get(Type::SByteTy)) { + Casted = new CastInst(Casted,PointerType::get(Type::SByteTy), + (Casted)->getName()+".pc2.casted",InsertPt); + } + Instruction *CastedPointerOperand = new CastInst(PointerOperand, + PointerType::get(Type::SByteTy), + PointerOperand->getName()+".casted",InsertPt); + Instruction *CastedPH = new CastInst(PH, + PointerType::get(Type::SByteTy), + "ph",InsertPt); + if (Node->isIncomplete()) { + std::vector<Value *> args(1, CastedPH); + args.push_back(CastedPointerOperand); + args.push_back(Casted); + CallInst * newCI = new CallInst(PoolCheckArray,args, "",InsertPt); + } else { + std::vector<Value *> args(1, CastedPH); + args.push_back(Casted); + CallInst * newCI = new CallInst(PoolCheck,args, "",InsertPt); + } +#endif + } +} + +void InsertPoolChecks::addPoolCheckProto(Module &M) { + const Type * VoidPtrType = PointerType::get(Type::SByteTy); + /* + const Type *PoolDescType = ArrayType::get(VoidPtrType, 50); + // StructType::get(make_vector<const Type*>(VoidPtrType, VoidPtrType, + // Type::UIntTy, Type::UIntTy, 0)); + const Type * PoolDescTypePtr = PointerType::get(PoolDescType); + */ + + std::vector<const Type *> Arg(1, VoidPtrType); + Arg.push_back(VoidPtrType); + FunctionType *PoolCheckTy = + FunctionType::get(Type::VoidTy,Arg, false); + PoolCheck = M.getOrInsertFunction("poolcheck", PoolCheckTy); + + std::vector<const Type *> Arg2(1, VoidPtrType); + Arg2.push_back(VoidPtrType); + Arg2.push_back(VoidPtrType); + FunctionType *PoolCheckArrayTy = + FunctionType::get(Type::VoidTy,Arg2, false); + PoolCheckArray = M.getOrInsertFunction("poolcheckarray", PoolCheckArrayTy); + + std::vector<const Type *> FArg2(1, Type::UIntTy); + FArg2.push_back(Type::IntTy); + FunctionType *ExactCheckTy = FunctionType::get(Type::VoidTy, FArg2, false); + ExactCheck = M.getOrInsertFunction("exactcheck", ExactCheckTy); + + std::vector<const Type *> FArg3(1, Type::UIntTy); + FArg3.push_back(VoidPtrType); + FArg3.push_back(VoidPtrType); + FunctionType *FunctionCheckTy = FunctionType::get(Type::VoidTy, FArg3, true); + FunctionCheck = M.getOrInsertFunction("funccheck", FunctionCheckTy); + } DSNode* InsertPoolChecks::getDSNode(const Value *V, Function *F) { - DSGraph &TDG = getDSGraph(*F); +#ifndef LLVA_KERNEL + DSGraph &TDG = equivPass->getDSGraph(*F); +#else + DSGraph &TDG = TDPass->getDSGraph(*F); +#endif DSNode *DSN = TDG.getNodeForValue((Value *)V).getNode(); return DSN; } unsigned InsertPoolChecks::getDSNodeOffset(const Value *V, Function *F) { - DSGraph &TDG = getDSGraph(*F); +#ifndef LLVA_KERNEL + DSGraph &TDG = equivPass->getDSGraph(*F); +#else + DSGraph &TDG = TDPass->getDSGraph(*F); +#endif return TDG.getNodeForValue((Value *)V).getOffset(); } - #ifndef LLVA_KERNEL Value *InsertPoolChecks::getPoolHandle(const Value *V, Function *F, PA::FuncInfo &FI, bool collapsed) { const DSNode *Node = getDSNode(V,F); @@ -3659,58 +838,14 @@ if (!collapsed && CollapsedPoolPtrs.count(F)) { Value *v = I->second; - if (CollapsedPoolPtrs[F].find(I->second) != CollapsedPoolPtrs[F].end()) { + if (CollapsedPoolPtrs[F].find(I->second) != + CollapsedPoolPtrs[F].end()) { #ifdef DEBUG - std::cerr << "Collapsed pools \n"; + std::cerr << "Collapsed pools \n"; #endif - return Constant::getNullValue(PoolDescPtrTy); + return Constant::getNullValue(PoolDescPtrTy); } else { - return v; - } - } else { - return I->second; - } - } - return 0; -} - -Value * -InsertPoolChecks::getPoolHandle(const Value *V, Function *F, bool collapsed) { - const DSNode *Node = getDSNode(V,F); - PA::FuncInfo * FI = paPass->getFuncInfoOrClone(*F); - - // Get the pool handle for this DSNode... - // assert(!Node->isUnknownNode() && "Unknown node \n"); - Type *VoidPtrType = PointerType::get(Type::SByteTy); - Type *PoolDescType = ArrayType::get(VoidPtrType, 50); - Type *PoolDescPtrTy = PointerType::get(PoolDescType); - if (!Node) { - return 0; //0 means there is no isse with the value, otherwise there will be a callnode - } - if (Node->isUnknownNode()) { - //FIXME this should be in a top down pass or propagated like collapsed pools below - if (!collapsed) { - assert(!getDSNodeOffset(V, F) && " we don't handle middle of structs yet\n"); - return Constant::getNullValue(PoolDescPtrTy); - } - } - std::map<const DSNode*, Value*>::iterator I = FI->PoolDescriptors.find(Node); - map <Function *, set<Value *> > & - CollapsedPoolPtrs = efPass->CollapsedPoolPtrs; - - if (I != FI->PoolDescriptors.end()) { - // Check that the node pointed to by V in the TD DS graph is not - // collapsed - - if (!collapsed && CollapsedPoolPtrs.count(F)) { - Value *v = I->second; - if (CollapsedPoolPtrs[F].find(I->second) != CollapsedPoolPtrs[F].end()) { -#ifdef DEBUG - std::cerr << "Collapsed pools \n"; -#endif - return Constant::getNullValue(PoolDescPtrTy); - } else { - return v; + return v; } } else { return I->second; @@ -3719,20 +854,16 @@ return 0; } #else -Value * -InsertPoolChecks::getPoolHandle(const Value *V, Function *F) { - DSGraph &TDG = getDSGraph(*F); - DSNode *Node = TDG.getNodeForValue((Value *)V).getNode(); - - // Register that we will need allocations with this DSNode registered. - if (Node) - PHNeeded.insert (Node); - +Value *InsertPoolChecks::getPoolHandle(const Value *V, Function *F) { + DSGraph &TDG = TDPass->getDSGraph(*F); + const DSNode *Node = TDG.getNodeForValue((Value *)V).getNode(); // Get the pool handle for this DSNode... // assert(!Node->isUnknownNode() && "Unknown node \n"); // if (Node->isUnknownNode()) { // return 0; // } - return getPD (Node, *F->getParent()); + if ((TDG.getPoolDescriptorsMap()).count(Node)) + return (TDG.getPoolDescriptorsMap()[Node]->getMetaPoolValue()); + return 0; } #endif
diff --git a/safecode/lib/Makefile b/safecode/lib/Makefile index 99c31f2..159129f 100755 --- a/safecode/lib/Makefile +++ b/safecode/lib/Makefile
@@ -1,6 +1,6 @@ LEVEL = .. -PARALLEL_DIRS = ArrayBoundChecks ConvertUnsafeAllocas InsertPoolChecks StackSafety PointerChecks ProofWrap +PARALLEL_DIRS = ArrayBoundChecks ConvertUnsafeAllocas InsertPoolChecks StackSafety PointerChecks include $(LEVEL)/Makefile.common
diff --git a/safecode/runtime/KPoolCheck/ExactCheck.c b/safecode/runtime/KPoolCheck/ExactCheck.c deleted file mode 100755 index ae775b9..0000000 --- a/safecode/runtime/KPoolCheck/ExactCheck.c +++ /dev/null
@@ -1,104 +0,0 @@ -/*===- ExactCheck.cpp - Implementation of exactcheck functions ------------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* This file implements the exactcheck family of functions. */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#include "PoolCheck.h" -#include "PoolSystem.h" -#include "adl_splay.h" -#ifdef LLVA_KERNEL -#include <stdarg.h> -#endif -#define DEBUG(x) - -/* Flag whether to print error messages on bounds violations */ -int ec_do_fail = 1; - -extern int stat_exactcheck; -extern int stat_exactcheck2; -extern int stat_exactcheck3; - -void * exactcheck(int a, int b, void * result) { - ++stat_exactcheck; - if ((0 > a) || (a >= b)) { - if(ec_do_fail) poolcheckfail ("exact check failed", (a), (void*)__builtin_return_address(0)); - if(ec_do_fail) poolcheckfail ("exact check failed", (b), (void*)__builtin_return_address(0)); - } - return result; -} - -void * exactcheck2(signed char *base, signed char *result, unsigned size) { - ++stat_exactcheck2; - if ((result < base) || (result >= base + size )) { - if(ec_do_fail) poolcheckfail("Array bounds violation detected ", (unsigned)base, (void*)__builtin_return_address(0)); - } - return result; -} - -void * exactcheck2a(signed char *base, signed char *result, unsigned size) { - ++stat_exactcheck2; - if (result >= base + size ) { - if(ec_do_fail) poolcheckfail("Array bounds violation detected ", (unsigned)base, (void*)__builtin_return_address(0)); - } - return result; -} - -void * exactcheck3(signed char *base, signed char *result, signed char * end) { - ++stat_exactcheck3; - if ((result < base) || (result > end )) { - if(ec_do_fail) poolcheckfail("Array bounds violation detected ", (unsigned)base, (void*)__builtin_return_address(0)); - } - return result; -} - -void funccheck (unsigned num, void *f, void *t1, void *t2, void *t3, - void *t4, void *t5, void *t6) { - if ((t1) && (f == t1)) return; - if ((t2) && (f == t2)) return; - if ((t3) && (f == t3)) return; - if ((t4) && (f == t4)) return; - if ((t5) && (f == t5)) return; - if ((t6) && (f == t6)) return; - if (ec_do_fail) poolcheckfail ("funccheck failed", f, (void*)__builtin_return_address(0)); - return; -} - -void funccheck_t (unsigned num, void * f, void ** table) { - unsigned int index; - /* - * Look for the pointer in the big table - */ - for (index = 0; index < num; ++index) { - if (f == table[index]) { - return; - } - } - - if (ec_do_fail) poolcheckfail ("funccheck_t failed", f, (void*)__builtin_return_address(0)); -} - -struct node { - void* left; - void* right; - char* key; - char* end; - void* tag; -}; - -void * getBegin (void * node) { - return ((struct node *)(node))->key; -} - -void * getEnd (void * node) { - return ((struct node *)(node))->end; -} -
diff --git a/safecode/runtime/KPoolCheck/Makefile b/safecode/runtime/KPoolCheck/Makefile deleted file mode 100755 index af7b14a..0000000 --- a/safecode/runtime/KPoolCheck/Makefile +++ /dev/null
@@ -1,8 +0,0 @@ -LEVEL = ../.. -BYTECODE_LIBRARY=1 -LIBRARYNAME=kpoolcheck_rt - -include $(LEVEL)/Makefile.common - -# Always build optimized and debug versions -all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG)
diff --git a/safecode/runtime/KPoolCheck/PoolCheck.c b/safecode/runtime/KPoolCheck/PoolCheck.c deleted file mode 100755 index c5f21b3..0000000 --- a/safecode/runtime/KPoolCheck/PoolCheck.c +++ /dev/null
@@ -1,849 +0,0 @@ -/*===- PoolCheck.cpp - Implementation of poolcheck runtime ----------------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* This file implements the poolcheck interface w/ metapools and opaque */ -/* pool ids. */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#include "PoolCheck.h" -#include "PoolSystem.h" -#include "adl_splay.h" -#ifdef LLVA_KERNEL -#include <stdarg.h> -#endif -#define DEBUG(x) - -/* Flag whether we are pchk_ready to perform pool operations */ -int pchk_ready = 0; - -/* Flag whether to do profiling */ -/* profiling only works if this library is compiled to a .o file, not llvm */ -static const int do_profile = 0; - -/* Flag whether to support out of bounds pointer rewriting */ -static const int use_oob = 0; - -/* Flag whether to print error messages on bounds violations */ -static const int do_fail = 0; - -/* Statistic counters */ -int stat_poolcheck=0; -int stat_poolcheckarray=0; -int stat_poolcheckarray_i=0; -int stat_boundscheck=0; -int stat_boundscheck_i=0; - -/* Global splay for holding the interrupt context */ -void * ICSplay; - -/* Global splay for holding the integer states */ -MetaPoolTy IntegerStatePool; - -extern void llva_load_lif (unsigned int enable); -extern unsigned int llva_save_lif (void); - - -static unsigned -disable_irqs () -{ - unsigned int is_set; - is_set = llva_save_lif (); - llva_load_lif (0); - return is_set; -} - -static void -enable_irqs (int is_set) -{ - llva_load_lif (is_set); -} - -#define PCLOCK() int pc_i = disable_irqs(); -#define PCLOCK2() pc_i = disable_irqs(); -#define PCUNLOCK() enable_irqs(pc_i); - -#define maskaddr(_a) ((void*) ((unsigned)_a & ~(4096 - 1))) - -static int isInCache(MetaPoolTy* MP, void* addr) { - addr = maskaddr(addr); - if (!addr) return 0; - if (MP->cache0 == addr) - return 1; - if (MP->cache1 == addr) - return 2; - if (MP->cache2 == addr) - return 3; - if (MP->cache3 == addr) - return 4; - return 0; -} - -static void mtfCache(MetaPoolTy* MP, int ent) { - void* z = MP->cache0; - switch (ent) { - case 2: - MP->cache0 = MP->cache1; - MP->cache1 = z; - break; - case 3: - MP->cache0 = MP->cache1; - MP->cache1 = MP->cache2; - MP->cache2 = z; - break; - case 4: - MP->cache0 = MP->cache1; - MP->cache1 = MP->cache2; - MP->cache2 = MP->cache3; - MP->cache3 = z; - break; - default: - break; - } - return; -} - -static int insertCache(MetaPoolTy* MP, void* addr) { - addr = maskaddr(addr); - if (!addr) return 0; - if (!MP->cache0) { - MP->cache0 = addr; - return 1; - } - else if (!MP->cache1) { - MP->cache1 = addr; - return 2; - } - else if (!MP->cache2) { - MP->cache2 = addr; - return 3; - } - else { - MP->cache3 = addr; - return 4; - } -} - -/* - * Function: pchk_init() - * - * Description: - * Initialization function to be called when the memory allocator run-time - * intializes itself. - * - * Preconditions: - * 1) The OS kernel is able to handle callbacks from the Execution Engine. - */ -void pchk_init(void) { - - /* initialize runtime */ - adl_splay_libinit(poolcheckmalloc); - - /* - * Register all of the global variables in their respective meta pools. - */ - poolcheckglobals(); - - /* - * Flag that we're pchk_ready to rumble! - */ - pchk_ready = 1; - return; -} - -/* Register a slab */ -void pchk_reg_slab(MetaPoolTy* MP, void* PoolID, void* addr, unsigned len) { -#if 0 - if (!MP) { poolcheckinfo("reg slab on null pool", (int)addr); return; } -#else - if (!MP) { return; } -#endif - PCLOCK(); - adl_splay_insert(&MP->Slabs, addr, len, PoolID); - PCUNLOCK(); -} - -/* Remove a slab */ -void pchk_drop_slab(MetaPoolTy* MP, void* PoolID, void* addr) { - if (!MP) return; - /* TODO: check that slab's tag is == PoolID */ - PCLOCK(); - adl_splay_delete(&MP->Slabs, addr); - PCUNLOCK(); -} - -/* Register a non-pool allocated object */ -void pchk_reg_obj(MetaPoolTy* MP, void* addr, unsigned len) { - unsigned int index; -#if 0 - if (!MP) { poolcheckinfo("reg obj on null pool", addr); return; } -#else - if (!MP) { return; } -#endif -#if 0 - if (pchk_ready) poolcheckinfo2 ("pchk_reg_obj", addr, len); -#endif - PCLOCK(); -#if 0 - { - void * S = addr; - unsigned len, tag = 0; - if ((pchk_ready) && (adl_splay_retrieve(&MP->Objs, &S, &len, &tag))) - poolcheckinfo2 ("regobj: Object exists", __builtin_return_address(0), tag); - } -#endif - - adl_splay_insert(&MP->Objs, addr, len, __builtin_return_address(0)); -#if 1 - /* - * Look for an entry in the cache that matches. If it does, just erase it. - */ - for (index=0; index < 4; ++index) { - if ((MP->start[index] <= addr) && - (MP->start[index]+MP->length[index] >= addr)) { - MP->start[index] = 0; - MP->length[index] = 0; - MP->cache[index] = 0; - } - } -#endif - PCUNLOCK(); -} - -void pchk_reg_stack (MetaPoolTy* MP, void* addr, unsigned len) { - unsigned int index; - if (!MP) { return; } - PCLOCK(); - - adl_splay_insert(&MP->Objs, addr, len, __builtin_return_address(0)); -#if 1 - /* - * Look for an entry in the cache that matches. If it does, just erase it. - */ - for (index=0; index < 4; ++index) { - if ((MP->start[index] <= addr) && - (MP->start[index]+MP->length[index] >= addr)) { - MP->start[index] = 0; - MP->length[index] = 0; - MP->cache[index] = 0; - } - } -#endif - PCUNLOCK(); -} - -void pchk_reg_ic (int sysnum, int a, int b, int c, int d, int e, int f, void* addr) { - PCLOCK(); - adl_splay_insert(&ICSplay, addr, (28*4), 0); - PCUNLOCK(); -} - -void pchk_reg_ic_memtrap (void * p, void* addr) { - PCLOCK(); - adl_splay_insert(&ICSplay, addr, (28*4), 0); - PCUNLOCK(); -} - -void pchk_reg_int (void* addr) { - unsigned int index; - if (!pchk_ready) return; - PCLOCK(); - adl_splay_insert(&(IntegerStatePool.Objs), addr, 72, __builtin_return_address(0)); -#if 1 - /* - * Look for an entry in the cache that matches. If it does, just erase it. - */ - for (index=0; index < 4; ++index) { - if ((IntegerStatePool.start[index] <= addr) && - (IntegerStatePool.start[index]+IntegerStatePool.length[index] >= addr)) { - IntegerStatePool.start[index] = 0; - IntegerStatePool.length[index] = 0; - IntegerStatePool.cache[index] = 0; - } - } -#endif - PCUNLOCK(); -} - -/* Remove a non-pool allocated object */ -void pchk_drop_obj(MetaPoolTy* MP, void* addr) { - unsigned int index; - if (!MP) return; - PCLOCK(); - adl_splay_delete(&MP->Objs, addr); -#if 0 - { - void * S = addr; - unsigned len, tag; - if (adl_splay_retrieve(&MP->Objs, &S, &len, &tag)) - poolcheckinfo ("drop_obj: Failed to remove: 1", addr, tag); - } -#endif - /* - * See if the object is within the cache. If so, remove it from the cache. - */ - for (index=0; index < 4; ++index) { - if ((MP->start[index] <= addr) && - (MP->start[index]+MP->length[index] >= addr)) { - MP->start[index] = 0; - MP->length[index] = 0; - MP->cache[index] = 0; - } - } - PCUNLOCK(); -} - -void pchk_drop_stack (MetaPoolTy* MP, void* addr) { - unsigned int index; - if (!MP) return; - PCLOCK(); - adl_splay_delete(&MP->Objs, addr); - - /* - * See if the object is within the cache. If so, remove it from the cache. - */ - for (index=0; index < 4; ++index) { - if ((MP->start[index] <= addr) && - (MP->start[index]+MP->length[index] >= addr)) { - MP->start[index] = 0; - MP->length[index] = 0; - MP->cache[index] = 0; - } - } - PCUNLOCK(); -} - -void pchk_drop_ic (void* addr) { - PCLOCK(); - adl_splay_delete(&ICSplay, addr); - PCUNLOCK(); -} - -/* - * Function: pchk_drop_ic_interrupt() - * - * Description: - * Identical to pchk_drop_ic but takes an additional argument to make the - * assembly dispatching code easier and faster. - */ -void pchk_drop_ic_interrupt (int intnum, void* addr) { - PCLOCK(); - adl_splay_delete(&ICSplay, addr); - PCUNLOCK(); -} - -/* - * Function: pchk_drop_ic_memtrap() - * - * Description: - * Identical to pchk_drop_ic but takes an additional argument to make the - * assembly dispatching code easier and faster. - */ -void pchk_drop_ic_memtrap (void * p, void* addr) { - PCLOCK(); - adl_splay_delete(&ICSplay, addr); - PCUNLOCK(); -} - -/* - * Function: pchk_reg_func() - * - * Description: - * Register a set of function pointers with a MetaPool. - */ -void -pchk_reg_func (MetaPoolTy * MP, unsigned int num, void ** functable) { - unsigned int index; - unsigned int tag=0; - - for (index=0; index < num; ++index) { - adl_splay_insert(&MP->Functions, functable[index], 1, &tag); - } -} - -/* Register a pool */ -/* The MPLoc is the location the pool wishes to store the metapool tag for */ -/* the pool PoolID is in at. */ -/* MP is the actual metapool. */ -void pchk_reg_pool(MetaPoolTy* MP, void* PoolID, void* MPLoc) { - if(!MP) return; - if(*(void**)MPLoc && *(void**)MPLoc != MP) { - if(do_fail) poolcheckfail("reg_pool: Pool in 2 MP (inference bug a): ", (unsigned)*(void**)MPLoc, (void*)__builtin_return_address(0)); - if(do_fail) poolcheckfail("reg_pool: Pool in 2 MP (inference bug b): ", (unsigned) MP, (void*)__builtin_return_address(0)); - if(do_fail) poolcheckfail("reg_pool: Pool in 2 MP (inference bug c): ", (unsigned) PoolID, (void*)__builtin_return_address(0)); - } - - *(void**)MPLoc = (void*) MP; -} - -/* A pool is deleted. free it's resources (necessary for correctness of checks) */ -void pchk_drop_pool(MetaPoolTy* MP, void* PoolID) { - if(!MP) return; - PCLOCK(); - adl_splay_delete_tag(&MP->Slabs, PoolID); - PCUNLOCK(); -} - -/* - * Function: poolcheckalign() - * - * Description: - * Detremine whether the specified pointer is within the specified MetaPool - * and whether it is at the specified offset from the beginning on an - * object. - */ -void -poolcheckalign (MetaPoolTy* MP, void* addr, unsigned offset) { - if (!pchk_ready || !MP) return; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_poolcheck; - PCLOCK(); - void* S = addr; - unsigned len = 0; - int t = adl_splay_retrieve(&MP->Objs, &S, &len, 0); - PCUNLOCK(); - if ((t) && ((addr - S) == offset)) - return; - if(do_fail) poolcheckfail ("poolcheckalign failure: ", (unsigned)addr, (void*)__builtin_return_address(0)); -} - -/* - * Function: poolcheckalign_i() - * - * Description: - * This is the same as poolcheckalign(), but does not fail if an object cannot - * be found. This is useful for checking incomplete/unknown nodes. - */ -void -poolcheckalign_i (MetaPoolTy* MP, void* addr, unsigned offset) { - if (!pchk_ready || !MP) return; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_poolcheck; - PCLOCK(); - void* S = addr; - unsigned len = 0; - volatile int t = adl_splay_retrieve(&MP->Objs, &S, &len, 0); - PCUNLOCK(); - if (t) { - if ((addr - S) == offset) - return; - else - if (do_fail) poolcheckfail ("poolcheckalign_i failure: ", (unsigned)addr, (void*)__builtin_return_address(0)); - } - return; -} - -/* check that addr exists in pool MP */ -void poolcheck(MetaPoolTy* MP, void* addr) { - if (!pchk_ready || !MP) return; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_poolcheck; - PCLOCK(); - int t = adl_splay_find(&MP->Objs, addr); - PCUNLOCK(); - if (t) - return; - if(do_fail) poolcheckfail ("poolcheck failure: ", (unsigned)addr, (void*)__builtin_return_address(0)); -} - -/* - * Function: poolcheck_i() - * - * Description: - * Same as poolcheck(), but does not fail if the pointer is not found. This is - * useful for checking incomplete/unknown nodes. - */ -void poolcheck_i (MetaPoolTy* MP, void* addr) { - if (!pchk_ready || !MP) return; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_poolcheck; - PCLOCK(); - volatile int t = adl_splay_find(&MP->Objs, addr); - PCUNLOCK(); - return; -} - -/* check that src and dest are same obj or slab */ -void poolcheckarray(MetaPoolTy* MP, void* src, void* dest) { - if (!pchk_ready || !MP) return; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_poolcheckarray; - void* S = src; - void* D = dest; - PCLOCK(); - /* try objs */ - adl_splay_retrieve(&MP->Objs, &S, 0, 0); - adl_splay_retrieve(&MP->Objs, &D, 0, 0); - PCUNLOCK(); - if (S == D) - return; - if(do_fail) poolcheckfail ("poolcheck failure: ", (unsigned)src, (void*)__builtin_return_address(0)); -} - -/* check that src and dest are same obj or slab */ -/* if src and dest do not exist in the pool, pass */ -void poolcheckarray_i(MetaPoolTy* MP, void* src, void* dest) { - if (!pchk_ready || !MP) return; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_poolcheckarray_i; - /* try slabs first */ - void* S = src; - void* D = dest; - PCLOCK(); - - /* try objs */ - int fs = adl_splay_retrieve(&MP->Objs, &S, 0, 0); - int fd = adl_splay_retrieve(&MP->Objs, &D, 0, 0); - PCUNLOCK(); - if (S == D) - return; - if (fs || fd) { /*fail if we found one but not the other*/ - if(do_fail) poolcheckfail ("poolcheck failure: ", (unsigned)src, (void*)__builtin_return_address(0)); - return; - } - return; /*default is to pass*/ -} - -/* - * Function: pchk_iccheck() - * - * Description: - * Determine whether the given pointer points to the beginning of an Interrupt - * Context. - */ -void -pchk_iccheck (void * addr) { - if (!pchk_ready) return; - - /* try objs */ - void* S = addr; - unsigned len = 0; - PCLOCK(); - int fs = adl_splay_retrieve(&ICSplay, &S, &len, 0); - PCUNLOCK(); - if (fs && (S == addr)) { - return; - } - - if (do_fail) poolcheckfail("iccheck failure: ", (unsigned) addr, (void*)__builtin_return_address(0)); - return; -} - -const unsigned InvalidUpper = 4096; -const unsigned InvalidLower = 0x03; - - -/* if src is an out of object pointer, get the original value */ -void* pchk_getActualValue(MetaPoolTy* MP, void* src) { - if (!pchk_ready || !MP || !use_oob) return src; - if ((unsigned)src <= InvalidLower) return src; - void* tag = 0; - /* outside rewrite zone */ - if ((unsigned)src & ~(InvalidUpper - 1)) return src; - PCLOCK(); - if (adl_splay_retrieve(&MP->OOB, &src, 0, &tag)) { - PCUNLOCK(); - return tag; - } - PCUNLOCK(); - if(do_fail) poolcheckfail("GetActualValue failure: ", (unsigned) src, (void*)__builtin_return_address(0)); - return tag; -} - -/* - * Function: getBounds() - * - * Description: - * Get the bounds associated with this object in the specified metapool. - * - * Return value: - * If the node is found in the pool, it returns the bounds relative to - * *src* (NOT the beginning of the object). - * If the node is not found in the pool, it returns 0x00000000. - * If the pool is not yet pchk_ready, it returns 0xffffffff - */ -struct node { - void* left; - void* right; - char* key; - char* end; - void* tag; -}; - -#define USERSPACE 0xC0000000 - -struct node zero_page = {0, 0, 0, (char *)4095, 0}; -struct node not_found = {0, 0, 0, (char *)0x00000000, 0}; -struct node found = {0, 0, 0, (char *)0xffffffff, 0}; -struct node userspace = {0, 0, 0, (char* )USERSPACE, 0}; - -void * getBegin (void * node) { - return ((struct node *)(node))->key; -} - -void * getEnd (void * node) { - return ((struct node *)(node))->end; -} - -void* getBounds(MetaPoolTy* MP, void* src) { - if (!pchk_ready || !MP) return &found; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_boundscheck; - /* first check for user space */ - if (src < USERSPACE) return &userspace; - - /* try objs */ - void* S = src; - unsigned len = 0; - PCLOCK(); - int fs = adl_splay_retrieve(&MP->Objs, &S, &len, 0); - if (fs) { - PCUNLOCK(); - return (MP->Objs); - } - - PCUNLOCK(); - - /* - * If the source pointer is within the first page of memory, return the zero - * page. - */ - if (src < 4096) - return &zero_page; - - /* Return that the object was not found */ - return ¬_found; -} - -/* - * Function: getBounds_i() - * - * Description: - * Get the bounds associated with this object in the specified metapool. - * - * Return value: - * If the node is found in the pool, it returns the bounds. - * If the node is not found in the pool, it returns 0xffffffff. - * If the pool is not yet pchk_ready, it returns 0xffffffff - */ -void* getBounds_i(MetaPoolTy* MP, void* src) { - if (!pchk_ready || !MP) return &found; - ++stat_boundscheck; - /* Try fail cache first */ - PCLOCK(); -#if 0 - int i = isInCache(MP, src); - if (i) { - mtfCache(MP, i); - PCUNLOCK(); - return &found; - } -#endif -#if 1 - { - unsigned int index = MP->cindex; - unsigned int cindex = MP->cindex; - do - { - if ((MP->start[index] <= src) && - (MP->start[index]+MP->length[index] >= src)) - return MP->cache[index]; - index = (index + 1) & 3; - } while (index != cindex); - } -#endif - /* try objs */ - void* S = src; - unsigned len = 0; -#if 0 - PCLOCK2(); -#endif - long long tsc1, tsc2; - if (do_profile) tsc1 = llva_save_tsc(); - int fs = adl_splay_retrieve(&MP->Objs, &S, &len, 0); - if (do_profile) tsc2 = llva_save_tsc(); - if (do_profile) pchk_profile(MP, __builtin_return_address(0), (long)(tsc2 - tsc1)); - if (fs) { -#if 1 - unsigned int index = MP->cindex; - MP->start[index] = S; - MP->length[index] = len; - MP->cache[index] = MP->Objs; - MP->cindex = (index+1) & 3u; -#endif - PCUNLOCK(); - return MP->Objs; - } - - PCUNLOCK(); - - /* - * If the source pointer is within the first page of memory, return the zero - * page. - */ - if (src < 4096) - return &zero_page; - - return &found; -} - -char* invalidptr = 0; - -/* - * Function: boundscheck() - * - * Description: - * Perform a precise array bounds check on source and result. If the result - * is out of range for the array, return 0x1 so that getactualvalue() will - * know that the pointer is bad and should not be dereferenced. - */ -void* pchk_bounds(MetaPoolTy* MP, void* src, void* dest) { - if (!pchk_ready || !MP) return dest; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_boundscheck; - /* try objs */ - void* S = src; - unsigned len = 0; - PCLOCK(); - int fs = adl_splay_retrieve(&MP->Objs, &S, &len, 0); - PCUNLOCK(); - if ((fs) && S <= dest && ((char*)S + len) > (char*)dest ) - return dest; - else if (fs) { - if (!use_oob) { - if(do_fail) poolcheckfail ("boundscheck failure 1", (unsigned)src, (void*)__builtin_return_address(0)); - return dest; - } - PCLOCK2(); - if (invalidptr == 0) invalidptr = (unsigned char*)InvalidLower; - ++invalidptr; - void* P = invalidptr; - PCUNLOCK(); - if ((unsigned)P & ~(InvalidUpper - 1)) { - if(do_fail) poolcheckfail("poolcheck failure: out of rewrite ptrs", 0, (void*)__builtin_return_address(0)); - return dest; - } - if(do_fail) poolcheckinfo2("Returning oob pointer of ", (int)P, __builtin_return_address(0)); - PCLOCK2(); - adl_splay_insert(&MP->OOB, P, 1, dest); - PCUNLOCK() - return P; - } - - /* - * The node is not found or is not within bounds; fail! - */ - if(do_fail) poolcheckfail ("boundscheck failure 2", (unsigned)src, (void*)__builtin_return_address(0)); - return dest; -} - -/* - * Function: uiboundscheck() - * - * Description: - * Perform a precise array bounds check on source and result. If the result - * is out of range for the array, return a sentinel so that getactualvalue() - * will know that the pointer is bad and should not be dereferenced. - * - * This version differs from boundscheck() in that it does not generate a - * poolcheck failure if the source node cannot be found within the MetaPool. - */ -void* pchk_bounds_i(MetaPoolTy* MP, void* src, void* dest) { - if (!pchk_ready || !MP) return dest; -#if 0 - if (do_profile) pchk_profile(MP, __builtin_return_address(0)); -#endif - ++stat_boundscheck_i; - /* try fail cache */ - PCLOCK(); - int i = isInCache(MP, src); - if (i) { - mtfCache(MP, i); - PCUNLOCK(); - return dest; - } - /* try objs */ - void* S = src; - unsigned len = 0; - unsigned int tag; - int fs = adl_splay_retrieve(&MP->Objs, &S, &len, &tag); - if ((fs) && (S <= dest) && (((unsigned char*)S + len) > (unsigned char*)dest)) { - PCUNLOCK(); - return dest; - } - else if (fs) { - if (!use_oob) { - PCUNLOCK(); -#if 0 - if(do_fail) poolcheckfail ("uiboundscheck failure 1", (unsigned)S, len); - if(do_fail) poolcheckfail ("uiboundscheck failure 2", (unsigned)S, tag); -#endif - if (do_fail) poolcheckfail ("uiboundscheck failure 3", (unsigned)dest, (void*)__builtin_return_address(0)); - return dest; - } - if (invalidptr == 0) invalidptr = (unsigned char*)0x03; - ++invalidptr; - void* P = invalidptr; - if ((unsigned)P & ~(InvalidUpper - 1)) { - PCUNLOCK(); - if(do_fail) poolcheckfail("poolcheck failure: out of rewrite ptrs", 0, (void*)__builtin_return_address(0)); - return dest; - } - adl_splay_insert(&MP->OOB, P, 1, dest); - PCUNLOCK(); - return P; - } - - /* - * The node is not found or is not within bounds; pass! - */ - int nn = insertCache(MP, src); - mtfCache(MP, nn); - PCUNLOCK(); - return dest; -} - -void funccheck_g (MetaPoolTy * MP, void * f) { - void* S = f; - unsigned len = 0; - - PCLOCK(); - int fs = adl_splay_retrieve(&MP->Functions, &S, &len, 0); - PCUNLOCK(); - if (fs) - return; - - if (do_fail) poolcheckfail ("funccheck_g failed", f, (void*)__builtin_return_address(0)); -} - -void pchk_ind_fail(void * f) { -#if 0 - if (do_fail) poolcheckfail("indirect call failure", f, (void*)__builtin_return_address(0)); -#else - printk ("<0> LLVA: pchk_ind_fail: pc=%x, f=%x\n", f, (void*)(__builtin_return_address(0))); -#endif -} -
diff --git a/safecode/runtime/KPoolCheck/PoolCheck.h b/safecode/runtime/KPoolCheck/PoolCheck.h deleted file mode 100755 index ad3b1d7..0000000 --- a/safecode/runtime/KPoolCheck/PoolCheck.h +++ /dev/null
@@ -1,107 +0,0 @@ -/*===- PoolCheck.h - Pool check runtime interface file --------------------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#ifndef POOLCHECK_RUNTIME_H -#define POOLCHECK_RUNTIME_H - -typedef struct MetaPoolTy { - /* A splay of Pools, useful for registration tracking */ - void* Slabs; - - /* A splay for registering global objects and heap objects */ - void* Objs; - - /* A splay for registering function pointers */ - void * Functions; - - /* A splay of rewritten Obj Pointers */ - void* OOB; - - /* Next invalid Ptr for rewriting */ - void* profile; - - /*cache space */ - void* cache0; - void* cache1; - void* cache2; - void* cache3; - -#if 1 - unsigned int cindex; - unsigned int start[4]; - unsigned int length[4]; - void * cache[4]; -#endif - -} MetaPoolTy; - -typedef struct funccache { - unsigned int index; - void * cache[4]; -} funccache; - -#ifdef __cpluscplus -extern "C" { -#endif - /* initialize library */ - void pchk_init(void); - - /* Registration functions */ - /* These are written such that a weaker version (without MP) can be */ - /* inserted in the kernel by the programer and we can trivial rewrite them */ - /* to include the metapool */ - void pchk_reg_slab(MetaPoolTy* MP, void* PoolID, void* addr, unsigned len); - void pchk_drop_slab(MetaPoolTy* MP, void* PoolID, void* addr); - void pchk_reg_obj(MetaPoolTy* MP, void* addr, unsigned len); - void pchk_drop_obj(MetaPoolTy* MP, void* addr); - void pchk_reg_pool(MetaPoolTy* MP, void* PoolID, void* MPLoc); - void pchk_drop_pool(MetaPoolTy* MP, void* PoolID); - - /* check that addr exists in pool MP */ - void poolcheck(MetaPoolTy* MP, void* addr); - - /* check that src and dest are same obj or slab */ - void poolcheckarray(MetaPoolTy* MP, void* src, void* dest); - - /* check that src and dest are same obj or slab */ - /* if src and dest do not exist in the pool, pass */ - void poolcheckarray_i(MetaPoolTy* MP, void* src, void* dest); - - /* if src is an out of object pointer, get the original value */ - void* pchk_getActualValue(MetaPoolTy* MP, void* src); - - /* check bounds and return result ptr, which may have been rewritten */ - void* pchk_bounds(MetaPoolTy* MP, void* src, void* dest); - void* pchk_bounds_i(MetaPoolTy* MP, void* src, void* dest); - - void * exactcheck(int a, int b, void * result) __attribute__ ((weak)); - void * exactcheck2(signed char *base, signed char *result, unsigned size) __attribute__ ((weak)); - void * exactcheck2a(signed char *base, signed char *result, unsigned size) __attribute__ ((weak)); - void * exactcheck3(signed char *base, signed char *result, signed char * end)__attribute__ ((weak)); - - void funccheck (unsigned num, void *f, void *t1, void *t2, void *t3, void *t4, void * t5, void * t6) __attribute__ ((weak)); - void funccheck_t (unsigned num, void * f, void ** table) __attribute__ ((weak)); - void funccheck_g (MetaPoolTy * MP, void * f) __attribute__ ((weak)); - void pchk_reg_ic (int s, int a, int b, int c, int d, int e, int f, void* ad); - void pchk_drop_ic (void* addr); - void pchk_iccheck (void * addr); - void * getBegin (void * node) __attribute__ ((weak)); - void * getEnd (void * node) __attribute__ ((weak)); - - void pchk_profile(MetaPoolTy* MP, void* pc, long time); - -#ifdef __cpluscplus -} -#endif - -#endif
diff --git a/safecode/runtime/KPoolCheck/PoolProfile.c b/safecode/runtime/KPoolCheck/PoolProfile.c deleted file mode 100755 index cff43af..0000000 --- a/safecode/runtime/KPoolCheck/PoolProfile.c +++ /dev/null
@@ -1,55 +0,0 @@ -/* Profiling support: - - Each Metapool contains a pointer to a profile tree. this tree - tracks profile call site and frequency A global tree is also - maintained that tracks all metapools. -*/ - -#include "PoolCheck.h" -#include "adl_splay.h" - -extern int printk(const char *fmt, ...); - -static void* allmp = 0; -int profile_pause = 1; - -void pchk_profile(MetaPoolTy* MP, void* pc, long time) { - if (profile_pause) return; - if (!MP) return; - - if (!adl_splay_retrieve (&allmp, MP, 0, 0)) - adl_splay_insert(&allmp, MP, 1, 0); - - void* key = pc; - unsigned tag=0; - unsigned len=0; - - if (adl_splay_retrieve(&MP->profile, &key, &len, &tag)) { - tag += time; - adl_splay_insert(&MP->profile, key, len, tag); - } else { - adl_splay_insert(&MP->profile, key, 1, tag); - } -} - -static void * thepool; - -void print_item(void* p, unsigned l, void* t) { - printk("(0x%x, 0x%x, %d)\n", thepool, p, (unsigned) t); -} - -void print_pool(void* p, unsigned l, void* t) { - thepool = p; - adl_splay_foreach(&(((MetaPoolTy*)p)->profile), print_item); -} - -void pchk_profile_print() { - int old = profile_pause; - profile_pause = 1; - -printk ("LLVA:Printing Profile:\n"); - adl_splay_foreach(&allmp, print_pool); - - profile_pause = old; -} -
diff --git a/safecode/runtime/KPoolCheck/PoolSystem.h b/safecode/runtime/KPoolCheck/PoolSystem.h deleted file mode 100755 index 0c0fcac..0000000 --- a/safecode/runtime/KPoolCheck/PoolSystem.h +++ /dev/null
@@ -1,32 +0,0 @@ -/*===- PoolSystem.h - Pool check runtime interface to the system ----------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#ifndef POOLSYSTEM_RUNTIME_H -#define POOLSYSTEM_RUNTIME_H - -#ifdef __cplusplus -extern "C" { -#endif - /* Functions that need to be provided by the pool allocation run-time */ - void poolcheckfail (const char * msg, int, void*); - void poolcheckfatal (const char * msg, int); - void poolcheckinfo (const char * msg, int); - void poolcheckinfo2 (const char * msg, int, int); - void * poolcheckmalloc (unsigned int size); - void printpoolinfo (void *Pool); - void poolcheckglobals (); -#ifdef __cplusplus -} -#endif - -#endif
diff --git a/safecode/runtime/KPoolCheck/Statistics.c b/safecode/runtime/KPoolCheck/Statistics.c deleted file mode 100755 index 98e74cf..0000000 --- a/safecode/runtime/KPoolCheck/Statistics.c +++ /dev/null
@@ -1,54 +0,0 @@ -/*===- Stats.cpp - Statistics held by the runtime -------------------------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* This file implements functions that can be used to hold statistics */ -/* information */ -/* */ -/*===----------------------------------------------------------------------===*/ - -/* The number of stack to heap promotions executed dynamically */ -static int stack_promotes = 0; - -int stat_exactcheck = 0; -int stat_exactcheck2 = 0; -int stat_exactcheck3 = 0; - -extern int stat_poolcheck; -extern int stat_poolcheckarray; -extern int stat_poolcheckarray_i; -extern int stat_boundscheck; -extern int stat_boundscheck_i; -extern unsigned int externallocs; -extern unsigned int allallocs; - -void -stackpromote() -{ - ++stack_promotes; - return; -} - -int -getstackpromotes() -{ - poolcheckinfo ("LLVA: getstackpromotes", stack_promotes); - poolcheckinfo ("LLVA: stat_exactcheck", stat_exactcheck); - poolcheckinfo ("LLVA: stat_exactcheck2", stat_exactcheck2); - poolcheckinfo ("LLVA: stat_exactcheck3", stat_exactcheck3); - poolcheckinfo ("LLVA: stat_poolcheck", stat_poolcheck); - poolcheckinfo ("LLVA: stat_poolcheckarray", stat_poolcheckarray); - poolcheckinfo ("LLVA: stat_poolcheckarray_i", stat_poolcheckarray_i); - poolcheckinfo ("LLVA: stat_boundscheck", stat_boundscheck); - poolcheckinfo ("LLVA: stat_boundscheck_i", stat_boundscheck_i); - poolcheckinfo ("LLVA: external allocs", externallocs); - poolcheckinfo ("LLVA: all allocs", allallocs); - return stack_promotes; -} -
diff --git a/safecode/runtime/KPoolCheck/adl_rbtree.c b/safecode/runtime/KPoolCheck/adl_rbtree.c deleted file mode 100755 index 6174a84..0000000 --- a/safecode/runtime/KPoolCheck/adl_rbtree.c +++ /dev/null
@@ -1,265 +0,0 @@ -#include "adl_splay.h" - -#ifdef USE_RB - -#include "rb_kernel.h" -#include "PoolSystem.h" - -typedef struct tree_node Tree; -struct tree_node { - rb_node_t node; - char* key; - char* end; - void* tag; -}; - - -/* Memory management functions */ - -static Tree* freelist = 0; -static void* (*ext_alloc)(unsigned) = 0; -unsigned int externallocs = 0; -unsigned int allallocs = 0; - -static Tree initmem[1024]; -static int use = 0; - -static void * -internal_malloc (unsigned int size) -{ - static unsigned char * page = 0; - static unsigned char * loc = 0; - unsigned char * retvalue; - - if (size > 4096) - poolcheckfatal ("LLVA: internal_malloc: Size", size); - - /* - * Allocate a new page if we've never had a page or there isn't any room - * in the current page. - */ - if (!page) - { - loc = page = ext_alloc (0); - ++externallocs; - } - - if ((loc+size) > (page + 4096)) - { - loc = page = ext_alloc (0); - ++externallocs; - } - - /* - * Allocate the space and return a pointer to it. - */ - retvalue = loc; - loc += size; - return retvalue; -} - -static inline Tree* tmalloc() { - ++allallocs; - if(freelist) { - Tree* t = freelist; - freelist = (Tree*)freelist->key; - return t; - } else if(use < 1024) { - ++use; - return &initmem[use-1]; - } else { - Tree * tmp = internal_malloc(sizeof(Tree)); - if (!tmp) - poolcheckfatal ("LLVA: tmalloc: Failed to allocate\n", 0); - return (Tree*) tmp; - } -} - -static inline void tfree(Tree* t) { - t->key = (char*)freelist; - freelist = t; -} - - -#define key_lt(_key, _t) (((char*)_key < (char*)_t->key)) - -#define key_gt(_key, _t) (((char*)_key > (char*)_t->end)) - -static Tree *my_search(rb_root_t *root, char *k) -{ - rb_node_t *node = root->rb_node; - - while (node) { - Tree* data = rb_entry(node, Tree, node); - - if (key_lt(k,data)) - node = node->rb_left; - else if (key_gt(k,data)) - node = node->rb_right; - else - return data; - } - return 0; -} - -static int my_insert(rb_root_t *root, char* key, unsigned len, void* tag) -{ - Tree* data = 0; - rb_node_t **new = &(root->rb_node), *parent = 0; - - /* Figure out where to put new node */ - while (*new) { - Tree* this = rb_entry(*new, Tree, node); - - parent = *new; - if (key_lt(key, this)) - new = &((*new)->rb_left); - else if (key_gt(key, this)) - new = &((*new)->rb_right); - else - return 0; - } - - data = tmalloc(); - data->key = key; - data->end = key + (len - 1); - data->tag = tag; - - /* Add new node and rebalance tree. */ - rb_link_node(&data->node, parent, new); - rb_insert_color(&data->node, root); - - return 1; -} - -static void my_delete(rb_root_t* root, char* k) { - Tree *data = my_search(root, k); - - if (data) { - rb_erase(&data->node, root); - tfree(data); - } -} - -static int count(rb_node_t* t) { - if (t) - return 1 + count(t->rb_left) + count(t->rb_right); - return 0; -} - -/* return any node with the matching tag */ -static Tree* find_tag(rb_node_t* n, void* tag) { - if (n) { - Tree *t = rb_entry(n, Tree, node); - if (t->tag == tag) return t; - if ((t = find_tag(n->rb_left, tag))) return t; - if ((t = find_tag(n->rb_right, tag))) return t; - } - return 0; -} - -/* interface */ - -void adl_splay_insert(void** tree, void* key, unsigned len, void* tag) -{ - my_insert((rb_root_t*)tree, (char*)key, len, tag); -} - -void adl_splay_delete(void** tree, void* key) -{ - my_delete((rb_root_t*)tree, (char*)key); -} - -void adl_splay_delete_tag(void** tree, void* tag) { - rb_root_t* t = (rb_root_t*)tree; - Tree* n = find_tag(t->rb_node, tag); - while (n) { - my_delete(t, n->key); - n = find_tag(t->rb_node, tag); - } -} - -int adl_splay_find(void** tree, void* key) { - Tree* t = my_search((rb_root_t*)tree, (char*)key); - return (t && - !key_lt(key, t) && - !key_gt(key, t)); -} - -int adl_splay_retrieve(void** tree, void** key, unsigned* len, void** tag) { - void* k = *key; - Tree* t = my_search((rb_root_t*)tree, (char*)k); - if (t && - !key_lt(k, t) && - !key_gt(k, t)) { - *key = t->key; - if (len) *len = (t->end - t->key) + 1; - if (tag) *tag = t->tag; - return 1; - } - return 0; -} - -int adl_splay_size(void** tree) { - return (count(((rb_root_t*)tree)->rb_node)); -} - -void* adl_splay_any(void** tree) { - if (((rb_root_t*)tree)->rb_node) { - Tree *t = rb_entry(((rb_root_t*)tree)->rb_node, Tree, node); - return t->key; - } - return 0; -} - -void adl_splay_libinit(void* (nodealloc)(unsigned) ) { - ext_alloc = nodealloc; -} - -void adl_splay_libfini(void (nodefree)(void*) ) { - while (freelist) { - Tree* n = (Tree*)freelist->key; - nodefree(freelist); - freelist = n; - } -} - - -#ifdef TEST_TREE -#include <stdio.h> -#include <stdlib.h> - -int main() { - adl_splay_libinit((void* (*)(int))malloc); - void* t = 0; - long x; - for (x = 0; x < 100; ++x) { - adl_splay_insert(&t, (void*)x, 10, 0); - } - - printf("Size after 100 inserts of size 10 (overlap): %d\n", adl_splay_size(&t)); - - for (x = 0; x < 100; ++x) { - int f = adl_splay_find(&t, (void*)x); - if (!f) printf("Failed find!\n"); - } - for (x = 0; x < 100; x += 20) { - int f = adl_splay_find(&t, (void*)x); - if (!f) printf("Failed find!\n"); - } - - for (x = 0; x < 100; ++x) { - adl_splay_delete(&t, (void*)x); - } - - printf("Size should be 0: %d\n", adl_splay_size(&t)); - return 0; -} - -void poolcheckfatal (const char * msg, int x) { - printf("%s %d\n", msg, x); -} - -#endif - -#endif
diff --git a/safecode/runtime/KPoolCheck/adl_splay.c b/safecode/runtime/KPoolCheck/adl_splay.c deleted file mode 100755 index b536d31..0000000 --- a/safecode/runtime/KPoolCheck/adl_splay.c +++ /dev/null
@@ -1,352 +0,0 @@ -#include "adl_splay.h" - -#ifndef USE_RB - -#include "PoolSystem.h" - -typedef struct tree_node Tree; -struct tree_node { - Tree* left; - Tree* right; - char* key; - char* end; - void* tag; -}; - -/* Memory management functions */ - -static Tree* freelist = 0; -static void* (*ext_alloc)(unsigned) = 0; -unsigned int externallocs = 0; -unsigned int allallocs = 0; - -static Tree initmem[1024]; -static int use = 0; - -static void * -internal_malloc (unsigned int size) -{ - static unsigned char * page = 0; - static unsigned char * loc = 0; - unsigned char * retvalue; - - if (size > 4096) - poolcheckfatal ("LLVA: internal_malloc: Size", size); - - /* - * Allocate a new page if we've never had a page or there isn't any room - * in the current page. - */ - if (!page) - { - loc = page = ext_alloc (0); - ++externallocs; - } - - if ((loc+size) > (page + 4096)) - { - loc = page = ext_alloc (0); - ++externallocs; - } - - /* - * Allocate the space and return a pointer to it. - */ - retvalue = loc; - loc += size; - return retvalue; -} - -static inline Tree* tmalloc() { - ++allallocs; - if(freelist) { - Tree* t = freelist; - freelist = freelist->left; - return t; - } else if(use < 1024) { - ++use; - return &initmem[use-1]; - } else { - Tree * tmp = internal_malloc(sizeof(Tree)); - if (!tmp) - poolcheckfatal ("LLVA: tmalloc: Failed to allocate\n", 0); - return (Tree*) tmp; - } -} - -static inline void tfree(Tree* t) { - t->left = freelist; - freelist = t; -} - - -#define key_lt(_key, _t) (((char*)_key < (char*)_t->key)) - -#define key_gt(_key, _t) (((char*)_key > (char*)_t->end)) - - -static inline Tree* rotate_right(Tree* p) { - Tree* x = p->left; - p->left = x->right; - x->right = p; - return x; -} - -static inline Tree* rotate_left(Tree* p) { - Tree* x = p->right; - p->right = x->left; - x->left = p; - return x; -} - -/* This function by D. Sleator <sleator@cs.cmu.edu> */ -static Tree* splay (Tree * t, char* key) { - Tree N, *l, *r, *y; - if (t == 0) return t; - N.left = N.right = 0; - l = r = &N; - - while(1) { - if (key_lt(key, t)) { - if (t->left == 0) break; - if (key_lt(key, t->left)) { - y = t->left; /* rotate right */ - t->left = y->right; - y->right = t; - t = y; - if (t->left == 0) break; - } - r->left = t; /* link right */ - r = t; - t = t->left; - } else if (key_gt(key, t)) { - if (t->right == 0) break; - if (key_gt(key, t->right)) { - y = t->right; /* rotate left */ - t->right = y->left; - y->left = t; - t = y; - if (t->right == 0) break; - } - l->right = t; /* link left */ - l = t; - t = t->right; - } else { - break; - } - } - l->right = t->left; /* assemble */ - r->left = t->right; - t->left = N.right; - t->right = N.left; - return t; -} - -/* My version, needs testing */ -static Tree* my_splay(Tree* t, char* key) { - if (!t) return t; - - while (1) { - if (key_lt(key, t)) { - if (!t->left) return t; - else if (key_lt(key, t->left)) - t = rotate_right(rotate_right(t)); - else if (key_gt(key, t->left)) { - t->left = rotate_left(t->left); - t = rotate_right(t); - } else - return rotate_right(t); - } else if (key_gt(key, t)) { - if (!t->right) return t; - else if (key_gt(key, t->right)) - t = rotate_left(rotate_left(t)); - else if (key_lt(key, t->right)) { - t->right = rotate_right(t->right); - t = rotate_left(t); - } else - return rotate_left(t); - } else - return t; - } -} - -static inline Tree* insert(Tree* t, char* key, unsigned len, void* tag) { - Tree* n = 0; - t = splay(t, key); - if (t && !key_lt(key, t) && !key_gt(key, t)) { - /* already in, so update the record. This could break - the tree */ - t->key = key; - t->end = t->key + (len - 1); - t->tag = tag; - return t; - } - n = tmalloc(); - n->key = key; - n->end = key + (len - 1); - n->tag = tag; - n->right = n->left = 0; - if (t) { - if (key_lt(key, t)) { - n->left = t->left; - n->right = t; - t->left = 0; - } else { - n->right = t->right; - n->left = t; - t->right = 0; - } - } - return n; -} - -static inline Tree* delete(Tree* t, char* key) { - if (!t) return t; - t = splay(t, key); - if (!key_lt(key, t) && !key_gt(key, t)) { - Tree* x = 0; - if (!t->left) - x = t->right; - else { - x = splay(t->left, key); - x->right = t->right; - } - tfree(t); - return x; - } - return t; /* not there */ -} - -static int count(Tree* t) { - if (t) - return 1 + count(t->left) + count(t->right); - return 0; -} - -/* return any node with the matching tag */ -static Tree* find_tag(Tree* t, void* tag) { - if (t) { - Tree* n = 0; - if (t->tag == tag) return t; - if ((n = find_tag(t->left, tag))) return n; - if ((n = find_tag(t->right, tag))) return n; - } - return 0; -} - -/* interface */ - -void adl_splay_insert(void** tree, void* key, unsigned len, void* tag) -{ - *(Tree**)tree = insert(*(Tree**)tree, (char*)key, len, tag); -} - -void adl_splay_delete(void** tree, void* key) -{ - *(Tree**)tree = delete(*(Tree**)tree, (char*)key); -} - -void adl_splay_delete_tag(void** tree, void* tag) { - Tree* t = *(Tree**)tree; - Tree* n = find_tag(t, tag); - while (n) { - t = delete(t, n->key); - n = find_tag(t, tag); - } - *(Tree**)tree = t; -} - -int adl_splay_find(void** tree, void* key) { - Tree* t = splay(*(Tree**)tree, (char*)key); - *(Tree**)tree = t; - return (t && - !key_lt(key, t) && - !key_gt(key, t)); -} - -int adl_splay_retrieve(void** tree, void** key, unsigned* len, void** tag) { - void* k = *key; - Tree* t = splay(*(Tree**)tree, (char*)k); - *(Tree**)tree = t; - if (t && - !key_lt(k, t) && - !key_gt(k, t)) { - *key = t->key; - if (len) *len = (t->end - t->key) + 1; - if (tag) *tag = t->tag; - return 1; - } - return 0; -} - -int adl_splay_size(void** tree) { - return (count(*(Tree**)tree)); -} - -void* adl_splay_any(void** tree) { - if (*(Tree**)tree) - return ((*(Tree**)tree)->key); - return 0; -} - -void adl_splay_libinit(void* (nodealloc)(unsigned) ) { - ext_alloc = nodealloc; -} - -void adl_splay_libfini(void (nodefree)(void*) ) { - while (freelist) { - Tree* n = freelist->left; - nodefree(freelist); - freelist = n; - } -} - -void adl_splay_foreach(void** tree, void (f)(void*, unsigned, void*)) { - Tree* T = *(Tree**)tree; - if (T) { - f(T->key, (T->end - T->key) + 1, T->tag); - adl_splay_foreach(&T->left, f); - adl_splay_foreach(&T->right, f); - } -} - - -#ifdef TEST_TREE -#include <stdio.h> -#include <stdlib.h> - -int main() { - adl_splay_libinit((void* (*)(int))malloc); - void* t = 0; - long x; - for (x = 0; x < 100; ++x) { - adl_splay_insert(&t, (void*)x, 10, 0); - } - - printf("Size after 100 inserts of size 10 (overlap): %d\n", adl_splay_size(&t)); - - for (x = 0; x < 100; ++x) { - int f = adl_splay_find(&t, (void*)x); - if (!f) printf("Failed find!\n"); - } - for (x = 0; x < 100; x += 20) { - int f = adl_splay_find(&t, (void*)x); - if (!f) printf("Failed find!\n"); - } - - for (x = 0; x < 100; ++x) { - adl_splay_delete(&t, (void*)x); - } - - printf("Size should be 0: %d\n", adl_splay_size(&t)); - return 0; -} - -void poolcheckfatal (const char * msg, int x) { - printf("%s %d\n", msg, x); -} - - -#endif - -#endif
diff --git a/safecode/runtime/KPoolCheck/adl_splay.h b/safecode/runtime/KPoolCheck/adl_splay.h deleted file mode 100755 index 89e0417..0000000 --- a/safecode/runtime/KPoolCheck/adl_splay.h +++ /dev/null
@@ -1,22 +0,0 @@ -#ifdef __cpluscplus -extern "C" { -#endif - extern void adl_splay_insert(void** tree, void* key, unsigned len, void* tag); - extern void adl_splay_delete(void** tree, void* key); - extern void adl_splay_delete_tag(void** tree, void* tag); /*expensive */ - - extern int adl_splay_find(void** tree, void* key); - extern int adl_splay_retrieve(void** tree, void** key, unsigned* len, void** tag); - extern int adl_splay_size(void** tree); - extern void* adl_splay_any(void** tree); - - extern void adl_splay_libinit(void* (nodealloc)(unsigned) ); - extern void adl_splay_libfini(void (nodefree)(void*) ); - - extern void adl_splay_foreach(void** tree, void (f)(void*, unsigned, void*)); - -#ifdef __cpluscplus -} -#endif - -/* #define USE_RB */
diff --git a/safecode/runtime/KPoolCheck/rb_kernel.h b/safecode/runtime/KPoolCheck/rb_kernel.h deleted file mode 100755 index 10ca87e..0000000 --- a/safecode/runtime/KPoolCheck/rb_kernel.h +++ /dev/null
@@ -1,300 +0,0 @@ -typedef struct rb_node_s -{ - struct rb_node_s * rb_parent; - int rb_color; -#define RB_RED 0 -#define RB_BLACK 1 - struct rb_node_s * rb_right; - struct rb_node_s * rb_left; -} - rb_node_t; - -typedef struct rb_root_s -{ - struct rb_node_s * rb_node; -} - rb_root_t; - -#define RB_ROOT (rb_root_t) { NULL, } -#define rb_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link) -{ - node->rb_parent = parent; - node->rb_color = RB_RED; - node->rb_left = node->rb_right = 0; - - *rb_link = node; -} - -static void __rb_rotate_left(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * right = node->rb_right; - - if ((node->rb_right = right->rb_left)) - right->rb_left->rb_parent = node; - right->rb_left = node; - - if ((right->rb_parent = node->rb_parent)) - { - if (node == node->rb_parent->rb_left) - node->rb_parent->rb_left = right; - else - node->rb_parent->rb_right = right; - } - else - root->rb_node = right; - node->rb_parent = right; -} - -static void __rb_rotate_right(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * left = node->rb_left; - - if ((node->rb_left = left->rb_right)) - left->rb_right->rb_parent = node; - left->rb_right = node; - - if ((left->rb_parent = node->rb_parent)) - { - if (node == node->rb_parent->rb_right) - node->rb_parent->rb_right = left; - else - node->rb_parent->rb_left = left; - } - else - root->rb_node = left; - node->rb_parent = left; -} - -static void rb_insert_color(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * parent, * gparent; - - while ((parent = node->rb_parent) && parent->rb_color == RB_RED) - { - gparent = parent->rb_parent; - - if (parent == gparent->rb_left) - { - { - register rb_node_t * uncle = gparent->rb_right; - if (uncle && uncle->rb_color == RB_RED) - { - uncle->rb_color = RB_BLACK; - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - node = gparent; - continue; - } - } - - if (parent->rb_right == node) - { - register rb_node_t * tmp; - __rb_rotate_left(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - __rb_rotate_right(gparent, root); - } else { - { - register rb_node_t * uncle = gparent->rb_left; - if (uncle && uncle->rb_color == RB_RED) - { - uncle->rb_color = RB_BLACK; - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - node = gparent; - continue; - } - } - - if (parent->rb_left == node) - { - register rb_node_t * tmp; - __rb_rotate_right(parent, root); - tmp = parent; - parent = node; - node = tmp; - } - - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; - __rb_rotate_left(gparent, root); - } - } - - root->rb_node->rb_color = RB_BLACK; -} - -static void __rb_erase_color(rb_node_t * node, rb_node_t * parent, - rb_root_t * root) -{ - rb_node_t * other; - - while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node) - { - if (parent->rb_left == node) - { - other = parent->rb_right; - if (other->rb_color == RB_RED) - { - other->rb_color = RB_BLACK; - parent->rb_color = RB_RED; - __rb_rotate_left(parent, root); - other = parent->rb_right; - } - if ((!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - && (!other->rb_right || - other->rb_right->rb_color == RB_BLACK)) - { - other->rb_color = RB_RED; - node = parent; - parent = node->rb_parent; - } - else - { - if (!other->rb_right || - other->rb_right->rb_color == RB_BLACK) - { - register rb_node_t * o_left; - if ((o_left = other->rb_left)) - o_left->rb_color = RB_BLACK; - other->rb_color = RB_RED; - __rb_rotate_right(other, root); - other = parent->rb_right; - } - other->rb_color = parent->rb_color; - parent->rb_color = RB_BLACK; - if (other->rb_right) - other->rb_right->rb_color = RB_BLACK; - __rb_rotate_left(parent, root); - node = root->rb_node; - break; - } - } - else - { - other = parent->rb_left; - if (other->rb_color == RB_RED) - { - other->rb_color = RB_BLACK; - parent->rb_color = RB_RED; - __rb_rotate_right(parent, root); - other = parent->rb_left; - } - if ((!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - && (!other->rb_right || - other->rb_right->rb_color == RB_BLACK)) - { - other->rb_color = RB_RED; - node = parent; - parent = node->rb_parent; - } - else - { - if (!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - { - register rb_node_t * o_right; - if ((o_right = other->rb_right)) - o_right->rb_color = RB_BLACK; - other->rb_color = RB_RED; - __rb_rotate_left(other, root); - other = parent->rb_left; - } - other->rb_color = parent->rb_color; - parent->rb_color = RB_BLACK; - if (other->rb_left) - other->rb_left->rb_color = RB_BLACK; - __rb_rotate_right(parent, root); - node = root->rb_node; - break; - } - } - } - if (node) - node->rb_color = RB_BLACK; -} - -static void rb_erase(rb_node_t * node, rb_root_t * root) -{ - rb_node_t * child, * parent; - int color; - - if (!node->rb_left) - child = node->rb_right; - else if (!node->rb_right) - child = node->rb_left; - else - { - rb_node_t * old = node, * left; - - node = node->rb_right; - while ((left = node->rb_left)) - node = left; - child = node->rb_right; - parent = node->rb_parent; - color = node->rb_color; - - if (child) - child->rb_parent = parent; - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - - if (node->rb_parent == old) - parent = node; - node->rb_parent = old->rb_parent; - node->rb_color = old->rb_color; - node->rb_right = old->rb_right; - node->rb_left = old->rb_left; - - if (old->rb_parent) - { - if (old->rb_parent->rb_left == old) - old->rb_parent->rb_left = node; - else - old->rb_parent->rb_right = node; - } else - root->rb_node = node; - - old->rb_left->rb_parent = node; - if (old->rb_right) - old->rb_right->rb_parent = node; - goto color; - } - - parent = node->rb_parent; - color = node->rb_color; - - if (child) - child->rb_parent = parent; - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - - color: - if (color == RB_BLACK) - __rb_erase_color(child, parent, root); -}
diff --git a/safecode/runtime/KernelSafePoolAllocator/PageManager.cpp b/safecode/runtime/KernelSafePoolAllocator/PageManager.cpp index 906aa6a..32e5643 100755 --- a/safecode/runtime/KernelSafePoolAllocator/PageManager.cpp +++ b/safecode/runtime/KernelSafePoolAllocator/PageManager.cpp
@@ -63,15 +63,9 @@ // MAP_SHARED|MAP_ANONYMOUS, fdq, 0); // void *pa = malloc(NumPages * PageSize); // assert(Addr != MAP_FAILED && "MMAP FAILED!"); -#if POSIX_MEMALIGN if (posix_memalign(&Addr, PageSize, NumPages*PageSize) != 0){ - assert(0 && "memalign failed \n"); + assert(1 && "memalign failed \n"); } -#else - if ((Addr = valloc (NumPages*PageSize)) == 0){ - assert(0 && "valloc failed \n"); - } -#endif DEBUG(printf("memalign returns %x for %d\n", Addr, NumPages);) // fprintf(fd1, "memory usage statistic :%d %d\n", getpid(), poolmemusage); // fflush(fd1);
diff --git a/safecode/runtime/KernelSafePoolAllocator/PoolCheck.cpp b/safecode/runtime/KernelSafePoolAllocator/PoolCheck.cpp index 1a37dfe..60fe708 100755 --- a/safecode/runtime/KernelSafePoolAllocator/PoolCheck.cpp +++ b/safecode/runtime/KernelSafePoolAllocator/PoolCheck.cpp
@@ -79,22 +79,24 @@ return false; } -inline int refcheck(Splay *splay, void *Node) { + +inline bool refcheck(Splay *splay, void *Node) { unsigned long base = (unsigned long) (splay->key); unsigned long length = (unsigned long) (splay->val); unsigned long result = (unsigned long) Node; - if ((result >= base) && (result < (base + length))) return 1; - return -1; + if ((result >= base) && (result < (base + length))) return true; + return false; } -int poolcheckarrayoptim(void *Pool, void *NodeSrc, void *NodeResult) { + +bool poolcheckarrayoptim(void *Pool, void *NodeSrc, void *NodeResult) { Splay *psplay = poolchecksplay(Pool); splay *ref = splay_find_ptr(psplay, (unsigned long)NodeSrc); if (ref) { return refcheck(ref, NodeResult); } - return 0; + return false; } void poolcheckarray(MetaPoolTy **MP, void *NodeSrc, void *NodeResult) { @@ -112,41 +114,6 @@ poolcheckfail ("poolcheck failure \n"); } -inline signed char * getactualvalue(signed char *Pool, signed char *val) { - if ((unsigned long) val != 0x00000001) { - return val; - } else { - poolcheckfail("Bounds check failure : value in the first page \n"); - } -} - -inline void exactcheck2(signed char *base, signed char *result, unsigned size) { - if (result >= base + size ) { - poolcheckfail("Array bounds violation detected \n"); - } -} - - - -void* boundscheck(MetaPoolTy **MP, void *NodeSrc, void *NodeResult) { - MetaPoolTy *MetaPool = *MP; - if (!MetaPool) { - poolcheckfail ("Empty meta pool? \n"); - } - //iteratively search through the list - //Check if there are other efficient data structures. - while (MetaPool) { - void *Pool = MetaPool->Pool; - int ret = poolcheckarrayoptim(Pool, NodeSrc, NodeResult); - if (ret) { - if (ret == -1) return ((void *)(0x00000001)); - return NodeResult; - } - MetaPool = MetaPool->next; - } - poolcheckfail ("poolcheck failure \n"); -} - void poolcheck(MetaPoolTy **MP, void *Node) { MetaPoolTy *MetaPool = *MP; if (!MetaPool) {
diff --git a/safecode/runtime/Makefile b/safecode/runtime/Makefile index f289822..73aa89b 100755 --- a/safecode/runtime/Makefile +++ b/safecode/runtime/Makefile
@@ -6,7 +6,7 @@ # # List all of the subdirectories that we will compile. # -PARALLEL_DIRS=SafePoolAllocator BoundsCheckAllocator KernelSafePoolAllocator PoolCheck KPoolCheck +PARALLEL_DIRS=SafePoolAllocator BoundsCheckAllocator KernelSafePoolAllocator include $(LEVEL)/Makefile.common
diff --git a/safecode/runtime/PoolCheck/Makefile b/safecode/runtime/PoolCheck/Makefile deleted file mode 100755 index 965458c..0000000 --- a/safecode/runtime/PoolCheck/Makefile +++ /dev/null
@@ -1,8 +0,0 @@ -LEVEL = ../.. -BYTECODE_LIBRARY=1 -LIBRARYNAME=poolcheck_rt - -include $(LEVEL)/Makefile.common - -# Always build optimized and debug versions -all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG)
diff --git a/safecode/runtime/PoolCheck/PoolCheck.c b/safecode/runtime/PoolCheck/PoolCheck.c deleted file mode 100755 index 0ceae6d..0000000 --- a/safecode/runtime/PoolCheck/PoolCheck.c +++ /dev/null
@@ -1,546 +0,0 @@ -/*===- PoolCheck.cpp - Implementation of poolcheck runtime ----------------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* This file is one possible implementation of the LLVM pool allocator */ -/* runtime library. */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#include "PoolCheck.h" -#ifdef LLVA_KERNEL -#include <stdarg.h> -#endif -#define DEBUG(x) - -/* This defines the value of an invalid pointer address */ -static const unsigned char * invalidptr = 0x00000004; -volatile unsigned char dosplays = 1; - -#if 1 -/* - * These are symbols exported by the kernel so that we can figure out where - * various sections are. - */ -extern char _etext; -extern char _edata; -extern char __bss_start; -extern char _end; -#endif - -/*===----------------------------------------------------------------------===*/ -extern unsigned PageSize; - -/* Flag whether we are ready to perform pool operations */ -static int ready = 0; - -/* - * Function: poolcheckinit() - * - * Description: - * Initialization function to be called when the memory allocator run-time - * intializes itself. - * - * Preconditions: - * 1) The OS kernel is able to handle callbacks from the Execution Engine. - */ -void -poolcheckinit(void *Pool, unsigned NodeSize) { - /* - * Register all of the global variables in their respective meta pools. - */ - poolcheckglobals(); - - /* - * Flag that we're ready to rumble! - */ - ready = 1; - return; -} - -/* - * Function: poolcheckdestroy() - * - * Description: - * To be called from pooldestroy. - */ -void -poolcheckdestroy(void *Pool) { - /* Do nothing as of now since all MetaPools are global */ -#if 0 - free_splay(Pool->splay); -#endif - ready = 0; - return; -} - - -void AddPoolDescToMetaPool(MetaPoolTy **MP, void *P) { - MetaPoolTy *MetaPoolPrev = *MP; - MetaPoolTy *MetaPool = *MP; - if (!ready) return; - if (MetaPool) { - MetaPool = MetaPool->next; - } else { - if (*MP = (MetaPoolTy *) poolcheckmalloc (sizeof(MetaPoolTy))) - { - (*MP)->Pool = P; - (*MP)->Splay = 0; - (*MP)->next = 0; - } - return; - } - - /* - * Scan for the end of the list. If we run across the pool already in the - * meta-pool list, then don't bother adding it again. - */ - while (MetaPool) { - if (MetaPool->Pool == P) { - return; - } - MetaPoolPrev = MetaPool; - MetaPool = MetaPool->next; - } - /* MetaPool is null; */ - if (MetaPoolPrev->next = (MetaPoolTy *) poolcheckmalloc (sizeof(MetaPoolTy))) - { - MetaPoolPrev->next->Pool = P; - MetaPoolPrev->next->Splay = 0; - MetaPoolPrev->next->next = 0; - } -} - - -/* - * Function: poolcheckoptim() - * - * Description: - * Determine whether the pointer is within the pool. - * - * Return value: - * 1 - The pointer is within the pool. - * 0 - The pointer is not within the pool. - */ -unsigned char poolcheckoptim(void *Pool, void *Node) { - Splay *psplay; - Splay *ref; -#if 0 - /* - * Determine if this is a global variable in the data section. - */ - if (((Node) >= &_etext) && ((Node) <= &_edata)) - { - return; - } - - /* - * Determine if this is a global variable in the BSS section. - */ - if ((((Node)) >= &__bss_start) && (((Node)) <= &_end)) - { - return; - } -#endif - - /* - * Determine the size of the slabs used in this pool. - * Then, assuming this is the pool in which this node lives, determine - * the slab to which the node would belong. - */ - unsigned int SlabSize = poolcheckslabsize (Pool); - void *PS = (void *)((unsigned)Node & ~(SlabSize-1)); - - /* - * Scan through the list of slabs belonging to the pool and determine - * whether this node is in one of those slabs. - */ - PoolCheckSlab * PCS = poolcheckslab(Pool); - while (PCS) { - if (PCS->Slab == PS) return 1; - /* we can optimize by moving it to the front of the list */ - PCS = PCS->nextSlab; - } - - /* - * Here we check for the splay tree - */ - psplay = poolchecksplay(Pool); - ref = splay_find_ptr(psplay, (unsigned long) Node); - if (ref) { - return 1; - } - return 0; -} - -/* - * Function: poolcheckarrayoptim() - * - * Description: - * This function determines: - * 1) Whether the source node of a GEP is in the correct pool, and - * 2) Whether the result of the GEP expression is in the same pool as the - * source. - * - * Return value: - * 1 - The source and destination were found in the pool. - * 0 - The source was not found in the pool - * -1 - The source was found in the pool, but the result is outside of the pool. - */ -char -poolcheckarrayoptim(MetaPoolTy *Pool, void *NodeSrc, void *NodeResult) { - Splay *psplay = poolchecksplay(Pool); - Splay *ref = splay_find_ptr(psplay, (unsigned long)NodeSrc); - if (ref) { - return refcheck(ref, NodeResult); - } - return 0; -} - -/* - * Function: poolcheckarray() - * - * Description: - * This function performs the same check as poolcheckarrayoptim(), but - * checks all the pools associated with a meta-pool. - */ -void poolcheckarray(MetaPoolTy **MP, void *NodeSrc, void *NodeResult) { - if (!ready) return; - MetaPoolTy *MetaPool = *MP; - if (!MetaPool) { - poolcheckfail ("Empty meta pool? Src \n", NodeSrc); - } - /* - * iteratively search through the list - * Check if there are other efficient data structures. - */ - while (MetaPool) { - void *Pool = MetaPool->Pool; - if ((Pool) && (poolcheckarrayoptim(Pool, NodeSrc, NodeResult))) return ; - MetaPool = MetaPool->next; - } - poolcheckfail ("poolcheckarray failure: Result \n", NodeResult); -} - -/* - * Function: poolcheckiarray () - * - * Description: - * This function performs the same check as poolcheckarray() but - * allows the check to succeed if the source node is not found. - */ -void poolcheckiarray(MetaPoolTy **MP, void *NodeSrc, void *NodeResult) { - if (!ready) return; - MetaPoolTy *MetaPool = *MP; - if (!MetaPool) { - poolcheckfail ("Empty meta pool? Src \n", NodeSrc); - } - - /* - * iteratively search through the list - * Check if there are other efficient data structures. - */ - while (MetaPool) { - void *Pool = MetaPool->Pool; - if (Pool) - if (poolcheckoptim (Pool, NodeSrc)) - if (poolcheckoptim (Pool, NodeResult)) - return; - else - poolcheckfail ("poolcheckiarray failure: Result \n", NodeResult); - MetaPool = MetaPool->next; - } - - return; -} - -inline int refcheck(Splay *splay, void *Node) { - unsigned long base = (unsigned long) (splay->key); - unsigned long length = (unsigned long) (splay->val); - unsigned long result = (unsigned long) Node; - if ((result >= base) && (result < (base + length))) return 1; - return -1; - -} - -inline signed char * getactualvalue(signed char *Pool, signed char *val) { - if (!ready) return val; - if ((unsigned long) val != invalidptr) { - return val; - } else { - poolcheckfail("Bounds check failure : value in the first page \n", val); - } -} - -inline void exactcheck2(signed char *base, signed char *result, unsigned size) { - if (result >= base + size ) { - poolcheckfail("Array bounds violation detected \n", base); - } -} - -/* - * Function: boundscheck() - * - * Description: - * Perform a precise array bounds check on source and result. If the result - * is out of range for the array, return 0x1 so that getactualvalue() will - * know that the pointer is bad and should not be dereferenced. - */ -void * -boundscheck(MetaPoolTy **MP, void *NodeSrc, void *NodeResult) { - MetaPoolTy *MetaPool = *MP; - Splay *ref; - void *Pool; - int ret; - - if (!ready) return NodeResult; -#if 0 - if (!MetaPool) { - poolcheckfail ("Empty meta pool? \n", __builtin_return_address(0)); - } -#endif - - /* - * Iteratively search through the list; - * Check if there are other efficient data structures. - */ - while (MetaPool) { - Pool = MetaPool->Pool; - if (Pool) { - ret = poolcheckarrayoptim(Pool, NodeSrc, NodeResult); - if (ret) { - if (ret == -1) return invalidptr; - return NodeResult; - } - } - - if ((MetaPool->Splay)) { - ref = splay_find_ptr (MetaPool->Splay, (unsigned long) NodeSrc); - if (ref) - if ((refcheck (ref, NodeResult)) == 1) - return NodeResult; - else { - poolcheckfail ("boundscheck: global", NodeResult); - return NodeResult; - } - } - - MetaPool = MetaPool->next; - } - - /* - * The node is not found or is not within bounds; fail! - */ - poolcheckfail ("boundscheck failure 1\n", NodeSrc); - return NodeResult; -} - -/* - * Function: uiboundscheck() - * - * Description: - * Perform a precise array bounds check on source and result. If the result - * is out of range for the array, return a sentinel so that getactualvalue() - * will know that the pointer is bad and should not be dereferenced. - * - * This version differs from boundscheck() in that it does not generate a - * poolcheck failure if the source node cannot be found within the MetaPool. - */ -void * -uiboundscheck (MetaPoolTy **MP, void *NodeSrc, void *NodeResult) { - MetaPoolTy *MetaPool = *MP; - Splay *ref; - void *Pool; - int ret; - - return NodeResult; - /* Don't do a check if the kernel is not ready */ - if (!ready) return NodeResult; - - /* It is an error if there is no MetaPool */ - if (!MetaPool) { - poolcheckfail ("Empty meta pool? \n", 0); - } - - /* - * iteratively search through the list - * Check if there are other efficient data structures. - */ - while (MetaPool) { - Pool = MetaPool->Pool; - if (Pool) { - ret = poolcheckarrayoptim(Pool, NodeSrc, NodeResult); - switch (ret) { - case -1: - return invalidptr; - break; - case 1: - return NodeResult; - break; - case 0: - break; - } - } - - /* - * Search the Meta Pool's splay; the pointer might be a global or stack - * value. - */ - if ((dosplays) && (MetaPool->Splay)) { - ref = splay_find_ptr (MetaPool->Splay, (unsigned long) NodeSrc); - if (ref) - if ((refcheck (ref, NodeResult)) == 1) - return NodeResult; - else - return invalidptr; - } - - MetaPool = MetaPool->next; - } - - /* - * We did not find the source node at all. For incomplete and unknown - * pointers, this means we just silently pass. - */ - return NodeResult; -} - - - -/* - * Function: poolcheck() - * - * Description: - * Verify whether a node is located within one of the pools associated with - * the MetaPool. - */ -void poolcheck(MetaPoolTy **MP, void *Node) { - if (!ready) return; - MetaPoolTy *MetaPool = *MP; - if (!MetaPool) { - poolcheckfail ("Empty meta pool? \n", Node); - } - /* - * iteratively search through the list - * Check if there are other efficient data structures. - */ - while (MetaPool) { - void *Pool = MetaPool->Pool; - if ((Pool) && (poolcheckoptim(Pool, Node))) return; - MetaPool = MetaPool->next; - } - poolcheckfail ("poolcheck failure \n", Node); -} - - -void poolcheckAddSlab(PoolCheckSlab **PCSPtr, void *Slab) { - PoolCheckSlab *PCSPrev = *PCSPtr; - PoolCheckSlab *PCS = *PCSPtr; - if (!ready) return; - if (PCS) { - PCS = PCS->nextSlab; - } else { - if (*PCSPtr = (PoolCheckSlab *) poolcheckmalloc (sizeof(PoolCheckSlab))) - { - (*PCSPtr)->Slab = Slab; - (*PCSPtr)->nextSlab = 0; - } - return; - } - while (PCS) { - PCSPrev = PCS; - PCS = PCS->nextSlab; - } - /* PCS is null; */ - if (PCSPrev->nextSlab = (PoolCheckSlab *) poolcheckmalloc (sizeof(PoolCheckSlab))) - { - PCSPrev->nextSlab->Slab = Slab; - PCSPrev->nextSlab->nextSlab = 0; - } -} - - - void exactcheck(int a, int b) { - if ((0 > a) || (a >= b)) { - poolcheckfail ("exact check failed\n", (a)); - poolcheckfail ("exact check failed\n", (b)); - } - } - - /* - * Disable this for kernel code. I'm not sure how kernel code handles - * va_list type functions. - */ -#ifdef LLVA_KERNEL - void funccheck(unsigned num, void *f, void *g, ...) { - va_list ap; - unsigned i = 0; - if (f == g) return; - i++; - va_start(ap, g); - for ( ; i != num; ++i) { - void *h = va_arg(ap, void *); - if (f == h) { - return; - } - } - abort(); - } -#endif - -/* - * Function: poolregister() - * - * Description: - * Associate a memory range with a given MetaPool. - * - * Preconditions: - * For now, we assume that this function is only called by poolcheckglobals() - * which is called by poolcheckinit(). - */ -void -poolregister (MetaPoolTy ** MP, unsigned NumBytes, void * ptr) -{ - MetaPoolTy *MetaPool = *MP; - - /* - * Allocate a MetaPool node if one does not already exist. - */ - if (!MetaPool) { - if (MetaPool = *MP = (MetaPoolTy *) poolcheckmalloc (sizeof(MetaPoolTy))) { - (*MP)->Pool = 0; - (*MP)->Splay = 0; - (*MP)->next = 0; - } else { - poolcheckfatal ("poolregister: Cannot allocate memory", 0); - } - } - - /* Allocate a new splay for this node if needed */ - if (!(MetaPool->Splay)) - if (!(MetaPool->Splay = new_splay())) - poolcheckfatal ("poolregister: Cannot allocate splay\n", 0); - - /* - * Register the memory range with the MetaPool's splay. - */ - splay_insert_ptr(MetaPool->Splay, (unsigned long)(ptr), NumBytes); -} - -/* - * Function: poolcheckregister() - * - * Description: - * This function registers a range of memory as belonging to the splay. It is - * currently used to register arrays, stack nodes, and global nodes. - */ -void poolcheckregister(Splay *splay, void * allocaptr, unsigned NumBytes) { - if (!ready) return; - splay_insert_ptr(splay, (unsigned long)(allocaptr), NumBytes); -}
diff --git a/safecode/runtime/PoolCheck/PoolCheck.h b/safecode/runtime/PoolCheck/PoolCheck.h deleted file mode 100755 index f48e02a..0000000 --- a/safecode/runtime/PoolCheck/PoolCheck.h +++ /dev/null
@@ -1,61 +0,0 @@ -/*===- PoolCheck.h - Pool check runtime interface file --------------------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#ifndef POOLCHECK_RUNTIME_H -#define POOLCHECK_RUNTIME_H - -#include "PoolSystem.h" -#include "splay.h" - -typedef struct PoolCheckSlab { - void *Slab; - struct PoolCheckSlab *nextSlab; -} PoolCheckSlab; - -typedef struct MetaPoolTy { - // Pointer to the OS pool that this MetaPool node describes - void * Pool; - - // A splay for registering stack and global values - Splay * Splay; - - // A pointer to the next pool in the list - struct MetaPoolTy *next; -} MetaPoolTy; - - -#ifdef __cpluscplus -extern "C" { -#endif - /* register that starting from allocaptr numbytes are a part of the pool */ - void poolcheck(MetaPoolTy **Pool, void *Node); - unsigned char poolcheckoptim(void *Pool, void *Node); - void poolcheckregister(Splay *splay, void * allocaptr, unsigned NumBytes); - void AddPoolDescToMetaPool(MetaPoolTy **MetaPool, void *PoolDesc); - void poolcheckarray(MetaPoolTy **Pool, void *Node, void * Node1); - void poolcheckiarray(MetaPoolTy **Pool, void *Node, void * Node1); - char poolcheckarrayoptim(MetaPoolTy *Pool, void *Node, void * Node1); - void poolcheckAddSlab(PoolCheckSlab **PoolCheckSlabPtr, void *Slab); - void poolcheckinit(void *Pool, unsigned NodeSize); - void poolcheckdestroy(void *Pool); - void poolcheckfree(void *Pool, void *Node); - - /* Functions that need to be provided by the pool allocation run-time */ - PoolCheckSlab *poolcheckslab(void *Pool); - Splay *poolchecksplay(void *Pool); - unsigned poolcheckslabsize (void * Pool); -#ifdef __cpluscplus -} -#endif - -#endif
diff --git a/safecode/runtime/PoolCheck/PoolSystem.h b/safecode/runtime/PoolCheck/PoolSystem.h deleted file mode 100755 index 42289ff..0000000 --- a/safecode/runtime/PoolCheck/PoolSystem.h +++ /dev/null
@@ -1,31 +0,0 @@ -/*===- PoolSystem.h - Pool check runtime interface to the system ----------===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file was developed by the LLVM research group and is distributed */ -/* under the University of Illinois Open Source License. See LICENSE.TXT for */ -/* details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#ifndef POOLSYSTEM_RUNTIME_H -#define POOLSYSTEM_RUNTIME_H - -#ifdef __cplusplus -extern "C" { -#endif - /* Functions that need to be provided by the pool allocation run-time */ - void poolcheckfail (const char * msg, int); - void poolcheckfatal (const char * msg, int); - void poolcheckinfo (const char * msg, int); - void * poolcheckmalloc (unsigned int size); - void printpoolinfo (void *Pool); - void poolcheckglobals (); -#ifdef __cplusplus -} -#endif - -#endif
diff --git a/safecode/runtime/PoolCheck/splay.c b/safecode/runtime/PoolCheck/splay.c deleted file mode 100755 index 9c1d96f..0000000 --- a/safecode/runtime/PoolCheck/splay.c +++ /dev/null
@@ -1,326 +0,0 @@ -/* - * Note: This file is obtained from - * http://www.cs.utk.edu/~cs140/spring-2005/notes/Splay/ - * FIXME: This may not be the most efficient version of splay implementation - * This may be updated with a different splay implementation in near future - */ - -#include "PoolSystem.h" -#include <stdio.h> -#include "splay.h" -#include <stdlib.h> -void rotate(Splay *node) -{ - Splay *parent, *grandparent; - - if (node->parent->is_sentinel) return; - - parent = node->parent; - grandparent = parent->parent; - - if (parent->left == node) { - parent->left = node->right; - if (parent->left != NULL) parent->left->parent = parent; - node->right = parent; - } else if (parent->right == node) { - parent->right = node->left; - if (parent->right != NULL) parent->right->parent = parent; - node->left = parent; - } else { - fprintf(stderr, "rotate: error: parent's children are not right\n"); - exit(1); - } - - parent->parent = node; - node->parent = grandparent; - - if (grandparent->is_sentinel) { - grandparent->parent = node; - } else if (grandparent->left == parent) { - grandparent->left = node; - } else if (grandparent->right == parent) { - grandparent->right = node; - } else { - fprintf(stderr, "rotate: error: grandparent's children are not right\n"); - exit(1); - } -} - - void splay(Splay *node) -{ - Splay *parent, *grandparent; - - if (node->is_sentinel) return; - - while(1) { - if (node->parent->is_sentinel) return; - - parent = node->parent; - grandparent = parent->parent; - - /* If the node's parent is the root of the tree, do one rotation */ - - if (grandparent->is_sentinel) { - rotate(node); - - /* If we have a zig-zig, then rotate my parent, then rotate me */ - - } else if ((parent->left == node && grandparent->left == parent) || - (parent->right == node && grandparent->right == parent)) { - rotate(parent); - rotate(node); - - /* If we have a zig-zag, then rotate me twice */ - - } else { - rotate(node); - rotate(node); - } - } -} - -Splay *new_splay() -{ - Splay *tree; - - tree = (Splay *) poolcheckmalloc (sizeof(struct splay)); - tree->key = 0; - tree->val = 0; - tree->is_sentinel = 1; - tree->flink = tree; - tree->blink = tree; - tree->left = NULL; - tree->right = NULL; - tree->parent = NULL; - return tree; -} - -Splay *splay_root(Splay *tree) -{ - return tree->parent; -} - -Splay *splay_first(Splay *tree) -{ - return tree->flink; -} - -Splay *splay_last(Splay *tree) -{ - return tree->blink; -} - -Splay *splay_next(Splay *node) -{ - return node->flink; -} - -Splay *splay_prev(Splay *node) -{ - return node->blink; -} - -Splay *splay_nil(Splay *tree) -{ - return tree; -} - -void free_splay(Splay *tree) -{ - Splay *ptr; - - while (1) { - ptr = splay_first(tree); - if (!ptr->is_sentinel) { - splay_delete_node(ptr); - } else { - free(ptr); - return; - } - } -} - - Splay *splay_find_nearest_ptr(Splay *tree, unsigned long key, int *cmpval) -{ - Splay *s, *last; - int cmp; - - last = tree; - s = splay_root(tree); - cmp = 1; - - while(s != NULL) { - last = s; - if (key == s->key) { - *cmpval = 0; - return s; - } else if (key < (s->key)) { - s = s->left; - cmp = -1; - } else { - if (key < (s->val + s->key)) { - *cmpval = 0; - return s; - } - s = s->right; - cmp = 1; - } - } - - *cmpval = cmp; - return last; -} - - -Splay *splay_find_ptr(Splay *tree, unsigned long key) -{ - int cmpval; - Splay *s; - - s = splay_find_nearest_ptr(tree, key, &cmpval); - splay(s); - if (cmpval == 0) return s; else return NULL; -} - - -Splay *splay_insert(Splay *tree, Jval key, Jval val, Splay *parent, int cmpval) -{ - Splay *s; - - s = (Splay *) poolcheckmalloc (sizeof(struct splay)); - s->is_sentinel = 0; - s->parent = parent; - s->left = NULL; - s->right = NULL; - s->key = key; - s->val = val; - - /* Set the parent's correct child pointer. The only - subtle case here is when the key is already in - the tree -- then we need to find a leaf node - to use as a parent */ - - /* When we're done here, parent should point to the - new node's successor in the linked list */ - - if (parent->is_sentinel) { - parent->parent = s; - } else { - if (cmpval == 0) { /* If the key is already in the - tree, try to insert a new one as the - node's right child. If the node already - has a right child, then try to insert the - new one as a left child. If there is already - a left child, then go to parent-flink and - insert the node as its left child. */ - if (parent->right == NULL) { - cmpval = 1; - } else if (parent->left == NULL) { - cmpval = -1; - } else { - parent = parent->flink; - s->parent = parent; - cmpval = -1; - } - } - if (cmpval > 0) { /* Insert as right child */ - if (parent->right != NULL) { - fprintf(stderr, "splay_insert error: parent->right != NULL"); - exit(1); - } - parent->right = s; - parent = parent->flink; - } else { - if (parent->left != NULL) { - fprintf(stderr, "splay_insert error: parent->left != NULL"); - exit(1); - } - parent->left = s; - } - } - - s->flink = parent; - s->blink = parent->blink; - s->flink->blink = s; - s->blink->flink = s; - splay(s); - return s; -} - -Splay *splay_insert_ptr(Splay *tree, unsigned long key, Jval val) -{ - Splay *parent; - int cmpval; - - parent = splay_find_nearest_ptr(tree, key, &cmpval); - return splay_insert(tree, key, val, parent, cmpval); -} - -extern void splay_delete_node(Splay *node) -{ - Splay *left, *right, *tree, *newroot; - - splay(node); - - tree = node->parent; - - left = node->left; - right = node->right; - newroot = node->flink; - - node->flink->blink = node->blink; - node->blink->flink = node->flink; - - free(node); - - if (right == NULL && left == NULL) { - tree->parent = NULL; - } else if (right == NULL) { - tree->parent = left; - left->parent = tree; - } else if (left == NULL) { - tree->parent = right; - right->parent = tree; - } else { - tree->parent = right; - right->parent = tree; - splay(newroot); - newroot->left = left; - left->parent = newroot; - } -} - Splay *finish_gte(int cmpval, Splay *s, int *found) -{ - - if (cmpval == 0) { - *found = 1; - return s; - } else if (cmpval < 0) { - *found = 0; - return s; - } else { - *found = 1; - return s->flink; - } -} -/* -Splay *splay_find_gte_str(Splay *tree, char *key, int *found) -{ - int cmpval; - Splay *s; - - s = splay_find_nearest_str(tree, key, &cmpval); - return finish_gte(cmpval, s, found); -} -*/ - -Splay *splay_find_gte_ptr(Splay *tree, unsigned long key, int *found) -{ - int cmpval; - Splay *s; - - s = splay_find_nearest_ptr(tree, key, &cmpval); - return finish_gte(cmpval, s, found); -} - -
diff --git a/safecode/runtime/PoolCheck/splay.h b/safecode/runtime/PoolCheck/splay.h deleted file mode 100755 index 68c2e76..0000000 --- a/safecode/runtime/PoolCheck/splay.h +++ /dev/null
@@ -1,55 +0,0 @@ -/* - * Note: This file is obtained from - * http://www.cs.utk.edu/~cs140/spring-2005/notes/Splay/ - * FIXME: This may not be the most efficient version of splay implementation - * This may be updated with a different splay implementation in near future - */ - -#ifndef _SPLAY_ -#define _SPLAY_ - -typedef unsigned long Jval ; - -/* Node identities */ - -#define SPLAY_SENTINEL 0 -#define SPLAY_OTHER 1 - -typedef struct splay { - Jval key; - Jval val; - int is_sentinel; - struct splay *left; - struct splay *right; - struct splay *flink; - struct splay *blink; - struct splay *parent; -} Splay; - -#ifdef __cplusplus -extern "C" { -#endif - Splay *new_splay(); - void free_splay(Splay *); - Splay *splay_insert_ptr(Splay *tree, unsigned long key, Jval val); - Splay *splay_find_ptr(Splay *tree, unsigned long key); - Splay *splay_find_gte_ptr(Splay *tree, unsigned long key, int *found); - - Splay *splay_root(Splay *tree); - Splay *splay_first(Splay *tree); - Splay *splay_last(Splay *tree); - Splay *splay_next(Splay *node); - Splay *splay_prev(Splay *node); - Splay *splay_nil(Splay *tree); - - void splay_delete_node(Splay *node); -#ifdef __cplusplus -} -#endif - -#define splay_traverse(ptr, list) \ - for (ptr = splay_first(list); ptr != splay_nil(list); ptr = splay_next(ptr)) -#define splay_rtraverse(ptr, list) \ - for (ptr = splay_last(list); ptr != splay_nil(list); ptr = splay_prev(ptr)) - -#endif
diff --git a/safecode/runtime/SafePoolAllocator/PageManager.cpp b/safecode/runtime/SafePoolAllocator/PageManager.cpp index a03cc8b..cdf549d 100755 --- a/safecode/runtime/SafePoolAllocator/PageManager.cpp +++ b/safecode/runtime/SafePoolAllocator/PageManager.cpp
@@ -59,15 +59,9 @@ // MAP_SHARED|MAP_ANONYMOUS, fd, 0); // void *pa = malloc(NumPages * PageSize); // assert(Addr != MAP_FAILED && "MMAP FAILED!"); -#if POSIX_MEMALIGN if (posix_memalign(&Addr, PageSize, NumPages*PageSize) != 0){ - assert(0 && "memalign failed \n"); + assert(1 && "memalign failed \n"); } -#else - if ((Addr = valloc (NumPages*PageSize)) == 0){ - assert(0 && "valloc failed \n"); - } -#endif poolmemusage += NumPages * PageSize; memset(Addr, 0xcc, NumPages *PageSize); return Addr;
diff --git a/safecode/tools/Makefile b/safecode/tools/Makefile index d99cd10..2244d19 100755 --- a/safecode/tools/Makefile +++ b/safecode/tools/Makefile
@@ -1,5 +1,5 @@ LEVEL = .. -PARALLEL_DIRS = Sc +PARALLEL_DIRS = include $(LEVEL)/Makefile.common