├── LICENSE.TXT ├── Makefile ├── Makefile.common.in ├── autoconf ├── AutoRegen.sh ├── LICENSE.TXT ├── aclocal.m4 ├── autom4te.cache │ ├── output.0 │ ├── output.1 │ ├── output.2 │ ├── requests │ ├── traces.0 │ ├── traces.1 │ └── traces.2 ├── config.guess ├── config.sub ├── configure.ac ├── install-sh ├── ltmain.sh └── mkinstalldirs ├── configure ├── include ├── CallContext.h ├── CallSensitiveAnalysisPass.h ├── Constraints │ ├── ConstraintKit.h │ ├── DepsTypes.h │ ├── LHConsSoln.h │ ├── LHConstraint.h │ ├── LHConstraintKit.h │ ├── LHConstraints.h │ ├── PartialSolution.h │ └── SolverThread.h ├── FPCache.h ├── FlowRecord.h ├── Infoflow.h ├── InfoflowSignature.h ├── InterProcAnalysisPass.h ├── PointsToInterface.h ├── SignatureLibrary.h ├── Slice.h └── SourceSinkAnalysis.h ├── lib ├── Constraints │ ├── LHConsSoln.cpp │ ├── LHConstraintKit.cpp │ ├── LHConstraints.cpp │ ├── MTSolve.cpp │ ├── Makefile │ ├── PartialSolution.cpp │ └── Test.cpp ├── Deps │ ├── CallContext.cpp │ ├── Infoflow.cpp │ ├── InfoflowSignature.cpp │ ├── Makefile │ ├── SignatureLibrary.cpp │ ├── Slice.cpp │ ├── StdLibSignatures.cpp │ └── StdLibSignatures.h ├── Makefile ├── PointsToInterface │ ├── Makefile │ └── PointsToInterface.cpp └── SourceSinkAnalysis │ ├── Makefile │ └── SourceSinkAnalysis.cpp └── runtime └── Makefile /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | llvm-deps Release License 3 | ============================================================================== 4 | University of Illinois/NCSA 5 | Open Source License 6 | 7 | Copyright (c) 2011 the University of Illinois at Urbana-Champaign. 8 | 9 | All rights reserved. 10 | 11 | Developed by: 12 | 13 | Will Dietz, Joshua Cranmer, Matthew Wala 14 | University of Illinois at Urbana-Champaign 15 | 16 | Scott Moore 17 | Harvard School of Engineering and Applied Science 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy of 20 | this software and associated documentation files (the "Software"), to deal with 21 | the Software without restriction, including without limitation the rights to 22 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 23 | of the Software, and to permit persons to whom the Software is furnished to do 24 | so, subject to the following conditions: 25 | 26 | * Redistributions of source code must retain the above copyright notice, 27 | this list of conditions and the following disclaimers. 28 | 29 | * Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimers in the 31 | documentation and/or other materials provided with the distribution. 32 | 33 | * Neither the names of the LLVM Team, University of Illinois at 34 | Urbana-Champaign, nor the names of its contributors may be used to 35 | endorse or promote products derived from this Software without specific 36 | prior written permission. 37 | 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 41 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE 45 | SOFTWARE. 46 | 47 | ============================================================================== 48 | Copyrights and Licenses for Third Party Software: 49 | ============================================================================== 50 | 51 | This software contains code written by third parties. Such software 52 | will have its own individual LICENSE.TXT file in the directory in which it 53 | appears. This file will describe the copyrights, license, and restrictions 54 | which apply to that code. 55 | 56 | The disclaimer of warranty in the University of Illinois Open Source License 57 | applies to all code in this Distribution, and nothing in any of the 58 | other licenses gives permission to use the names of the LLVM Team or the 59 | University of Illinois to endorse or promote products derived from this 60 | Software. 61 | 62 | The following pieces of software have additional or alternate copyrights, 63 | licenses, and/or restrictions: 64 | 65 | Program Directory 66 | ------- --------- 67 | Autoconf deps/autoconf 68 | 69 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a sample Makefile for a project that uses LLVM. 3 | # 4 | 5 | # 6 | # Indicates our relative path to the top of the project's root directory. 7 | # 8 | LEVEL = . 9 | 10 | # 11 | # Directories that needs to be built. 12 | # 13 | DIRS = lib runtime 14 | 15 | # 16 | # Include the Master Makefile that knows how to build all. 17 | # 18 | -include $(LEVEL)/Makefile.common 19 | 20 | -------------------------------------------------------------------------------- /Makefile.common.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME := deps 2 | PROJ_VERSION := 1.0 3 | 4 | # Set this variable to the top of the LLVM source tree. 5 | LLVM_SRC_ROOT = @LLVM_SRC@ 6 | 7 | # Set this variable to the top level directory where LLVM was built 8 | # (this is *not* the same as OBJ_ROOT as defined in LLVM's Makefile.config). 9 | LLVM_OBJ_ROOT = @LLVM_OBJ@ 10 | 11 | # Set the source root and source directory pathnames 12 | ####PROJ_SRC_DIR := $(subst //,/,@abs_top_srcdir@/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR))) 13 | 14 | PROJ_SRC_ROOT := $(subst //,/,@abs_top_srcdir@) 15 | 16 | # Set the root directory of this project's object files 17 | PROJ_OBJ_ROOT := $(subst //,/,@abs_top_builddir@) 18 | 19 | # Set the root directory of this project's install prefix 20 | PROJ_INSTALL_ROOT := @prefix@ 21 | 22 | # Set the location of the pool allocation project 23 | POOLALLOC_SRCDIR := @poolallocsrcdir@ 24 | POOLALLOC_OBJDIR := @poolallocobjdir@ 25 | 26 | # Set the location of the LLVM Test Suite 27 | TEST_SRCDIR := @testsrcdir@ 28 | TEST_OBJDIR := @testobjdir@ 29 | 30 | # All of the code should additionally look inside the pool allocation source 31 | # code for include files 32 | SC_FLAGS = -DSAFECODE -I$(POOLALLOC_SRCDIR)/include -I$(POOLALLOC_OBJDIR)/include -Werror -Wall -fexceptions 33 | CFLAGS += $(SC_FLAGS) 34 | CPPFLAGS += $(SC_FLAGS) 35 | CXXFLAGS += $(SC_FLAGS) -Wno-deprecated -Wno-overloaded-virtual 36 | 37 | # Include LLVM's Master Makefile. 38 | include $(LLVM_SRC_ROOT)/Makefile.common 39 | 40 | -------------------------------------------------------------------------------- /autoconf/AutoRegen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | die () { 3 | echo "$@" 1>&2 4 | exit 1 5 | } 6 | test -d autoconf && test -f autoconf/configure.ac && cd autoconf 7 | test -f configure.ac || die "Can't find 'autoconf' dir; please cd into it first" 8 | autoconf --version | egrep '2\.[5-6][0-9]' > /dev/null 9 | if test $? -ne 0 ; then 10 | die "Your autoconf was not detected as being 2.5x" 11 | fi 12 | cwd=`pwd` 13 | if test -d ../../../autoconf/m4 ; then 14 | cd ../../../autoconf/m4 15 | llvm_m4=`pwd` 16 | cd $cwd 17 | elif test -d ../../llvm/autoconf/m4 ; then 18 | cd ../../llvm/autoconf/m4 19 | llvm_m4=`pwd` 20 | cd $cwd 21 | else 22 | die "Can't find the LLVM autoconf/m4 directory. SAFECode should be checked out to projects directory" 23 | fi 24 | echo "Regenerating aclocal.m4 with aclocal" 25 | rm -f aclocal.m4 26 | aclocal -I $llvm_m4 -I "$llvm_m4/.." || die "aclocal failed" 27 | echo "Regenerating configure with autoconf 2.5x" 28 | autoconf --force --warnings=all -o ../configure configure.ac || die "autoconf failed" 29 | cd .. 30 | exit 0 31 | -------------------------------------------------------------------------------- /autoconf/LICENSE.TXT: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------ 2 | Autoconf Files 3 | ------------------------------------------------------------------------------ 4 | All autoconf files are licensed under the LLVM license with the following 5 | additions: 6 | 7 | llvm/autoconf/install-sh: 8 | This script is licensed under the LLVM license, with the following 9 | additional copyrights and restrictions: 10 | 11 | Copyright 1991 by the Massachusetts Institute of Technology 12 | 13 | Permission to use, copy, modify, distribute, and sell this software and its 14 | documentation for any purpose is hereby granted without fee, provided that 15 | the above copyright notice appear in all copies and that both that 16 | copyright notice and this permission notice appear in supporting 17 | documentation, and that the name of M.I.T. not be used in advertising or 18 | publicity pertaining to distribution of the software without specific, 19 | written prior permission. M.I.T. makes no representations about the 20 | suitability of this software for any purpose. It is provided "as is" 21 | without express or implied warranty. 22 | 23 | Please see the source files for additional copyrights. 24 | 25 | -------------------------------------------------------------------------------- /autoconf/aclocal.m4: -------------------------------------------------------------------------------- 1 | # generated automatically by aclocal 1.11.3 -*- Autoconf -*- 2 | 3 | # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 4 | # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, 5 | # Inc. 6 | # This file is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | # 16 | # Configure a Makefile without clobbering it if it exists and is not out of 17 | # date. This macro is unique to LLVM. 18 | # 19 | AC_DEFUN([AC_CONFIG_MAKEFILE], 20 | [AC_CONFIG_COMMANDS($1, 21 | [${llvm_src}/autoconf/mkinstalldirs `dirname $1` 22 | ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/$1 $1]) 23 | ]) 24 | 25 | # 26 | # Provide the arguments and other processing needed for an LLVM project 27 | # 28 | AC_DEFUN([LLVM_CONFIG_PROJECT], 29 | [AC_ARG_WITH([llvmsrc], 30 | AS_HELP_STRING([--with-llvmsrc],[Location of LLVM Source Code]), 31 | [llvm_src="$withval"],[llvm_src="]$1["]) 32 | AC_SUBST(LLVM_SRC,$llvm_src) 33 | AC_ARG_WITH([llvmobj], 34 | AS_HELP_STRING([--with-llvmobj],[Location of LLVM Object Code]), 35 | [llvm_obj="$withval"],[llvm_obj="]$2["]) 36 | AC_SUBST(LLVM_OBJ,$llvm_obj) 37 | AC_CONFIG_COMMANDS([setup],,[llvm_src="${LLVM_SRC}"]) 38 | ]) 39 | 40 | -------------------------------------------------------------------------------- /autoconf/autom4te.cache/requests: -------------------------------------------------------------------------------- 1 | # This file was generated by Autom4te Sun Nov 6 20:57:04 UTC 2011. 2 | # It contains the lists of macros which have been traced. 3 | # It can be safely removed. 4 | 5 | @request = ( 6 | bless( [ 7 | '0', 8 | 1, 9 | [ 10 | '/usr/share/autoconf' 11 | ], 12 | [ 13 | '/usr/share/autoconf/autoconf/autoconf.m4f', 14 | '/home/sdmoore/llvm/autoconf/m4/config_makefile.m4', 15 | '/home/sdmoore/llvm/autoconf/m4/config_project.m4', 16 | 'configure.ac' 17 | ], 18 | { 19 | 'AC_CONFIG_MAKEFILE' => 1, 20 | '_AM_AUTOCONF_VERSION' => 1, 21 | 'm4_pattern_allow' => 1, 22 | 'm4_pattern_forbid' => 1, 23 | 'include' => 1, 24 | 'AC_DEFUN_ONCE' => 1, 25 | 'AC_DEFUN' => 1, 26 | 'm4_include' => 1, 27 | 'LLVM_CONFIG_PROJECT' => 1, 28 | '_m4_warn' => 1, 29 | 'AU_DEFUN' => 1 30 | } 31 | ], 'Autom4te::Request' ), 32 | bless( [ 33 | '1', 34 | 1, 35 | [ 36 | '/usr/share/autoconf' 37 | ], 38 | [ 39 | '/usr/share/autoconf/autoconf/autoconf.m4f', 40 | 'aclocal.m4', 41 | 'configure.ac' 42 | ], 43 | { 44 | '_LT_AC_TAGCONFIG' => 1, 45 | 'AM_PROG_F77_C_O' => 1, 46 | 'AC_INIT' => 1, 47 | 'm4_pattern_forbid' => 1, 48 | '_AM_COND_IF' => 1, 49 | 'AC_CANONICAL_TARGET' => 1, 50 | 'AC_SUBST' => 1, 51 | 'AC_CONFIG_LIBOBJ_DIR' => 1, 52 | 'AC_FC_SRCEXT' => 1, 53 | 'AC_CANONICAL_HOST' => 1, 54 | 'AC_PROG_LIBTOOL' => 1, 55 | 'AM_INIT_AUTOMAKE' => 1, 56 | 'AM_PATH_GUILE' => 1, 57 | 'AC_CONFIG_SUBDIRS' => 1, 58 | 'AM_AUTOMAKE_VERSION' => 1, 59 | 'LT_CONFIG_LTDL_DIR' => 1, 60 | 'AC_REQUIRE_AUX_FILE' => 1, 61 | 'AC_CONFIG_LINKS' => 1, 62 | 'm4_sinclude' => 1, 63 | 'LT_SUPPORTED_TAG' => 1, 64 | 'AM_MAINTAINER_MODE' => 1, 65 | 'AM_NLS' => 1, 66 | 'AM_GNU_GETTEXT_INTL_SUBDIR' => 1, 67 | 'AM_MAKEFILE_INCLUDE' => 1, 68 | '_m4_warn' => 1, 69 | 'AM_PROG_CXX_C_O' => 1, 70 | '_AM_COND_ENDIF' => 1, 71 | '_AM_MAKEFILE_INCLUDE' => 1, 72 | 'AM_ENABLE_MULTILIB' => 1, 73 | 'AM_SILENT_RULES' => 1, 74 | 'AM_PROG_MOC' => 1, 75 | 'AC_CONFIG_FILES' => 1, 76 | 'include' => 1, 77 | 'LT_INIT' => 1, 78 | 'AM_PROG_AR' => 1, 79 | 'AM_GNU_GETTEXT' => 1, 80 | 'AC_LIBSOURCE' => 1, 81 | 'AM_PROG_FC_C_O' => 1, 82 | 'AC_CANONICAL_BUILD' => 1, 83 | 'AC_FC_FREEFORM' => 1, 84 | 'AH_OUTPUT' => 1, 85 | '_AM_SUBST_NOTMAKE' => 1, 86 | 'AC_CONFIG_AUX_DIR' => 1, 87 | 'sinclude' => 1, 88 | 'AM_PROG_CC_C_O' => 1, 89 | 'm4_pattern_allow' => 1, 90 | 'AM_XGETTEXT_OPTION' => 1, 91 | 'AC_CANONICAL_SYSTEM' => 1, 92 | 'AM_CONDITIONAL' => 1, 93 | 'AC_CONFIG_HEADERS' => 1, 94 | 'AC_DEFINE_TRACE_LITERAL' => 1, 95 | 'AM_POT_TOOLS' => 1, 96 | 'm4_include' => 1, 97 | '_AM_COND_ELSE' => 1, 98 | 'AC_SUBST_TRACE' => 1 99 | } 100 | ], 'Autom4te::Request' ) 101 | ); 102 | 103 | -------------------------------------------------------------------------------- /autoconf/autom4te.cache/traces.0: -------------------------------------------------------------------------------- 1 | m4trace:/home/sdmoore/llvm/autoconf/m4/config_makefile.m4:5: -1- AC_DEFUN([AC_CONFIG_MAKEFILE], [AC_CONFIG_COMMANDS($1, 2 | [${llvm_src}/autoconf/mkinstalldirs `dirname $1` 3 | ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/$1 $1]) 4 | ]) 5 | m4trace:/home/sdmoore/llvm/autoconf/m4/config_project.m4:4: -1- AC_DEFUN([LLVM_CONFIG_PROJECT], [AC_ARG_WITH([llvmsrc], 6 | AS_HELP_STRING([--with-llvmsrc],[Location of LLVM Source Code]), 7 | [llvm_src="$withval"],[llvm_src="]$1["]) 8 | AC_SUBST(LLVM_SRC,$llvm_src) 9 | AC_ARG_WITH([llvmobj], 10 | AS_HELP_STRING([--with-llvmobj],[Location of LLVM Object Code]), 11 | [llvm_obj="$withval"],[llvm_obj="]$2["]) 12 | AC_SUBST(LLVM_OBJ,$llvm_obj) 13 | AC_CONFIG_COMMANDS([setup],,[llvm_src="${LLVM_SRC}"]) 14 | ]) 15 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?A[CHUM]_]) 16 | m4trace:configure.ac:4: -1- m4_pattern_forbid([_AC_]) 17 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) 18 | m4trace:configure.ac:4: -1- m4_pattern_allow([^AS_FLAGS$]) 19 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?m4_]) 20 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^dnl$]) 21 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?AS_]) 22 | m4trace:configure.ac:4: -1- m4_pattern_allow([^SHELL$]) 23 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PATH_SEPARATOR$]) 24 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_NAME$]) 25 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) 26 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_VERSION$]) 27 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_STRING$]) 28 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) 29 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_URL$]) 30 | m4trace:configure.ac:4: -1- m4_pattern_allow([^exec_prefix$]) 31 | m4trace:configure.ac:4: -1- m4_pattern_allow([^prefix$]) 32 | m4trace:configure.ac:4: -1- m4_pattern_allow([^program_transform_name$]) 33 | m4trace:configure.ac:4: -1- m4_pattern_allow([^bindir$]) 34 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sbindir$]) 35 | m4trace:configure.ac:4: -1- m4_pattern_allow([^libexecdir$]) 36 | m4trace:configure.ac:4: -1- m4_pattern_allow([^datarootdir$]) 37 | m4trace:configure.ac:4: -1- m4_pattern_allow([^datadir$]) 38 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sysconfdir$]) 39 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sharedstatedir$]) 40 | m4trace:configure.ac:4: -1- m4_pattern_allow([^localstatedir$]) 41 | m4trace:configure.ac:4: -1- m4_pattern_allow([^includedir$]) 42 | m4trace:configure.ac:4: -1- m4_pattern_allow([^oldincludedir$]) 43 | m4trace:configure.ac:4: -1- m4_pattern_allow([^docdir$]) 44 | m4trace:configure.ac:4: -1- m4_pattern_allow([^infodir$]) 45 | m4trace:configure.ac:4: -1- m4_pattern_allow([^htmldir$]) 46 | m4trace:configure.ac:4: -1- m4_pattern_allow([^dvidir$]) 47 | m4trace:configure.ac:4: -1- m4_pattern_allow([^pdfdir$]) 48 | m4trace:configure.ac:4: -1- m4_pattern_allow([^psdir$]) 49 | m4trace:configure.ac:4: -1- m4_pattern_allow([^libdir$]) 50 | m4trace:configure.ac:4: -1- m4_pattern_allow([^localedir$]) 51 | m4trace:configure.ac:4: -1- m4_pattern_allow([^mandir$]) 52 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_NAME$]) 53 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) 54 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_VERSION$]) 55 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_STRING$]) 56 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) 57 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_URL$]) 58 | m4trace:configure.ac:4: -1- m4_pattern_allow([^DEFS$]) 59 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_C$]) 60 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_N$]) 61 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_T$]) 62 | m4trace:configure.ac:4: -1- m4_pattern_allow([^LIBS$]) 63 | m4trace:configure.ac:4: -1- m4_pattern_allow([^build_alias$]) 64 | m4trace:configure.ac:4: -1- m4_pattern_allow([^host_alias$]) 65 | m4trace:configure.ac:4: -1- m4_pattern_allow([^target_alias$]) 66 | m4trace:configure.ac:12: -1- LLVM_CONFIG_PROJECT([$LLVM_SRC_ROOT], [$LLVM_OBJ_ROOT]) 67 | m4trace:configure.ac:12: -1- m4_pattern_allow([^LLVM_SRC$]) 68 | m4trace:configure.ac:12: -1- m4_pattern_allow([^LLVM_OBJ$]) 69 | m4trace:configure.ac:26: -1- AC_CONFIG_MAKEFILE([Makefile]) 70 | m4trace:configure.ac:27: -1- AC_CONFIG_MAKEFILE([lib/Makefile]) 71 | m4trace:configure.ac:28: -1- AC_CONFIG_MAKEFILE([runtime/Makefile]) 72 | m4trace:configure.ac:29: -1- AC_CONFIG_MAKEFILE([test/Makefile]) 73 | m4trace:configure.ac:73: -2- m4_pattern_allow([^poolallocsrcdir$]) 74 | m4trace:configure.ac:74: -2- m4_pattern_allow([^poolallocsrcdir$]) 75 | m4trace:configure.ac:80: -2- m4_pattern_allow([^poolallocobjdir$]) 76 | m4trace:configure.ac:81: -2- m4_pattern_allow([^poolallocobjdir$]) 77 | m4trace:configure.ac:88: -2- m4_pattern_allow([^testsrcdir$]) 78 | m4trace:configure.ac:89: -2- m4_pattern_allow([^testsrcdir$]) 79 | m4trace:configure.ac:95: -2- m4_pattern_allow([^testobjdir$]) 80 | m4trace:configure.ac:96: -2- m4_pattern_allow([^testobjdir$]) 81 | m4trace:configure.ac:110: -1- m4_pattern_allow([^LIB@&t@OBJS$]) 82 | m4trace:configure.ac:110: -1- m4_pattern_allow([^LTLIBOBJS$]) 83 | -------------------------------------------------------------------------------- /autoconf/autom4te.cache/traces.1: -------------------------------------------------------------------------------- 1 | m4trace:configure.ac:4: -1- AC_INIT([[[llvm-deps]]], [[[0.00]]], [sdmoore@fas.harvard.edu]) 2 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?A[CHUM]_]) 3 | m4trace:configure.ac:4: -1- m4_pattern_forbid([_AC_]) 4 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) 5 | m4trace:configure.ac:4: -1- m4_pattern_allow([^AS_FLAGS$]) 6 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?m4_]) 7 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^dnl$]) 8 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?AS_]) 9 | m4trace:configure.ac:4: -1- AC_SUBST([SHELL]) 10 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([SHELL]) 11 | m4trace:configure.ac:4: -1- m4_pattern_allow([^SHELL$]) 12 | m4trace:configure.ac:4: -1- AC_SUBST([PATH_SEPARATOR]) 13 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([PATH_SEPARATOR]) 14 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PATH_SEPARATOR$]) 15 | m4trace:configure.ac:4: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME], ['AC_PACKAGE_NAME'])]) 16 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([PACKAGE_NAME]) 17 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_NAME$]) 18 | m4trace:configure.ac:4: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME], ['AC_PACKAGE_TARNAME'])]) 19 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([PACKAGE_TARNAME]) 20 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) 21 | m4trace:configure.ac:4: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION], ['AC_PACKAGE_VERSION'])]) 22 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([PACKAGE_VERSION]) 23 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_VERSION$]) 24 | m4trace:configure.ac:4: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING], ['AC_PACKAGE_STRING'])]) 25 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([PACKAGE_STRING]) 26 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_STRING$]) 27 | m4trace:configure.ac:4: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])]) 28 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([PACKAGE_BUGREPORT]) 29 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) 30 | m4trace:configure.ac:4: -1- AC_SUBST([PACKAGE_URL], [m4_ifdef([AC_PACKAGE_URL], ['AC_PACKAGE_URL'])]) 31 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([PACKAGE_URL]) 32 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_URL$]) 33 | m4trace:configure.ac:4: -1- AC_SUBST([exec_prefix], [NONE]) 34 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([exec_prefix]) 35 | m4trace:configure.ac:4: -1- m4_pattern_allow([^exec_prefix$]) 36 | m4trace:configure.ac:4: -1- AC_SUBST([prefix], [NONE]) 37 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([prefix]) 38 | m4trace:configure.ac:4: -1- m4_pattern_allow([^prefix$]) 39 | m4trace:configure.ac:4: -1- AC_SUBST([program_transform_name], [s,x,x,]) 40 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([program_transform_name]) 41 | m4trace:configure.ac:4: -1- m4_pattern_allow([^program_transform_name$]) 42 | m4trace:configure.ac:4: -1- AC_SUBST([bindir], ['${exec_prefix}/bin']) 43 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([bindir]) 44 | m4trace:configure.ac:4: -1- m4_pattern_allow([^bindir$]) 45 | m4trace:configure.ac:4: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin']) 46 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([sbindir]) 47 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sbindir$]) 48 | m4trace:configure.ac:4: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec']) 49 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([libexecdir]) 50 | m4trace:configure.ac:4: -1- m4_pattern_allow([^libexecdir$]) 51 | m4trace:configure.ac:4: -1- AC_SUBST([datarootdir], ['${prefix}/share']) 52 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([datarootdir]) 53 | m4trace:configure.ac:4: -1- m4_pattern_allow([^datarootdir$]) 54 | m4trace:configure.ac:4: -1- AC_SUBST([datadir], ['${datarootdir}']) 55 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([datadir]) 56 | m4trace:configure.ac:4: -1- m4_pattern_allow([^datadir$]) 57 | m4trace:configure.ac:4: -1- AC_SUBST([sysconfdir], ['${prefix}/etc']) 58 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([sysconfdir]) 59 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sysconfdir$]) 60 | m4trace:configure.ac:4: -1- AC_SUBST([sharedstatedir], ['${prefix}/com']) 61 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([sharedstatedir]) 62 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sharedstatedir$]) 63 | m4trace:configure.ac:4: -1- AC_SUBST([localstatedir], ['${prefix}/var']) 64 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([localstatedir]) 65 | m4trace:configure.ac:4: -1- m4_pattern_allow([^localstatedir$]) 66 | m4trace:configure.ac:4: -1- AC_SUBST([includedir], ['${prefix}/include']) 67 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([includedir]) 68 | m4trace:configure.ac:4: -1- m4_pattern_allow([^includedir$]) 69 | m4trace:configure.ac:4: -1- AC_SUBST([oldincludedir], ['/usr/include']) 70 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([oldincludedir]) 71 | m4trace:configure.ac:4: -1- m4_pattern_allow([^oldincludedir$]) 72 | m4trace:configure.ac:4: -1- AC_SUBST([docdir], [m4_ifset([AC_PACKAGE_TARNAME], 73 | ['${datarootdir}/doc/${PACKAGE_TARNAME}'], 74 | ['${datarootdir}/doc/${PACKAGE}'])]) 75 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([docdir]) 76 | m4trace:configure.ac:4: -1- m4_pattern_allow([^docdir$]) 77 | m4trace:configure.ac:4: -1- AC_SUBST([infodir], ['${datarootdir}/info']) 78 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([infodir]) 79 | m4trace:configure.ac:4: -1- m4_pattern_allow([^infodir$]) 80 | m4trace:configure.ac:4: -1- AC_SUBST([htmldir], ['${docdir}']) 81 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([htmldir]) 82 | m4trace:configure.ac:4: -1- m4_pattern_allow([^htmldir$]) 83 | m4trace:configure.ac:4: -1- AC_SUBST([dvidir], ['${docdir}']) 84 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([dvidir]) 85 | m4trace:configure.ac:4: -1- m4_pattern_allow([^dvidir$]) 86 | m4trace:configure.ac:4: -1- AC_SUBST([pdfdir], ['${docdir}']) 87 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([pdfdir]) 88 | m4trace:configure.ac:4: -1- m4_pattern_allow([^pdfdir$]) 89 | m4trace:configure.ac:4: -1- AC_SUBST([psdir], ['${docdir}']) 90 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([psdir]) 91 | m4trace:configure.ac:4: -1- m4_pattern_allow([^psdir$]) 92 | m4trace:configure.ac:4: -1- AC_SUBST([libdir], ['${exec_prefix}/lib']) 93 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([libdir]) 94 | m4trace:configure.ac:4: -1- m4_pattern_allow([^libdir$]) 95 | m4trace:configure.ac:4: -1- AC_SUBST([localedir], ['${datarootdir}/locale']) 96 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([localedir]) 97 | m4trace:configure.ac:4: -1- m4_pattern_allow([^localedir$]) 98 | m4trace:configure.ac:4: -1- AC_SUBST([mandir], ['${datarootdir}/man']) 99 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([mandir]) 100 | m4trace:configure.ac:4: -1- m4_pattern_allow([^mandir$]) 101 | m4trace:configure.ac:4: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME]) 102 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_NAME$]) 103 | m4trace:configure.ac:4: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */ 104 | @%:@undef PACKAGE_NAME]) 105 | m4trace:configure.ac:4: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME]) 106 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) 107 | m4trace:configure.ac:4: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */ 108 | @%:@undef PACKAGE_TARNAME]) 109 | m4trace:configure.ac:4: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION]) 110 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_VERSION$]) 111 | m4trace:configure.ac:4: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */ 112 | @%:@undef PACKAGE_VERSION]) 113 | m4trace:configure.ac:4: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING]) 114 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_STRING$]) 115 | m4trace:configure.ac:4: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */ 116 | @%:@undef PACKAGE_STRING]) 117 | m4trace:configure.ac:4: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT]) 118 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) 119 | m4trace:configure.ac:4: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */ 120 | @%:@undef PACKAGE_BUGREPORT]) 121 | m4trace:configure.ac:4: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_URL]) 122 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_URL$]) 123 | m4trace:configure.ac:4: -1- AH_OUTPUT([PACKAGE_URL], [/* Define to the home page for this package. */ 124 | @%:@undef PACKAGE_URL]) 125 | m4trace:configure.ac:4: -1- AC_SUBST([DEFS]) 126 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([DEFS]) 127 | m4trace:configure.ac:4: -1- m4_pattern_allow([^DEFS$]) 128 | m4trace:configure.ac:4: -1- AC_SUBST([ECHO_C]) 129 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([ECHO_C]) 130 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_C$]) 131 | m4trace:configure.ac:4: -1- AC_SUBST([ECHO_N]) 132 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([ECHO_N]) 133 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_N$]) 134 | m4trace:configure.ac:4: -1- AC_SUBST([ECHO_T]) 135 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([ECHO_T]) 136 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_T$]) 137 | m4trace:configure.ac:4: -1- AC_SUBST([LIBS]) 138 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([LIBS]) 139 | m4trace:configure.ac:4: -1- m4_pattern_allow([^LIBS$]) 140 | m4trace:configure.ac:4: -1- AC_SUBST([build_alias]) 141 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([build_alias]) 142 | m4trace:configure.ac:4: -1- m4_pattern_allow([^build_alias$]) 143 | m4trace:configure.ac:4: -1- AC_SUBST([host_alias]) 144 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([host_alias]) 145 | m4trace:configure.ac:4: -1- m4_pattern_allow([^host_alias$]) 146 | m4trace:configure.ac:4: -1- AC_SUBST([target_alias]) 147 | m4trace:configure.ac:4: -1- AC_SUBST_TRACE([target_alias]) 148 | m4trace:configure.ac:4: -1- m4_pattern_allow([^target_alias$]) 149 | m4trace:configure.ac:12: -1- AC_SUBST([LLVM_SRC], [$llvm_src]) 150 | m4trace:configure.ac:12: -1- AC_SUBST_TRACE([LLVM_SRC]) 151 | m4trace:configure.ac:12: -1- m4_pattern_allow([^LLVM_SRC$]) 152 | m4trace:configure.ac:12: -1- AC_SUBST([LLVM_OBJ], [$llvm_obj]) 153 | m4trace:configure.ac:12: -1- AC_SUBST_TRACE([LLVM_OBJ]) 154 | m4trace:configure.ac:12: -1- m4_pattern_allow([^LLVM_OBJ$]) 155 | m4trace:configure.ac:16: -1- AC_CONFIG_AUX_DIR([$LLVM_SRC/autoconf]) 156 | m4trace:configure.ac:22: -1- AC_CONFIG_FILES([Makefile.common]) 157 | m4trace:configure.ac:73: -2- AC_SUBST([poolallocsrcdir], ["$withval"]) 158 | m4trace:configure.ac:73: -2- AC_SUBST_TRACE([poolallocsrcdir]) 159 | m4trace:configure.ac:73: -2- m4_pattern_allow([^poolallocsrcdir$]) 160 | m4trace:configure.ac:74: -2- AC_SUBST([poolallocsrcdir], ["$LLVM_SRC_ROOT/projects/poolalloc" 161 | ]) 162 | m4trace:configure.ac:74: -2- AC_SUBST_TRACE([poolallocsrcdir]) 163 | m4trace:configure.ac:74: -2- m4_pattern_allow([^poolallocsrcdir$]) 164 | m4trace:configure.ac:80: -2- AC_SUBST([poolallocobjdir], ["$withval"]) 165 | m4trace:configure.ac:80: -2- AC_SUBST_TRACE([poolallocobjdir]) 166 | m4trace:configure.ac:80: -2- m4_pattern_allow([^poolallocobjdir$]) 167 | m4trace:configure.ac:81: -2- AC_SUBST([poolallocobjdir], ["$LLVM_OBJ_ROOT/projects/poolalloc" 168 | ]) 169 | m4trace:configure.ac:81: -2- AC_SUBST_TRACE([poolallocobjdir]) 170 | m4trace:configure.ac:81: -2- m4_pattern_allow([^poolallocobjdir$]) 171 | m4trace:configure.ac:88: -2- AC_SUBST([testsrcdir], ["$withval"]) 172 | m4trace:configure.ac:88: -2- AC_SUBST_TRACE([testsrcdir]) 173 | m4trace:configure.ac:88: -2- m4_pattern_allow([^testsrcdir$]) 174 | m4trace:configure.ac:89: -2- AC_SUBST([testsrcdir], ["$LLVM_SRC_ROOT/projects/test-suite" 175 | ]) 176 | m4trace:configure.ac:89: -2- AC_SUBST_TRACE([testsrcdir]) 177 | m4trace:configure.ac:89: -2- m4_pattern_allow([^testsrcdir$]) 178 | m4trace:configure.ac:95: -2- AC_SUBST([testobjdir], ["$withval"]) 179 | m4trace:configure.ac:95: -2- AC_SUBST_TRACE([testobjdir]) 180 | m4trace:configure.ac:95: -2- m4_pattern_allow([^testobjdir$]) 181 | m4trace:configure.ac:96: -2- AC_SUBST([testobjdir], ["$LLVM_OBJ_ROOT/projects/test-suite" 182 | ]) 183 | m4trace:configure.ac:96: -2- AC_SUBST_TRACE([testobjdir]) 184 | m4trace:configure.ac:96: -2- m4_pattern_allow([^testobjdir$]) 185 | m4trace:configure.ac:110: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs]) 186 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([LIB@&t@OBJS]) 187 | m4trace:configure.ac:110: -1- m4_pattern_allow([^LIB@&t@OBJS$]) 188 | m4trace:configure.ac:110: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs]) 189 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([LTLIBOBJS]) 190 | m4trace:configure.ac:110: -1- m4_pattern_allow([^LTLIBOBJS$]) 191 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([top_builddir]) 192 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([top_build_prefix]) 193 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([srcdir]) 194 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([abs_srcdir]) 195 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([top_srcdir]) 196 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([abs_top_srcdir]) 197 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([builddir]) 198 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([abs_builddir]) 199 | m4trace:configure.ac:110: -1- AC_SUBST_TRACE([abs_top_builddir]) 200 | -------------------------------------------------------------------------------- /autoconf/autom4te.cache/traces.2: -------------------------------------------------------------------------------- 1 | m4trace:/Users/criswell/src/llvm/autoconf/m4/config_makefile.m4:9: -1- AC_DEFUN([AC_CONFIG_MAKEFILE], [AC_CONFIG_COMMANDS($1, 2 | [${llvm_src}/autoconf/mkinstalldirs `dirname $1` 3 | ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/$1 $1]) 4 | ]) 5 | m4trace:/Users/criswell/src/llvm/autoconf/m4/config_project.m4:14: -1- AC_DEFUN([LLVM_CONFIG_PROJECT], [AC_ARG_WITH([llvmsrc], 6 | AS_HELP_STRING([--with-llvmsrc],[Location of LLVM Source Code]), 7 | [llvm_src="$withval"],[llvm_src="]$1["]) 8 | AC_SUBST(LLVM_SRC,$llvm_src) 9 | AC_ARG_WITH([llvmobj], 10 | AS_HELP_STRING([--with-llvmobj],[Location of LLVM Object Code]), 11 | [llvm_obj="$withval"],[llvm_obj="]$2["]) 12 | AC_SUBST(LLVM_OBJ,$llvm_obj) 13 | AC_CONFIG_COMMANDS([setup],,[llvm_src="${LLVM_SRC}"]) 14 | ]) 15 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?A[CHUM]_]) 16 | m4trace:configure.ac:4: -1- m4_pattern_forbid([_AC_]) 17 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) 18 | m4trace:configure.ac:4: -1- m4_pattern_allow([^AS_FLAGS$]) 19 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?m4_]) 20 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^dnl$]) 21 | m4trace:configure.ac:4: -1- m4_pattern_forbid([^_?AS_]) 22 | m4trace:configure.ac:4: -1- m4_pattern_allow([^SHELL$]) 23 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PATH_SEPARATOR$]) 24 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_NAME$]) 25 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) 26 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_VERSION$]) 27 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_STRING$]) 28 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) 29 | m4trace:configure.ac:4: -1- m4_pattern_allow([^exec_prefix$]) 30 | m4trace:configure.ac:4: -1- m4_pattern_allow([^prefix$]) 31 | m4trace:configure.ac:4: -1- m4_pattern_allow([^program_transform_name$]) 32 | m4trace:configure.ac:4: -1- m4_pattern_allow([^bindir$]) 33 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sbindir$]) 34 | m4trace:configure.ac:4: -1- m4_pattern_allow([^libexecdir$]) 35 | m4trace:configure.ac:4: -1- m4_pattern_allow([^datarootdir$]) 36 | m4trace:configure.ac:4: -1- m4_pattern_allow([^datadir$]) 37 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sysconfdir$]) 38 | m4trace:configure.ac:4: -1- m4_pattern_allow([^sharedstatedir$]) 39 | m4trace:configure.ac:4: -1- m4_pattern_allow([^localstatedir$]) 40 | m4trace:configure.ac:4: -1- m4_pattern_allow([^includedir$]) 41 | m4trace:configure.ac:4: -1- m4_pattern_allow([^oldincludedir$]) 42 | m4trace:configure.ac:4: -1- m4_pattern_allow([^docdir$]) 43 | m4trace:configure.ac:4: -1- m4_pattern_allow([^infodir$]) 44 | m4trace:configure.ac:4: -1- m4_pattern_allow([^htmldir$]) 45 | m4trace:configure.ac:4: -1- m4_pattern_allow([^dvidir$]) 46 | m4trace:configure.ac:4: -1- m4_pattern_allow([^pdfdir$]) 47 | m4trace:configure.ac:4: -1- m4_pattern_allow([^psdir$]) 48 | m4trace:configure.ac:4: -1- m4_pattern_allow([^libdir$]) 49 | m4trace:configure.ac:4: -1- m4_pattern_allow([^localedir$]) 50 | m4trace:configure.ac:4: -1- m4_pattern_allow([^mandir$]) 51 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_NAME$]) 52 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_TARNAME$]) 53 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_VERSION$]) 54 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_STRING$]) 55 | m4trace:configure.ac:4: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$]) 56 | m4trace:configure.ac:4: -1- m4_pattern_allow([^DEFS$]) 57 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_C$]) 58 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_N$]) 59 | m4trace:configure.ac:4: -1- m4_pattern_allow([^ECHO_T$]) 60 | m4trace:configure.ac:4: -1- m4_pattern_allow([^LIBS$]) 61 | m4trace:configure.ac:4: -1- m4_pattern_allow([^build_alias$]) 62 | m4trace:configure.ac:4: -1- m4_pattern_allow([^host_alias$]) 63 | m4trace:configure.ac:4: -1- m4_pattern_allow([^target_alias$]) 64 | m4trace:configure.ac:12: -1- LLVM_CONFIG_PROJECT([$LLVM_SRC_ROOT], [$LLVM_OBJ_ROOT]) 65 | m4trace:configure.ac:12: -1- m4_pattern_allow([^LLVM_SRC$]) 66 | m4trace:configure.ac:12: -1- m4_pattern_allow([^LLVM_OBJ$]) 67 | m4trace:configure.ac:26: -1- AC_CONFIG_MAKEFILE([Makefile]) 68 | m4trace:configure.ac:27: -1- AC_CONFIG_MAKEFILE([lib/Makefile]) 69 | m4trace:configure.ac:28: -1- AC_CONFIG_MAKEFILE([runtime/Makefile]) 70 | m4trace:configure.ac:29: -1- AC_CONFIG_MAKEFILE([test/Makefile]) 71 | m4trace:configure.ac:73: -2- m4_pattern_allow([^poolallocsrcdir$]) 72 | m4trace:configure.ac:75: -2- m4_pattern_allow([^poolallocsrcdir$]) 73 | m4trace:configure.ac:80: -2- m4_pattern_allow([^poolallocobjdir$]) 74 | m4trace:configure.ac:82: -2- m4_pattern_allow([^poolallocobjdir$]) 75 | m4trace:configure.ac:88: -2- m4_pattern_allow([^testsrcdir$]) 76 | m4trace:configure.ac:90: -2- m4_pattern_allow([^testsrcdir$]) 77 | m4trace:configure.ac:95: -2- m4_pattern_allow([^testobjdir$]) 78 | m4trace:configure.ac:97: -2- m4_pattern_allow([^testobjdir$]) 79 | m4trace:configure.ac:110: -1- m4_pattern_allow([^LIB@&t@OBJS$]) 80 | m4trace:configure.ac:110: -1- m4_pattern_allow([^LTLIBOBJS$]) 81 | -------------------------------------------------------------------------------- /autoconf/configure.ac: -------------------------------------------------------------------------------- 1 | dnl ************************************************************************** 2 | dnl * Initialize 3 | dnl ************************************************************************** 4 | AC_INIT([[[llvm-deps]]],[[[0.00]]],[sdmoore@fas.harvard.edu]) 5 | 6 | dnl Identify where LLVM source tree is 7 | LLVM_SRC_ROOT="`(cd $srcdir/../..; pwd)`" 8 | LLVM_OBJ_ROOT="`(cd ../..; pwd)`" 9 | 10 | dnl Tell autoconf that this is an LLVM project being configured 11 | dnl This provides the --with-llvmsrc and --with-llvmobj options 12 | LLVM_CONFIG_PROJECT($LLVM_SRC_ROOT,$LLVM_OBJ_ROOT) 13 | 14 | dnl Tell autoconf that the auxilliary files are actually located in 15 | dnl the LLVM autoconf directory, not here. 16 | AC_CONFIG_AUX_DIR($LLVM_SRC/autoconf) 17 | 18 | dnl Verify that the source directory is valid 19 | AC_CONFIG_SRCDIR(["Makefile.common.in"]) 20 | 21 | dnl Configure a common Makefile 22 | AC_CONFIG_FILES(Makefile.common) 23 | 24 | dnl Configure project makefiles 25 | dnl List every Makefile that exists within your source tree 26 | AC_CONFIG_MAKEFILE(Makefile) 27 | AC_CONFIG_MAKEFILE(lib/Makefile) 28 | AC_CONFIG_MAKEFILE(runtime/Makefile) 29 | AC_CONFIG_MAKEFILE(test/Makefile) 30 | 31 | dnl ************************************************************************** 32 | dnl * Determine which system we are building on 33 | dnl ************************************************************************** 34 | 35 | dnl ************************************************************************** 36 | dnl * Check for programs. 37 | dnl ************************************************************************** 38 | 39 | dnl ************************************************************************** 40 | dnl * Check for libraries. 41 | dnl ************************************************************************** 42 | 43 | dnl Check for GNU GMP 44 | #AC_CHECK_LIB(gmp, __gmpz_init) 45 | 46 | dnl Check for CVC3 47 | #AC_CHECK_LIB(cvc3, vc_get_error_status,[],[],[-lgmp -lstdc++]) 48 | 49 | dnl ************************************************************************** 50 | dnl * Checks for header files. 51 | dnl ************************************************************************** 52 | 53 | dnl ************************************************************************** 54 | dnl * Checks for typedefs, structures, and compiler characteristics. 55 | dnl ************************************************************************** 56 | 57 | dnl ************************************************************************** 58 | dnl * Checks for library functions. 59 | dnl ************************************************************************** 60 | 61 | dnl ************************************************************************** 62 | dnl * Enable various compile-time options 63 | dnl ************************************************************************** 64 | 65 | dnl ************************************************************************** 66 | dnl * Set the location of various third-party software packages 67 | dnl ************************************************************************** 68 | 69 | dnl Specify the location of the llvm-poolalloc project 70 | AC_ARG_WITH(poolalloc-srcdir, 71 | AS_HELP_STRING([--with-poolalloc-srcdir], 72 | [Specify location of Pool Allocation source code]), 73 | AC_SUBST(poolallocsrcdir,"$withval"), 74 | AC_SUBST(poolallocsrcdir,"$LLVM_SRC_ROOT/projects/poolalloc" 75 | )) 76 | 77 | AC_ARG_WITH(poolalloc-objdir, 78 | AS_HELP_STRING([--with-poolalloc-objdir], 79 | [Specify location of Pool Allocation object code]), 80 | AC_SUBST(poolallocobjdir,"$withval"), 81 | AC_SUBST(poolallocobjdir,"$LLVM_OBJ_ROOT/projects/poolalloc" 82 | )) 83 | 84 | dnl Specify the location of the LLVM Test Suite 85 | AC_ARG_WITH(test-srcdir, 86 | AS_HELP_STRING([--with-test-srcdir], 87 | [Specify location of LLVM Test Suite source code]), 88 | AC_SUBST(testsrcdir,"$withval"), 89 | AC_SUBST(testsrcdir,"$LLVM_SRC_ROOT/projects/test-suite" 90 | )) 91 | 92 | AC_ARG_WITH(test-objdir, 93 | AS_HELP_STRING([--with-test-objdir], 94 | [Specify location of LLVM Test Suite object code]), 95 | AC_SUBST(testobjdir,"$withval"), 96 | AC_SUBST(testobjdir,"$LLVM_OBJ_ROOT/projects/test-suite" 97 | )) 98 | 99 | dnl Ensure that all pathnames are absolute pathnames 100 | poolallocsrcdir=`cd $poolallocsrcdir; pwd` 101 | poolallocobjdir=`cd $poolallocobjdir; pwd` 102 | testsrcdir=`cd $testsrcdir; pwd` 103 | testobjdir=`cd $testobjdir; pwd` 104 | 105 | dnl ************************************************************************** 106 | dnl * Create the output files 107 | dnl ************************************************************************** 108 | 109 | dnl AC_CONFIG_HEADERS(include/deps/config.h) 110 | AC_OUTPUT 111 | -------------------------------------------------------------------------------- /autoconf/install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5 (mit/util/scripts/install.sh). 5 | # 6 | # Copyright 1991 by the Massachusetts Institute of Technology 7 | # 8 | # Permission to use, copy, modify, distribute, and sell this software and its 9 | # documentation for any purpose is hereby granted without fee, provided that 10 | # the above copyright notice appear in all copies and that both that 11 | # copyright notice and this permission notice appear in supporting 12 | # documentation, and that the name of M.I.T. not be used in advertising or 13 | # publicity pertaining to distribution of the software without specific, 14 | # written prior permission. M.I.T. makes no representations about the 15 | # suitability of this software for any purpose. It is provided "as is" 16 | # without express or implied warranty. 17 | # 18 | # Calling this script install-sh is preferred over install.sh, to prevent 19 | # `make' implicit rules from creating a file called install from it 20 | # when there is no Makefile. 21 | # 22 | # This script is compatible with the BSD install script, but was written 23 | # from scratch. It can only install one file at a time, a restriction 24 | # shared with many OS's install programs. 25 | 26 | 27 | # set DOITPROG to echo to test this script 28 | 29 | # Don't use :- since 4.3BSD and earlier shells don't like it. 30 | doit="${DOITPROG-}" 31 | 32 | 33 | # put in absolute paths if you don't have them in your path; or use env. vars. 34 | 35 | mvprog="${MVPROG-mv}" 36 | cpprog="${CPPROG-cp}" 37 | chmodprog="${CHMODPROG-chmod}" 38 | chownprog="${CHOWNPROG-chown}" 39 | chgrpprog="${CHGRPPROG-chgrp}" 40 | stripprog="${STRIPPROG-strip}" 41 | rmprog="${RMPROG-rm}" 42 | mkdirprog="${MKDIRPROG-mkdir}" 43 | 44 | transformbasename="" 45 | transform_arg="" 46 | instcmd="$mvprog" 47 | chmodcmd="$chmodprog 0755" 48 | chowncmd="" 49 | chgrpcmd="" 50 | stripcmd="" 51 | rmcmd="$rmprog -f" 52 | mvcmd="$mvprog" 53 | src="" 54 | dst="" 55 | dir_arg="" 56 | 57 | while [ x"$1" != x ]; do 58 | case $1 in 59 | -c) instcmd="$cpprog" 60 | shift 61 | continue;; 62 | 63 | -d) dir_arg=true 64 | shift 65 | continue;; 66 | 67 | -m) chmodcmd="$chmodprog $2" 68 | shift 69 | shift 70 | continue;; 71 | 72 | -o) chowncmd="$chownprog $2" 73 | shift 74 | shift 75 | continue;; 76 | 77 | -g) chgrpcmd="$chgrpprog $2" 78 | shift 79 | shift 80 | continue;; 81 | 82 | -s) stripcmd="$stripprog" 83 | shift 84 | continue;; 85 | 86 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 87 | shift 88 | continue;; 89 | 90 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 91 | shift 92 | continue;; 93 | 94 | *) if [ x"$src" = x ] 95 | then 96 | src=$1 97 | else 98 | # this colon is to work around a 386BSD /bin/sh bug 99 | : 100 | dst=$1 101 | fi 102 | shift 103 | continue;; 104 | esac 105 | done 106 | 107 | if [ x"$src" = x ] 108 | then 109 | echo "install: no input file specified" 110 | exit 1 111 | else 112 | : 113 | fi 114 | 115 | if [ x"$dir_arg" != x ]; then 116 | dst=$src 117 | src="" 118 | 119 | if [ -d $dst ]; then 120 | instcmd=: 121 | chmodcmd="" 122 | else 123 | instcmd=$mkdirprog 124 | fi 125 | else 126 | 127 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 128 | # might cause directories to be created, which would be especially bad 129 | # if $src (and thus $dsttmp) contains '*'. 130 | 131 | if [ -f $src -o -d $src ] 132 | then 133 | : 134 | else 135 | echo "install: $src does not exist" 136 | exit 1 137 | fi 138 | 139 | if [ x"$dst" = x ] 140 | then 141 | echo "install: no destination specified" 142 | exit 1 143 | else 144 | : 145 | fi 146 | 147 | # If destination is a directory, append the input filename; if your system 148 | # does not like double slashes in filenames, you may need to add some logic 149 | 150 | if [ -d $dst ] 151 | then 152 | dst="$dst"/`basename $src` 153 | else 154 | : 155 | fi 156 | fi 157 | 158 | ## this sed command emulates the dirname command 159 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 160 | 161 | # Make sure that the destination directory exists. 162 | # this part is taken from Noah Friedman's mkinstalldirs script 163 | 164 | # Skip lots of stat calls in the usual case. 165 | if [ ! -d "$dstdir" ]; then 166 | defaultIFS=' 167 | ' 168 | IFS="${IFS-${defaultIFS}}" 169 | 170 | oIFS="${IFS}" 171 | # Some sh's can't handle IFS=/ for some reason. 172 | IFS='%' 173 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 174 | IFS="${oIFS}" 175 | 176 | pathcomp='' 177 | 178 | while [ $# -ne 0 ] ; do 179 | pathcomp="${pathcomp}${1}" 180 | shift 181 | 182 | if [ ! -d "${pathcomp}" ] ; 183 | then 184 | $mkdirprog "${pathcomp}" 185 | else 186 | : 187 | fi 188 | 189 | pathcomp="${pathcomp}/" 190 | done 191 | fi 192 | 193 | if [ x"$dir_arg" != x ] 194 | then 195 | $doit $instcmd $dst && 196 | 197 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && 198 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && 199 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && 200 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi 201 | else 202 | 203 | # If we're going to rename the final executable, determine the name now. 204 | 205 | if [ x"$transformarg" = x ] 206 | then 207 | dstfile=`basename $dst` 208 | else 209 | dstfile=`basename $dst $transformbasename | 210 | sed $transformarg`$transformbasename 211 | fi 212 | 213 | # don't allow the sed command to completely eliminate the filename 214 | 215 | if [ x"$dstfile" = x ] 216 | then 217 | dstfile=`basename $dst` 218 | else 219 | : 220 | fi 221 | 222 | # Make a temp file name in the proper directory. 223 | 224 | dsttmp=$dstdir/#inst.$$# 225 | 226 | # Move or copy the file name to the temp name 227 | 228 | $doit $instcmd $src $dsttmp && 229 | 230 | trap "rm -f ${dsttmp}" 0 && 231 | 232 | # and set any options; do chmod last to preserve setuid bits 233 | 234 | # If any of these fail, we abort the whole thing. If we want to 235 | # ignore errors from any of these, just make sure not to ignore 236 | # errors from the above "$doit $instcmd $src $dsttmp" command. 237 | 238 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && 239 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && 240 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && 241 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && 242 | 243 | # Now rename the file to the real destination. 244 | 245 | $doit $rmcmd -f $dstdir/$dstfile && 246 | $doit $mvcmd $dsttmp $dstdir/$dstfile 247 | 248 | fi && 249 | 250 | 251 | exit 0 252 | -------------------------------------------------------------------------------- /autoconf/mkinstalldirs: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | # Author: Noah Friedman 4 | # Created: 1993-05-16 5 | # Public domain 6 | 7 | # $Id: mkinstalldirs,v 1.2 2005-11-09 01:45:54 dhurjati Exp $ 8 | 9 | errstatus=0 10 | dirmode="" 11 | 12 | usage="\ 13 | Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." 14 | 15 | # process command line arguments 16 | while test $# -gt 0 ; do 17 | case "${1}" in 18 | -h | --help | --h* ) # -h for help 19 | echo "${usage}" 1>&2; exit 0 ;; 20 | -m ) # -m PERM arg 21 | shift 22 | test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } 23 | dirmode="${1}" 24 | shift ;; 25 | -- ) shift; break ;; # stop option processing 26 | -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option 27 | * ) break ;; # first non-opt arg 28 | esac 29 | done 30 | 31 | for file 32 | do 33 | if test -d "$file"; then 34 | shift 35 | else 36 | break 37 | fi 38 | done 39 | 40 | case $# in 41 | 0) exit 0 ;; 42 | esac 43 | 44 | case $dirmode in 45 | '') 46 | if mkdir -p -- . 2>/dev/null; then 47 | echo "mkdir -p -- $*" 48 | exec mkdir -p -- "$@" 49 | fi ;; 50 | *) 51 | if mkdir -m "$dirmode" -p -- . 2>/dev/null; then 52 | echo "mkdir -m $dirmode -p -- $*" 53 | exec mkdir -m "$dirmode" -p -- "$@" 54 | fi ;; 55 | esac 56 | 57 | for file 58 | do 59 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` 60 | shift 61 | 62 | pathcomp= 63 | for d 64 | do 65 | pathcomp="$pathcomp$d" 66 | case "$pathcomp" in 67 | -* ) pathcomp=./$pathcomp ;; 68 | esac 69 | 70 | if test ! -d "$pathcomp"; then 71 | echo "mkdir $pathcomp" 72 | 73 | mkdir "$pathcomp" || lasterr=$? 74 | 75 | if test ! -d "$pathcomp"; then 76 | errstatus=$lasterr 77 | else 78 | if test ! -z "$dirmode"; then 79 | echo "chmod $dirmode $pathcomp" 80 | 81 | lasterr="" 82 | chmod "$dirmode" "$pathcomp" || lasterr=$? 83 | 84 | if test ! -z "$lasterr"; then 85 | errstatus=$lasterr 86 | fi 87 | fi 88 | fi 89 | fi 90 | 91 | pathcomp="$pathcomp/" 92 | done 93 | done 94 | 95 | exit $errstatus 96 | 97 | # Local Variables: 98 | # mode: shell-script 99 | # sh-indentation: 3 100 | # End: 101 | # mkinstalldirs ends here 102 | -------------------------------------------------------------------------------- /include/CallContext.h: -------------------------------------------------------------------------------- 1 | //===-- CallContext.h -------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Defines ContextManager for uniqueing and generating opaque ContextID's, 11 | // as well as myriad of Context types to use with CallSensitiveAnalysisPass. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef CALLCONTEXT_H 16 | #define CALLCONTEXT_H 17 | 18 | #include "llvm/Support/CallSite.h" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace llvm { 25 | 26 | // ContextManage - 27 | // Provide lightweight canonical reference's to Context objects. 28 | // Goal is to abstract away which Context type is being used, 29 | // as well as make them cheap to copy spuriously. 30 | // Similar to LLVM's FoldingSet. 31 | typedef uintptr_t ContextID; 32 | // DefaultID - Special-case (what ContextID zero-init's to) 33 | // that is used to respresent an empty context. 34 | static const ContextID DefaultID = 0; 35 | template 36 | class ContextManager { 37 | public: 38 | 39 | // getIDFor - Return a canonical ContextID for the given Context 40 | ContextID getIDFor(C & c) { 41 | // Try to find a match in our set of contexts... 42 | typename CSet::iterator I = Contexts.find((ContextID)&c); 43 | // If we don't already have on like this, add a copy 44 | if (I == Contexts.end()) { 45 | I = Contexts.insert((ContextID)new C(c)).first; 46 | } 47 | // Return the reference to the canonical object 48 | return *I; 49 | } 50 | 51 | // getContextFor - Return the Context object corresponding to the given ID 52 | const C & getContextFor(ContextID ID) const { 53 | // Special-case for 'default' ContextIDs 54 | if (ID == DefaultID) return initial; 55 | 56 | // Otherwise just return what the ID points to 57 | assert(Contexts.count(ID)); 58 | return *(C*)ID; 59 | } 60 | 61 | // Free all allocated context objects 62 | void clear() { 63 | for(typename CSet::iterator I = Contexts.begin(), E = Contexts.end(); 64 | I != E; ++I) 65 | delete (C*)*I; 66 | Contexts.clear(); 67 | } 68 | 69 | // Destructor 70 | ~ContextManager() { 71 | clear(); 72 | } 73 | 74 | private: 75 | // Comparator type, compares the ID's by comparing their dereferenced values 76 | struct CompareID { 77 | bool operator()(const ContextID &A, const ContextID &B) const { 78 | return *(C*)A < *(C*)B; 79 | } 80 | }; 81 | 82 | typedef std::set CSet; 83 | CSet Contexts; 84 | C initial; 85 | }; 86 | 87 | // Context types: 88 | 89 | class CallerContext { 90 | /// CallerContext is a thin wrapper around stl's deque with 91 | /// a custom < operator to support using CallerContext's 92 | /// as keys in a map. 93 | typedef std::deque callers_type; 94 | public: 95 | /// CallerContext's are ordered by lexicographical comparison 96 | /// over the deque of functions. 97 | bool operator<(const CallerContext & that) const { 98 | return std::lexicographical_compare(callers.begin(), callers.end(), 99 | that.callers.begin(), 100 | that.callers.end()); 101 | } 102 | 103 | void push_back(const ImmutableCallSite &cs) { 104 | callers.push_back(cs.getInstruction()->getParent()->getParent()); 105 | } 106 | size_t size() const { return callers.size(); } 107 | void pop_front() { callers.pop_front(); } 108 | void dump() const; 109 | 110 | private: 111 | callers_type callers; 112 | }; 113 | 114 | class CallSiteContext { 115 | /// CallSiteContext is a thin wrapper around stl's deque with 116 | /// a custom < operator to support using CallSiteContext's 117 | /// as keys in a map. 118 | typedef std::deque sites_type; 119 | public: 120 | /// CallSiteContext's are ordered by lexicographical comparison 121 | /// over the deque of callsites, using the instruction 122 | /// address for CallSite comparison. 123 | static bool compareCS(const ImmutableCallSite & LHS, 124 | const ImmutableCallSite & RHS) { 125 | return LHS.getInstruction() < RHS.getInstruction(); 126 | } 127 | bool operator<(const CallSiteContext & that) const { 128 | return std::lexicographical_compare(sites.begin(), sites.end(), 129 | that.sites.begin(), 130 | that.sites.end(),compareCS); 131 | } 132 | 133 | void push_back(const ImmutableCallSite &cs) { sites.push_back(cs); } 134 | size_t size() const { return sites.size(); } 135 | void pop_front() { sites.pop_front(); } 136 | void dump() const; 137 | 138 | private: 139 | sites_type sites; 140 | }; 141 | 142 | } 143 | 144 | #endif // CALLCONTEXT_H 145 | -------------------------------------------------------------------------------- /include/CallSensitiveAnalysisPass.h: -------------------------------------------------------------------------------- 1 | //===-- CallSensitiveAnalysisPass.h -----------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the CallSensitiveAnalysisPass template, which extends the 11 | // InterProcAnalysisPass template to implement a k-callsite sensitive 12 | // interprocedural analysis. 13 | // 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef CALLSENSITIVEANALYSISPASS_H_ 17 | #define CALLSENSITIVEANALYSISPASS_H_ 18 | 19 | #include "CallContext.h" 20 | #include "InterProcAnalysisPass.h" 21 | 22 | #include "llvm/Support/raw_ostream.h" 23 | #include "llvm/IntrinsicInst.h" 24 | 25 | #include "dsa/DSGraph.h" 26 | 27 | namespace llvm { 28 | 29 | /// CallSensitiveAnalysisPass can be extended to implement a k-callsite 30 | /// sensitive interprocedural analysis. The parameters to the template 31 | /// are an input and output type for the user's analysis and a non-negative 32 | /// integer k. 33 | /// 34 | /// The input and output types must implement the operators for 35 | /// <=, ==, and !=, and be default constructible. 36 | /// Furthermore, each should implement: 37 | /// const T upperBound(const T & other) const 38 | /// Where the output should be the join of the instances. 39 | template 40 | class CallSensitiveAnalysisPass : 41 | public InterProcAnalysisPass { 42 | public: 43 | typedef AnalysisUnit AUnitType; 44 | 45 | explicit CallSensitiveAnalysisPass(char &pid, bool collapseExtContext, bool collapseIndContext) : 46 | InterProcAnalysisPass(pid), 47 | collapseInd(collapseIndContext), collapseExt(collapseExtContext) { } 48 | 49 | 50 | /// bottomInput - This method should be implemented by the subclass as the 51 | /// initial input to use for each analysis unit. It should represent the 52 | /// "bottom" element of the p.o. of inputs 53 | virtual const I bottomInput() const = 0; 54 | /// bottomOutput - This method should be implemented by the subclass as the 55 | /// initial output to use for each analysis unit. It should represent the 56 | /// "bottom" element of the p.o. of summaries 57 | virtual const O bottomOutput() const = 0; 58 | 59 | /// runOnContext - This method should be implemented by the subclass to 60 | /// perform the desired analysis on the current analysis unit. 61 | virtual const O runOnContext(const AUnitType unit, const I input) = 0; 62 | /// signatureForExternalCall - This method should be implemented by the 63 | /// subclass to provide analysis results for calls that cannot be analysed 64 | /// directly. 65 | virtual const O signatureForExternalCall(const ImmutableCallSite & cs, const I input) = 0; 66 | 67 | bool functionIsCallable(const ImmutableCallSite &cs, const Function *F) { 68 | // If we don't have enough actual arguments, invalid callee 69 | if (cs.arg_size() < F->arg_size()) return false; 70 | // And for non-vararg we need exact argument match 71 | if (!F->isVarArg() && (cs.arg_size() != F->arg_size())) return false; 72 | 73 | // Otherwise use DSA's filtering 74 | return llvm::functionIsCallable(cs, F); 75 | } 76 | 77 | /// getCallResult - Analyzes all possible callees and returns a summary 78 | /// by joining their analysis results. 79 | virtual const O getCallResult(const ImmutableCallSite & cs, const I input) { 80 | // if the call is an intrinsic, jump straight to using a signature 81 | if (isa(cs.getInstruction())) { 82 | return signatureForExternalCall(cs, input); 83 | } 84 | 85 | // Compute what context callee's should be analyzed in. 86 | ContextID newContext = updateContext(this->getCurrentContext(), cs); 87 | 88 | // Fast-path direct calls 89 | if (const Function *F = cs.getCalledFunction()) { 90 | if (!F->isDeclaration()) { 91 | return this->getAnalysisResult(AUnitType(newContext, *F), input); 92 | } else { 93 | return signatureForExternalCall(cs, input); 94 | } 95 | } 96 | 97 | // FIXME: Why does this need explicit instantiation? 98 | const CallGraph & cg = this->template getAnalysis(); 99 | const CallGraphNode *caller = cg[cs.getCaller()]; 100 | 101 | // Query the call graph for callees of the given call site. 102 | std::set callees; 103 | for (CallGraphNode::const_iterator rec = caller->begin(), end = caller->end(); 104 | rec != end; ++rec) { 105 | if (rec->first == (const Value*)cs.getInstruction()) { 106 | callees.insert(rec->second); 107 | } 108 | } 109 | 110 | typedef std::set::const_iterator CGNIterator; 111 | 112 | O output = bottomOutput(); 113 | bool addExternalCallingNodes = false; 114 | bool useExternalSignature = false; 115 | 116 | ContextID indirectContext = 117 | collapseInd ? updateIndirectContext(this->getCurrentContext(), cs) : newContext; 118 | ContextID externalContext = 119 | collapseExt ? updateIndirectContext(this->getCurrentContext(), cs) : newContext; 120 | 121 | // For each callee, determine whether it's a function we have code for, 122 | // an indirect call, or an external function (which we will need a 123 | // signature for). 124 | for (CGNIterator callee = callees.begin(), end = callees.end(); 125 | callee != end; ++callee) { 126 | const Function *function = (*callee)->getFunction(); 127 | if (function) { 128 | if (!functionIsCallable(cs, function)) continue; 129 | // The callee is a function in the module 130 | // If we have code, request analysis and add it to the output 131 | // otherwise use a signature 132 | if (!function->isDeclaration()) { 133 | AUnitType unit = AUnitType(indirectContext, *function); 134 | output = output.upperBound(this->getAnalysisResult(unit, input)); 135 | } else { 136 | useExternalSignature = true; 137 | } 138 | } else { 139 | // The callee is either indirect or to an external function 140 | // TODO: Revisit handling of these calls 141 | if (*callee == cg.getCallsExternalNode()) { 142 | // Call to an external function: use a signature 143 | useExternalSignature = true; 144 | } else { 145 | // Indirect call, could call any function external calling node can call 146 | assert(*callee == cg.getExternalCallingNode()); 147 | addExternalCallingNodes = true; 148 | } 149 | } 150 | } 151 | 152 | // If the call is indirect, we need to add the analysis result for any 153 | // function the call graph tells us it could invoke. 154 | if (addExternalCallingNodes) { 155 | 156 | for (CallGraphNode::iterator callee = cg.getExternalCallingNode()->begin(), 157 | end = cg.getExternalCallingNode()->end(); 158 | callee != end; ++callee) { 159 | const Function *function = callee->second->getFunction(); 160 | if (!functionIsCallable(cs, function)) continue; 161 | // If we have code, analyze it, otherwise use a signature 162 | if (!function->isDeclaration()) { 163 | AUnitType unit = AUnitType(externalContext, *function); 164 | output = output.upperBound(this->getAnalysisResult(unit, input)); 165 | } else { 166 | useExternalSignature = true; 167 | } 168 | } 169 | } 170 | 171 | // If we call any declarations, use signature for this callsite 172 | // This only needs to be done once, since we don't specify callee. 173 | if (useExternalSignature) 174 | output = output.upperBound(signatureForExternalCall(cs, input)); 175 | 176 | return output; 177 | } 178 | 179 | /// invokableCode - returns a set of function pointers to code that could 180 | /// be analyzed by calling getCallResult(). 181 | /// XXX Hacky... should refactor so that we don't have to keep this code 182 | /// in sink with getCallResult... 183 | virtual std::set > invokableCode(const ImmutableCallSite & cs) { 184 | 185 | ContextID newContext = updateContext(this->getCurrentContext(), cs); 186 | ContextID indirectContext = 187 | collapseInd ? updateIndirectContext(this->getCurrentContext(), cs) : newContext; 188 | ContextID externalContext = 189 | collapseExt ? updateIndirectContext(this->getCurrentContext(), cs) : newContext; 190 | 191 | // Fast-path direct calls 192 | if (const Function *F = cs.getCalledFunction()) { 193 | std::set > single; 194 | if (!F->isDeclaration()) 195 | single.insert(std::pair(F,newContext)); 196 | return single; 197 | } 198 | 199 | std::set > callees; 200 | 201 | // FIXME: Why does this need explicit instantiation? 202 | const CallGraph & cg = this->template getAnalysis(); 203 | const CallGraphNode *caller = cg[cs.getCaller()]; 204 | 205 | // Query the call graph for callees of the given call site. 206 | std::set calleeGraphNodes; 207 | for (CallGraphNode::const_iterator rec = caller->begin(), end = caller->end(); 208 | rec != end; ++rec) { 209 | if (rec->first == (const Value*)cs.getInstruction()) { 210 | calleeGraphNodes.insert(rec->second); 211 | } 212 | } 213 | 214 | typedef std::set::const_iterator CGNIterator; 215 | bool addExternalCallingNodes = false; 216 | 217 | // For each callee, determine whether it's a function we have code for, 218 | // an indirect call, or an external function (which we will need a 219 | // signature for). 220 | for (CGNIterator callee = calleeGraphNodes.begin(), end = calleeGraphNodes.end(); 221 | callee != end; ++callee) { 222 | const Function *function = (*callee)->getFunction(); 223 | if (function) { 224 | if (!functionIsCallable(cs, function)) continue; 225 | // The callee is a function in the module 226 | // If we have code, it would be analyzed by getCallResult() 227 | // otherwise use a signature 228 | if (!function->isDeclaration()) { 229 | callees.insert(std::pair(function,indirectContext)); 230 | } else { 231 | // The callee is either indirect or to an external function 232 | if (*callee == cg.getExternalCallingNode()) { 233 | // Indirect call, could call any function external calling node can call 234 | addExternalCallingNodes = true; 235 | } 236 | } 237 | } 238 | } 239 | 240 | // If the call is indirect, so we will add the analysis result for any 241 | // function the call graph tells us it could invoke (that we have code for) 242 | if (addExternalCallingNodes) { 243 | for (CallGraphNode::iterator callee = cg.getExternalCallingNode()->begin(), 244 | end = cg.getExternalCallingNode()->end(); 245 | callee != end; ++callee) { 246 | const Function *function = callee->second->getFunction(); 247 | if (!functionIsCallable(cs, function)) continue; 248 | if (!function->isDeclaration()) { 249 | callees.insert(std::pair(function,externalContext)); 250 | } 251 | } 252 | } 253 | 254 | return callees; 255 | } 256 | 257 | virtual bool usesExternalSignature(const ImmutableCallSite &cs) { 258 | // XXX Hacked copy of getCallResult to figure out when we should... 259 | // if the call is an intrinsic, jump straight to using a signature 260 | if (isa(cs.getInstruction())) { 261 | return true; 262 | } 263 | 264 | // Fast-path direct calls 265 | if (const Function *F = cs.getCalledFunction()) { 266 | if (F->isDeclaration()) { 267 | return true; 268 | } 269 | } else { 270 | // FIXME: Why does this need explicit instantiation? 271 | const CallGraph & cg = this->template getAnalysis(); 272 | const CallGraphNode *caller = cg[cs.getCaller()]; 273 | 274 | // Query the call graph for callees of the given call site. 275 | std::set callees; 276 | for (CallGraphNode::const_iterator rec = caller->begin(), end = caller->end(); 277 | rec != end; ++rec) { 278 | if (rec->first == (const Value*)cs.getInstruction()) { 279 | callees.insert(rec->second); 280 | } 281 | } 282 | 283 | typedef std::set::const_iterator CGNIterator; 284 | 285 | bool addExternalCallingNodes = false; 286 | 287 | // For each callee, determine whether it's a function we have code for, 288 | // an indirect call, or an external function (which we will need a 289 | // signature for). 290 | for (CGNIterator callee = callees.begin(), end = callees.end(); 291 | callee != end; ++callee) { 292 | const Function *function = (*callee)->getFunction(); 293 | if (function) { 294 | if (!functionIsCallable(cs, function)) continue; 295 | // The callee is a function in the module 296 | // If we have code, request analysis and add it to the output 297 | // otherwise use a signature 298 | if (function->isDeclaration()) { 299 | return true; 300 | } 301 | } else { 302 | // The callee is either indirect or to an external function 303 | // TODO: Revisit handling of these calls 304 | if (*callee == cg.getCallsExternalNode()) { 305 | // Call to an external function: use a signature 306 | return true; 307 | } else { 308 | // Indirect call, could call any function external calling node can call 309 | assert(*callee == cg.getExternalCallingNode()); 310 | addExternalCallingNodes = true; 311 | } 312 | } 313 | } 314 | 315 | // If the call is indirect, we need to add the analysis result for any 316 | // function the call graph tells us it could invoke. 317 | if (addExternalCallingNodes) { 318 | for (CallGraphNode::iterator callee = cg.getExternalCallingNode()->begin(), 319 | end = cg.getExternalCallingNode()->end(); 320 | callee != end; ++callee) { 321 | const Function *function = callee->second->getFunction(); 322 | if (!functionIsCallable(cs, function)) continue; 323 | // If we have code, analyze it, otherwise use a signature 324 | if (function->isDeclaration()) { 325 | return true; 326 | } 327 | } 328 | } 329 | } 330 | return false; 331 | } 332 | 333 | 334 | /// The default initialContext is empty (the caller is the OS or an external 335 | /// process--there is no call hierarchy yet). 336 | ContextID initialContext(const Function &) { 337 | return DefaultID; 338 | } 339 | 340 | /// To update a CallSiteContext, add the new call site to the list of call sites. 341 | /// If there are more than K callsites in the list, drop the oldest. 342 | ContextID updateContext(const ContextID c, const ImmutableCallSite &cs) { 343 | C newContext = CM.getContextFor(c); 344 | newContext.push_back(cs); 345 | while (newContext.size() > K) { 346 | newContext.pop_front(); 347 | } 348 | return CM.getIDFor(newContext); 349 | } 350 | 351 | ContextID updateIndirectContext(const ContextID c, const ImmutableCallSite &cs) { 352 | return DefaultID; 353 | } 354 | 355 | /// getAnalysisUsage - Derived methods must call this implementation. 356 | virtual void getAnalysisUsage(AnalysisUsage &Info) const { 357 | InterProcAnalysisPass::getAnalysisUsage(Info); 358 | } 359 | 360 | protected: 361 | ContextManager CM; 362 | private: 363 | bool collapseInd; 364 | bool collapseExt; 365 | }; 366 | 367 | } 368 | 369 | #endif /* CALLSENSITIVEANALYSISPASS_H_ */ 370 | -------------------------------------------------------------------------------- /include/Constraints/ConstraintKit.h: -------------------------------------------------------------------------------- 1 | //===- constraints/ConstraintKit.h - Constraint Solver Interface *- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares a simple abstract interface for an information flow 11 | // constraint solver. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef CONSTRAINTKIT_H_ 16 | #define CONSTRAINTKIT_H_ 17 | 18 | #include "Constraints/DepsTypes.h" 19 | #include 20 | #include 21 | 22 | namespace deps { 23 | 24 | class ConsVar; 25 | 26 | /// Interface for elements that can appear in constraints. 27 | class ConsElem { 28 | public: 29 | /// Compare two elements for constraint satisfaction 30 | virtual bool leq(const ConsElem &elem) const = 0; 31 | virtual void variables(std::set &) const = 0; 32 | virtual bool operator== (const ConsElem &elem) const = 0; 33 | 34 | /// Support for llvm-style RTTI (isa<>, dyn_cast<>, etc.) 35 | virtual DepsType type() const = 0; 36 | 37 | virtual ~ConsElem() {} 38 | }; 39 | 40 | /// Interface distinguishing constraint variables 41 | class ConsVar : public ConsElem { }; 42 | 43 | /// Interface for querying the results of solving a constraint set 44 | class ConsSoln { 45 | public: 46 | /// Substitute the given constraint element under the solution's 47 | /// environment (e.g., get the assignment of a variable) 48 | virtual const ConsElem &subst(const ConsElem&) = 0; 49 | 50 | virtual ~ConsSoln() {} 51 | }; 52 | 53 | /// Interface for creating and solving constraints problems. 54 | class ConstraintKit { 55 | public: 56 | /// Create a new constraint variable 57 | virtual const ConsVar &newVar(const std::string) = 0; 58 | /// Create a new constraint element by taking the upper bound of two 59 | /// existing elements 60 | virtual const ConsElem &upperBound(const ConsElem&, const ConsElem&) = 0; 61 | /// Create a new constraint element by taking the upper bound of two 62 | /// existing elements. Arguments and return type may be null. 63 | virtual const ConsElem *upperBound(const ConsElem *e1, const ConsElem *e2) = 0; 64 | /// Constrain the left hand side with the right hand side and put it 65 | /// in the set "kind" 66 | virtual void addConstraint(const std::string kind, const ConsElem &lhs, const ConsElem &rhs) = 0; 67 | /// Find the lfp of the constraints in the "kinds" sets (caller must delete) 68 | virtual ConsSoln *leastSolution(const std::set kinds) = 0; 69 | /// Find the gfp of the constraints in the "kinds" sets (caller must delete) 70 | virtual ConsSoln *greatestSolution(const std::set kinds) = 0; 71 | 72 | virtual ~ConstraintKit() {} 73 | }; 74 | 75 | } 76 | 77 | #endif /* CONSTRAINTKIT_H_ */ 78 | -------------------------------------------------------------------------------- /include/Constraints/DepsTypes.h: -------------------------------------------------------------------------------- 1 | //===-- DepTypes.h ----------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef DEPSTYPES_H 15 | #define DEPTSTYPES_H 16 | 17 | /// Support for llvm-style RTTI (isa<>, dyn_cast<>, etc.) 18 | namespace deps { 19 | enum DepsType { 20 | DT_LHConstant, 21 | DT_LHConsVar, 22 | DT_LHJoin 23 | }; 24 | } 25 | 26 | #endif /* DEPSTYPES_H */ 27 | -------------------------------------------------------------------------------- /include/Constraints/LHConsSoln.h: -------------------------------------------------------------------------------- 1 | //===-- LHConsSoln.h --------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LHCONSSOLN_H_ 15 | #define LHCONSSOLN_H_ 16 | 17 | #include "Constraints/ConstraintKit.h" 18 | #include "Constraints/LHConstraints.h" 19 | 20 | #include "llvm/ADT/DenseMap.h" 21 | #include "llvm/ADT/DenseSet.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace deps { 29 | 30 | class LHConstraint; 31 | class LHConstant; 32 | class LHConstraintKit; 33 | 34 | class LHConsSoln : public ConsSoln { 35 | public: 36 | LHConsSoln(LHConstraintKit & kit, const LHConstant & defaultValue, std::vector *constraints); 37 | virtual const LHConstant &subst(const ConsElem & elem); 38 | protected: 39 | LHConstraintKit &kit; 40 | 41 | const LHConstant & defaultValue; 42 | std::vector *constraints; 43 | 44 | std::deque queue; 45 | llvm::DenseSet queueSet; 46 | 47 | llvm::DenseSet changed; 48 | bool solved; 49 | 50 | void solve(void); 51 | void enqueueConstraints(const std::vector & constraints); 52 | const LHConstraint &dequeueConstraint(void); 53 | 54 | virtual ~LHConsSoln(); 55 | virtual void releaseMemory() = 0; 56 | virtual void satisfyConstraint(const LHConstraint & constraint, const ConsElem & left, const ConsElem & right) = 0; 57 | }; 58 | 59 | class LHConsGreatestSoln : public LHConsSoln { 60 | llvm::DenseMap > invalidIfDecreased; 61 | std::vector &getOrCreateInvalidIfDecreasedSet(const ConsVar *var); 62 | void addInvalidIfDecreased(const ConsVar *var, const LHConstraint *c); 63 | public: 64 | LHConsGreatestSoln(LHConstraintKit & kit, std::vector * constraints); 65 | protected: 66 | virtual void satisfyConstraint(const LHConstraint & constraint, const ConsElem & left, const ConsElem & right); 67 | virtual void releaseMemory() { 68 | invalidIfDecreased.clear(); 69 | } 70 | }; 71 | 72 | class LHConsLeastSoln : public LHConsSoln { 73 | llvm::DenseMap > invalidIfIncreased; 74 | std::vector &getOrCreateInvalidIfIncreasedSet(const ConsVar *var); 75 | void addInvalidIfIncreased(const ConsVar *var, const LHConstraint *c); 76 | public: 77 | LHConsLeastSoln(LHConstraintKit & kit, std::vector * constraints); 78 | protected: 79 | virtual void satisfyConstraint(const LHConstraint & constraint, const ConsElem & left, const ConsElem & right); 80 | virtual void releaseMemory() { 81 | invalidIfIncreased.clear(); 82 | } 83 | }; 84 | 85 | } 86 | 87 | #endif /* LHCONSSOLN_H_ */ 88 | -------------------------------------------------------------------------------- /include/Constraints/LHConstraint.h: -------------------------------------------------------------------------------- 1 | //===-- LHConstraint.h ------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LHCONSTRAINT_H_ 15 | #define LHCONSTRAINT_H_ 16 | 17 | #include "llvm/ADT/DenseMap.h" 18 | 19 | namespace deps { 20 | 21 | class ConsElem; 22 | 23 | class LHConstraint { 24 | public: 25 | LHConstraint(const ConsElem &lhs, const ConsElem &rhs) : left(&lhs), right(&rhs) {} 26 | LHConstraint(const ConsElem *lhs, const ConsElem *rhs) : left(lhs), right(rhs) {} 27 | const ConsElem & lhs() const { return *left; } 28 | const ConsElem & rhs() const { return *right; } 29 | private: 30 | const ConsElem * left; 31 | const ConsElem * right; 32 | friend struct llvm::DenseMapInfo; 33 | }; 34 | 35 | } 36 | 37 | 38 | 39 | 40 | #endif /* LHCONSTRAINT_H_ */ 41 | -------------------------------------------------------------------------------- /include/Constraints/LHConstraintKit.h: -------------------------------------------------------------------------------- 1 | //===-- constraints/LHConstraintKit.h - LH Lattice Solver -------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares a concrete constraint solver for solving constraints 11 | // over the two level lattice L-H. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef LHCONSTRAINTKIT_H_ 16 | #define LHCONSTRAINTKIT_H_ 17 | 18 | #include "Constraints/ConstraintKit.h" 19 | #include "Constraints/LHConstraint.h" 20 | 21 | #include "llvm/ADT/StringMap.h" 22 | #include "llvm/ADT/DenseSet.h" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace deps { 29 | 30 | class LHConstant; 31 | class LHConsVar; 32 | class LHJoin; 33 | class PartialSolution; 34 | 35 | /// Singleton, concrete implementation of ConstraintKit for creating and 36 | /// solving constraints over a two level lattice. 37 | class LHConstraintKit : public ConstraintKit { 38 | public: 39 | LHConstraintKit(); 40 | ~LHConstraintKit(); 41 | /// Get a reference to the constant "low" element of the lattice 42 | const ConsElem &lowConstant() const; 43 | /// Get a reference to the constant "high" element of the lattice 44 | const ConsElem &highConstant() const; 45 | /// Create a new constraint variable 46 | virtual const ConsVar &newVar(const std::string description); 47 | /// Create a new constraint element by taking the upper bound of two 48 | /// existing elements 49 | virtual const ConsElem &upperBound(const ConsElem &e1, const ConsElem &e2); 50 | /// Create a new constraint element by taking the upper bound of two 51 | /// existing elements. Arguments and return type may be null. 52 | virtual const ConsElem *upperBound(const ConsElem *e1, const ConsElem *e2); 53 | /// Create a new constraint element by taking the upper bound of the 54 | /// given set of elements. 55 | virtual const ConsElem &upperBound(std::set elems); 56 | 57 | /// Add the constraint lhs <= rhs to the set "kind" 58 | virtual void addConstraint(const std::string kind, const ConsElem &lhs, const ConsElem &rhs); 59 | /// Find the lfp of the constraints in the "kinds" sets 60 | /// Unconstrained variables will be "Low" (caller delete) 61 | virtual ConsSoln *leastSolution(const std::set kinds); 62 | /// Find the gfp of the constraints in the "kinds" sets 63 | /// Unconstrained variables will be "High" (caller delete) 64 | virtual ConsSoln *greatestSolution(const std::set kinds); 65 | 66 | // Compute both least and greatest solutions simultaneously 67 | // for the given kind. 68 | void solveMT(std::string kind); 69 | // Solve the given kinds in parallel (per thread limit) 70 | std::vector solveLeastMT(std::vector kinds, bool useDefaultSinks); 71 | private: 72 | static LHConstraintKit *singleton; 73 | llvm::StringMap > constraints; 74 | std::set lockedConstraintKinds; 75 | 76 | std::vector vars; 77 | std::set joins; 78 | 79 | // Cached solutions for each kind 80 | llvm::StringMap leastSolutions; 81 | llvm::StringMap greatestSolutions; 82 | 83 | void freeUnneededConstraints(std::string kind); 84 | 85 | std::vector &getOrCreateConstraintSet(const std::string kind); 86 | }; 87 | 88 | } 89 | 90 | #endif /* LHCONSTRAINTKIT_H_ */ 91 | -------------------------------------------------------------------------------- /include/Constraints/LHConstraints.h: -------------------------------------------------------------------------------- 1 | //===-- constraints/LHConstraints - LH Constraint Classes -------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares concrete classes of constraint elements for use with 11 | // the LHConstraintKit. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef LHCONSTRAINTS_H_ 16 | #define LHCONSTRAINTS_H_ 17 | 18 | #include "Constraints/ConstraintKit.h" 19 | #include 20 | 21 | namespace deps { 22 | 23 | /// Singleton constants in the L-H lattice (Low and High) 24 | class LHConstant : public ConsElem { 25 | public: 26 | /// Get a reference to the low constant (do not delete!) 27 | static const LHConstant &low(); 28 | /// Get a reference to the high constant (do not delete!) 29 | static const LHConstant &high(); 30 | /// Compare with another constraint element. False if element is 31 | /// not an LHConstant. 32 | virtual bool leq(const ConsElem &elem) const; 33 | /// Returns the empty set of constraint variables. 34 | virtual void variables(std::set &) const {} 35 | /// Returns the least upper bound of two members of the L-H lattice 36 | virtual const LHConstant &join(const LHConstant & other) const; 37 | virtual bool operator== (const ConsElem& c) const; 38 | 39 | /// Support for llvm-style RTTI (isa<>, dyn_cast<>, etc.) 40 | virtual DepsType type() const { return DT_LHConstant; } 41 | static inline bool classof(const LHConstant *) { return true; } 42 | static inline bool classof(const ConsElem *elem) { 43 | return elem->type() == DT_LHConstant; 44 | } 45 | protected: 46 | enum LHLevel { LOW, HIGH }; 47 | LHConstant(LHLevel level); 48 | LHConstant& operator=(const LHConstant&); 49 | 50 | const LHLevel level; 51 | static LHConstant *lowSingleton; 52 | static LHConstant *highSingleton; 53 | }; 54 | 55 | /// Concrete implementation of constraint variables for use with LHConstraintKit. 56 | class LHConsVar : public ConsVar { 57 | public: 58 | /// Create a new variable with description 59 | LHConsVar(const std::string desc); 60 | /// Compare two elements for constraint satisfaction 61 | virtual bool leq(const ConsElem &elem) const; 62 | /// Returns the singleton set containing this variable 63 | virtual void variables(std::set & set) const { 64 | set.insert(this); 65 | } 66 | virtual bool operator== (const ConsElem& c) const; 67 | 68 | /// Support for llvm-style RTTI (isa<>, dyn_cast<>, etc.) 69 | virtual DepsType type() const { return DT_LHConsVar; } 70 | static inline bool classof(const LHConsVar *) { return true; } 71 | static inline bool classof(const ConsVar *var) { return var->type() == DT_LHConsVar; } 72 | static inline bool classof(const ConsElem *elem) { return elem->type() == DT_LHConsVar; } 73 | private: 74 | LHConsVar(const LHConsVar &); 75 | LHConsVar& operator=(const LHConsVar&); 76 | const std::string desc; 77 | }; 78 | 79 | /// Constraint element representing the join of L-H lattice elements. 80 | class LHJoin : public ConsElem { 81 | public: 82 | /// Returns true if all of the elements of the join are leq(elem) 83 | virtual bool leq(const ConsElem &elem) const; 84 | /// Returns set of sub-elements that are constraint variables 85 | virtual void variables(std::set & set) const; 86 | /// Create a new constraint element by joining two existing constraints (caller delete) 87 | static const LHJoin *create(const ConsElem &e1, const ConsElem &e2); 88 | /// Returns the set of elements joined by this element 89 | const std::set & elements() const { 90 | return elems; 91 | } 92 | virtual bool operator== (const ConsElem& c) const; 93 | bool operator<(const LHJoin &c) const { 94 | if (elems.size() != c.elems.size()) 95 | return elems.size() < c.elems.size(); 96 | return elems < c.elems; 97 | } 98 | 99 | /// Support for llvm-style RTTI (isa<>, dyn_cast<>, etc.) 100 | virtual DepsType type() const { return DT_LHJoin; } 101 | static inline bool classof(const LHJoin *) { return true; } 102 | static inline bool classof(const ConsElem *elem) { return elem->type() == DT_LHJoin; } 103 | LHJoin(std::set elems); 104 | private: 105 | const std::set elems; 106 | LHJoin& operator=(const LHJoin&); 107 | }; 108 | 109 | } 110 | 111 | 112 | #endif /* LHCONSTRAINTS_H_ */ 113 | -------------------------------------------------------------------------------- /include/Constraints/PartialSolution.h: -------------------------------------------------------------------------------- 1 | //===-- PartialSolution.h ---------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef _PARTIAL_SOLUTION_H_ 15 | #define _PARTIAL_SOLUTION_H_ 16 | 17 | #include "Constraints/ConstraintKit.h" 18 | #include "Constraints/LHConstraintKit.h" 19 | #include "Constraints/LHConstraints.h" 20 | 21 | #include "llvm/ADT/DenseSet.h" 22 | #include "llvm/ADT/DenseMap.h" 23 | #include "llvm/ADT/SmallPtrSet.h" 24 | 25 | #include 26 | 27 | namespace deps { 28 | 29 | class PartialSolution : public ConsSoln { 30 | public: 31 | // Exported types: 32 | typedef llvm::SmallPtrSet VarSet; 33 | typedef llvm::DenseMap > PMap; 34 | typedef std::vector Constraints; 35 | 36 | // Constructor, constraints aren't stored 37 | PartialSolution(Constraints & C, bool initial) : initial(initial) { 38 | initialize(C); 39 | propagate(); 40 | } 41 | 42 | // copy constructor 43 | PartialSolution(PartialSolution &P); 44 | 45 | // Merge in another PartialSolution with this, and re-solve. 46 | void mergeIn(PartialSolution &P); 47 | 48 | // Evaluate the given ConsElem in our solution environment 49 | const LHConstant& subst(const ConsElem& E); 50 | 51 | private: 52 | // Construct propagation map and seed VSet 53 | void initialize(Constraints & C); 54 | 55 | // Solve by propagation 56 | void propagate(); 57 | // Query VSets of this and all chained solutions 58 | bool isChanged(const ConsVar*); 59 | 60 | // Member variables: 61 | 62 | // TODO: This data really should be refactored out!! 63 | // Used to store by-value the PropagationMap when the non-merge ctor is used. 64 | PMap P; 65 | // Set of variables with non-default values 66 | VarSet VSet; 67 | 68 | // Chained solutions 69 | std::vector Chained; 70 | 71 | // Do we consider variables 'high' intially? 72 | bool initial; 73 | }; 74 | 75 | } // end namespace deps 76 | #endif // _PARTIAL_SOLUTION_H_ 77 | -------------------------------------------------------------------------------- /include/Constraints/SolverThread.h: -------------------------------------------------------------------------------- 1 | //===-- SolverThread.h ------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef _SOLVERTHREAD_H_ 15 | #define _SOLVERTHREAD_H_ 16 | 17 | #include "Constraints/LHConstraintKit.h" 18 | #include "Constraints/LHConstraints.h" 19 | #include "Constraints/PartialSolution.h" 20 | 21 | #include "llvm/ADT/DenseSet.h" 22 | #include "llvm/Support/Threading.h" 23 | #include "llvm/Support/Atomic.h" 24 | 25 | #include 26 | 27 | namespace deps { 28 | 29 | typedef std::vector Constraints; 30 | 31 | // Spawns thread to solve the given set of Constraints. 32 | class SolverThread { 33 | pthread_t thread; 34 | 35 | Constraints &C; 36 | bool greatest; 37 | 38 | SolverThread(Constraints &C, bool isG) 39 | : C(C), greatest(isG) {} 40 | 41 | static void* solve(void * arg); 42 | public: 43 | 44 | // Create a new thread to solve the given constraints 45 | static SolverThread *spawn(Constraints &C, bool greatest); 46 | 47 | // Wait for this thread to finish 48 | void join(PartialSolution*& P); 49 | 50 | // Please just call join() explicitly 51 | // But just in case... 52 | ~SolverThread() { 53 | PartialSolution* P; 54 | join(P); 55 | } 56 | }; 57 | 58 | } // end namespace deps 59 | 60 | #endif // _SOLVERTHREAD_H_ 61 | -------------------------------------------------------------------------------- /include/FPCache.h: -------------------------------------------------------------------------------- 1 | //===-- FPCache.h - Cache functionPass results ------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // For some reason, FunctionPass results don't seem to be properly cached 11 | // when requesting them multiple times from a ModulePass. 12 | // 13 | // This is a simple wrapper pass that explicitly caches them for us. 14 | // 15 | //===----------------------------------------------------------------------===// 16 | #ifndef _FPCACHE_H_ 17 | #define _FPCACHE_H_ 18 | 19 | #include "llvm/Pass.h" 20 | #include "llvm/Module.h" 21 | #include "llvm/ADT/DenseMap.h" 22 | 23 | using namespace llvm; 24 | 25 | namespace deps { 26 | 27 | template 28 | class FPCache : public ModulePass { 29 | DenseMap Cache; 30 | protected: 31 | FPCache(char & ID) : ModulePass(ID) {} 32 | public: 33 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 34 | AU.addRequired(); 35 | AU.setPreservesAll(); 36 | } 37 | virtual const char * getPassName() const { return "FunctionPass Cache"; } 38 | 39 | // When the pass is run, get results for all functions. 40 | virtual bool runOnModule(Module &M) { 41 | releaseMemory(); 42 | for(Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { 43 | if (!I->isDeclaration()) 44 | Cache[I] = &getAnalysis(*I); 45 | } 46 | return false; 47 | } 48 | 49 | // Cache accessor 50 | FP & get(const Function *F) const { 51 | typename DenseMap::const_iterator I = Cache.find(F); 52 | assert((I != Cache.end()) && "Function not in cache!"); 53 | return *I->second; 54 | } 55 | 56 | // Clear cache when pass is invalidated 57 | virtual void releaseMemory() { 58 | Cache.clear(); 59 | } 60 | 61 | }; 62 | 63 | 64 | } // end namespace deps 65 | 66 | #endif // _FPCACHE_H_ 67 | -------------------------------------------------------------------------------- /include/FlowRecord.h: -------------------------------------------------------------------------------- 1 | //===- FlowRecord.h ---------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines FlowRecords. A FlowRecord relates information flow 11 | // sources to sinks and is a relatively concise way of encoding constraints 12 | // (e.g. from a signature). 13 | // 14 | // There are four types of sources/sinks: 15 | // - Values: An actual llvm value 16 | // - DirectPtr: A memory location directly pointed to by a pointer. 17 | // Represented with the llvm pointer value itself. 18 | // - ReachPtr: All of the memory locations reachable by a pointer. 19 | // Represented with the llvm pointer value itself. 20 | // - Varg: The vararg list of a function 21 | //===----------------------------------------------------------------------===// 22 | 23 | #ifndef FLOWRECORD_H 24 | #define FLOWRECORD_H 25 | 26 | #include "CallContext.h" 27 | #include "llvm/Value.h" 28 | #include "llvm/ADT/SmallPtrSet.h" 29 | 30 | #include 31 | 32 | namespace deps { 33 | 34 | using namespace llvm; 35 | 36 | /// A FlowRecord relates information flow sources to sinks. There are three 37 | /// types of sources/sinks: 38 | /// - Values: An actual llvm value 39 | /// - DirectPtr: A memory location directly pointed to by a pointer. 40 | /// Represented with the llvm pointer value itself. 41 | /// - ReachPtr: All of the memory locations reachable by a pointer. 42 | /// Represented with the llvm pointer value itself. 43 | /// - Varg: ... 44 | class FlowRecord { 45 | public: 46 | typedef SmallPtrSet value_set; 47 | typedef value_set::const_iterator value_iterator; 48 | typedef SmallPtrSet fun_set; 49 | typedef fun_set::const_iterator fun_iterator; 50 | 51 | FlowRecord() : implicit(false), sourceCtxt(DefaultID), sinkCtxt(DefaultID) { } 52 | FlowRecord(bool type) : implicit(type), sourceCtxt(DefaultID), sinkCtxt(DefaultID) { } 53 | FlowRecord(const ContextID source, const ContextID sink) : 54 | implicit(false), sourceCtxt(source), sinkCtxt(sink) { } 55 | FlowRecord(bool type, const ContextID source, const ContextID sink) : 56 | implicit(type), sourceCtxt(source), sinkCtxt(sink) { } 57 | 58 | bool isImplicit() const { return implicit; } 59 | 60 | ContextID sourceContext() const { return sourceCtxt; } 61 | ContextID sinkContext() const { return sinkCtxt; } 62 | 63 | void addSourceValue(const Value & V) { valueSources.insert(&V); } 64 | void addSourceDirectPtr(const Value & V) { directPtrSources.insert(&V); } 65 | void addSourceReachablePtr(const Value & V) { reachPtrSources.insert(&V); } 66 | 67 | void addSinkValue(const Value & V) { valueSinks.insert(&V); } 68 | void addSinkDirectPtr(const Value & V) { directPtrSinks.insert(&V); } 69 | void addSinkReachablePtr(const Value & V) { reachPtrSinks.insert(&V); } 70 | 71 | template 72 | void addSourceValue(it begin, it end) { valueSources.insert(begin, end); } 73 | template 74 | void addSourceDirectPtr(it begin, it end) { directPtrSources.insert(begin, end); } 75 | template 76 | void addSourceReachablePtr(it begin, it end) { reachPtrSources.insert(begin, end); } 77 | 78 | template 79 | void addSinkValue(it begin, it end) { valueSinks.insert(begin, end); } 80 | template 81 | void addSinkDirectPtr(it begin, it end) { directPtrSinks.insert(begin, end); } 82 | template 83 | void addSinkReachablePtr(it begin, it end) { reachPtrSinks.insert(begin, end); } 84 | 85 | void addSourceVarg(const Function & F) { vargSources.insert(&F); } 86 | void addSinkVarg(const Function & F) { vargSinks.insert(&F); } 87 | template 88 | void addSourceVarg(it begin, it end) { vargSources.insert(begin, end); } 89 | template 90 | void addSinkVarg(it begin, it end) { vargSinks.insert(begin, end); } 91 | 92 | bool valueIsSink(const Value & V) const { return valueSinks.count(&V); } 93 | bool vargIsSink(const Function & F) const { return vargSinks.count(&F); } 94 | bool directPtrIsSink(const Value & V) const { return directPtrSinks.count(&V); } 95 | bool reachPtrIsSink(const Value & V) const { return reachPtrSinks.count(&V); } 96 | 97 | value_iterator source_value_begin() const { return valueSources.begin(); } 98 | value_iterator source_value_end() const { return valueSources.end(); } 99 | value_iterator source_directptr_begin() const { return directPtrSources.begin(); } 100 | value_iterator source_directptr_end() const { return directPtrSources.end(); } 101 | value_iterator source_reachptr_begin() const { return reachPtrSources.begin(); } 102 | value_iterator source_reachptr_end() const { return reachPtrSources.end(); } 103 | fun_iterator source_varg_begin() const { return vargSources.begin(); } 104 | fun_iterator source_varg_end() const { return vargSources.end(); } 105 | 106 | value_iterator sink_value_begin() const { return valueSinks.begin(); } 107 | value_iterator sink_value_end() const { return valueSinks.end(); } 108 | value_iterator sink_directptr_begin() const { return directPtrSinks.begin(); } 109 | value_iterator sink_directptr_end() const { return directPtrSinks.end(); } 110 | value_iterator sink_reachptr_begin() const { return reachPtrSinks.begin(); } 111 | value_iterator sink_reachptr_end() const { return reachPtrSinks.end(); } 112 | fun_iterator sink_varg_begin() const { return vargSinks.begin(); } 113 | fun_iterator sink_varg_end() const { return vargSinks.end(); } 114 | 115 | private: 116 | bool implicit; 117 | value_set valueSources, directPtrSources, reachPtrSources; 118 | value_set valueSinks, directPtrSinks, reachPtrSinks; 119 | fun_set vargSources, vargSinks; 120 | ContextID sourceCtxt; 121 | ContextID sinkCtxt; 122 | }; 123 | 124 | } 125 | 126 | #endif /* FLOWRECORD_H */ 127 | -------------------------------------------------------------------------------- /include/Infoflow.h: -------------------------------------------------------------------------------- 1 | //===- Infoflow.h -----------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines a constraint-based interprocedural (2-call site sensitive) 11 | // information flow analysis for a two-level security lattice (Untainted--Tainted). 12 | // While the analysis is context-sensitive, the Infoflow pass interface is not. 13 | // 14 | //===----------------------------------------------------------------------===// 15 | 16 | #ifndef INFOFLOW_H 17 | #define INFOFLOW_H 18 | 19 | #include "CallSensitiveAnalysisPass.h" 20 | #include "CallContext.h" 21 | #include "Constraints/LHConsSoln.h" 22 | #include "Constraints/LHConstraintKit.h" 23 | #include "FPCache.h" 24 | #include "FlowRecord.h" 25 | #include "InfoflowSignature.h" 26 | #include "PointsToInterface.h" 27 | #include "SourceSinkAnalysis.h" 28 | 29 | #include "llvm/Instructions.h" 30 | #include "llvm/IntrinsicInst.h" 31 | #include "llvm/Analysis/PostDominators.h" 32 | #include "llvm/ADT/DenseMap.h" 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | namespace deps { 39 | 40 | using namespace llvm; 41 | 42 | /// Unit is the interprocedural analysis input type. 43 | /// The analysis uses unit since each function should only 44 | /// be analyzed once per context. 45 | class Unit { 46 | public: 47 | const Unit & operator=(const Unit & u) { return u; } 48 | bool operator<=(const Unit &) const { return true; } 49 | bool operator==(const Unit &) const { return true; } 50 | bool operator!=(const Unit &) const { return false; } 51 | const Unit upperBound(const Unit & u) const { return u; } 52 | }; 53 | 54 | class PDTCache : public FPCache { 55 | public: 56 | static char ID; 57 | PDTCache() : FPCache(ID) {} 58 | virtual const char * getPassName() const { return "PostDom Cache"; } 59 | }; 60 | 61 | class Infoflow; 62 | 63 | /// InfoflowSolution wraps a constraint set solution with 64 | /// the information required to extract taint summaries for 65 | /// values and locations. 66 | class InfoflowSolution { 67 | public: 68 | InfoflowSolution(Infoflow & infoflow, ConsSoln * s, 69 | const ConsElem & high, bool defaultTainted, 70 | DenseMap & valueMap, 71 | DenseMap & locMap, 72 | DenseMap & vargMap) : 73 | infoflow(infoflow), soln(s), highConstant(high), 74 | defaultTainted(defaultTainted), valueMap(valueMap), 75 | locMap(locMap), vargMap(vargMap) { } 76 | ~InfoflowSolution(); 77 | 78 | /// isTainted - returns true if the security level of the value is High. 79 | bool isTainted(const Value &); 80 | /// isDirectPtrTainted - returns true if the security level of the memory 81 | /// pointed to is High. 82 | bool isDirectPtrTainted(const Value &); 83 | /// isReachPtrTainted - returns true if the security level of memory reachable 84 | /// from the pointer is High. 85 | bool isReachPtrTainted(const Value &); 86 | /// isVargTainted - returns true if the security level of the varargs of 87 | /// the function is High. 88 | bool isVargTainted(const Function &); 89 | private: 90 | InfoflowSolution & operator=(const InfoflowSolution& rhs); 91 | 92 | const Infoflow & infoflow; 93 | ConsSoln * soln; 94 | const ConsElem & highConstant; 95 | bool defaultTainted; 96 | DenseMap & valueMap; 97 | DenseMap & locMap; 98 | DenseMap & vargMap; 99 | }; 100 | 101 | /// A constraint-based, context-sensitive, interprocedural information 102 | /// flow analysis pass. Exposes information-flow constraints with a 103 | /// Tainted/Untainted security lattice that can be used with constraint 104 | /// kinds to implement arbitrary security lattices. 105 | class Infoflow : 106 | public CallSensitiveAnalysisPass { 107 | friend class InfoflowSolution; 108 | 109 | public: 110 | static char ID; 111 | Infoflow (); 112 | virtual ~Infoflow() { delete kit; delete signatureRegistrar; } 113 | const char *getPassName() const { return "Infoflow"; } 114 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 115 | CallSensitiveAnalysisPass::getAnalysisUsage(AU); 116 | AU.addRequired(); 117 | AU.addRequired(); 118 | AU.addRequired(); 119 | AU.setPreservesAll(); 120 | } 121 | 122 | virtual void releaseMemory() { 123 | // Clear out all the maps 124 | valueConstraintMap.clear(); 125 | vargConstraintMap.clear(); 126 | summarySinkValueConstraintMap.clear(); 127 | summarySourceValueConstraintMap.clear(); 128 | summarySinkVargConstraintMap.clear(); 129 | summarySourceVargConstraintMap.clear(); 130 | 131 | // And free the kit and all its constraints 132 | delete kit; 133 | kit = NULL; 134 | } 135 | 136 | bool DropAtSinks() const; 137 | 138 | /// registerSignatures - Register an information flow signature 139 | /// to be used when calling external code. 140 | virtual void registerSignatures(); 141 | 142 | ////////////////////////////////////////////////////////////// 143 | /// Adding taint sources and taint constraints 144 | ///----------------------------------------------------------- 145 | /// The following methods allow the user to add constraints 146 | /// to the default set computed by the information flow 147 | /// analysis. The first argument specifies the constraint 148 | /// 'kind' the new constraint should be added to. When 149 | /// solving for an information flow solution, the user 150 | /// may specify a set of constraints to include. 151 | 152 | /// Adds the constraint "TAINTED <= VALUE" to the given kind 153 | void setUntainted(std::string, const Value &); 154 | /// Adds the constraint "VALUE <= UNTAINTED" to the given kind 155 | void setTainted(std::string, const Value &); 156 | /// Adds the constraint "TAINTED <= LOC" for all locations 157 | /// the value could point to to the given kind 158 | void setDirectPtrUntainted(std::string, const Value &); 159 | /// Adds the constraint "LOC <= UNTAINTED" for all locations 160 | /// the value could point to to the given kind 161 | void setDirectPtrTainted(std::string, const Value &); 162 | /// Adds the constraint "TAINTED <= LOC" for all locations 163 | /// reachable through the given pointer to the given kind 164 | void setReachPtrUntainted(std::string, const Value &); 165 | /// Adds the constraint "LOC <= UNTAINTED" for all locations 166 | /// reachable through the given pointer to the given kind 167 | void setReachPtrTainted(std::string, const Value &); 168 | /// Adds the constraint "TAINTED <= VARGS OF FUN" to the given kind 169 | void setVargUntainted(std::string, const Function &); 170 | /// Adds the constraint "VARGS OF FUN <= UNTAINTED" to the given kind 171 | void setVargTainted(std::string, const Function &); 172 | 173 | ////////////////////////////////////////////////////////////// 174 | /// Solving sets of contraints 175 | ///----------------------------------------------------------- 176 | /// The following methods return solutions to a set of 177 | /// information flow constraints. Users can request the 178 | /// greatest or least fixed point of the constraint set. 179 | /// The list of kinds specifies additional constraints that 180 | /// should be satisfied in addition to the default constraints 181 | /// computed by the information flow analysis. 182 | 183 | /// Solve the default information flow constraints combined 184 | /// with any constraints from the given kinds, and if implicit 185 | /// is true, the implicit kind. Returns the least fixed point 186 | /// of the constraint system: unconstrained values and locations 187 | /// are considered UNTAINTED. 188 | /// 189 | /// Once a solution is requested for a given kind, no further 190 | /// constriants may be added to that kind. 191 | InfoflowSolution *leastSolution(std::set kinds, bool implicit, bool sinks); 192 | 193 | /// Solve the default information flow constraints combined 194 | /// with any constraints from the given kinds, and if implicit 195 | /// is true, the implicit kind. Returns the greatest fixed point 196 | /// of the constraint system: unconstrained values and locations 197 | /// are considered TAINTED. 198 | /// 199 | /// Once a solution is requested for a given kind, no further 200 | /// constriants may be added to that kind. 201 | InfoflowSolution *greatestSolution(std::set kinds, bool implicit); 202 | 203 | 204 | typedef std::vector Flows; 205 | Flows getInstructionFlows(const Instruction &); 206 | 207 | // Solve the given kind using two threads. 208 | void solveMT(std::string kind="default") { 209 | assert(kit); 210 | kit->solveMT(kind); 211 | } 212 | std::vector solveLeastMT(std::vector kinds, bool useDefaultSinks); 213 | private: 214 | virtual void doInitialization(); 215 | virtual void doFinalization(); 216 | virtual const Unit bottomInput() const; 217 | virtual const Unit bottomOutput() const; 218 | virtual const Unit runOnContext(const AUnitType unit, const Unit input); 219 | 220 | LHConstraintKit *kit; 221 | 222 | PointsToInterface *pti; 223 | SourceSinkAnalysis *sourceSinkAnalysis; 224 | 225 | SignatureRegistrar *signatureRegistrar; 226 | 227 | FlowRecord currentContextFlowRecord(bool implicit) const; 228 | 229 | const std::set &locsForValue(const Value & value) const; 230 | const std::set &reachableLocsForValue(const Value & value) const; 231 | 232 | DenseMap > valueConstraintMap; 233 | DenseMap locConstraintMap; 234 | DenseMap > vargConstraintMap; 235 | 236 | DenseMap summarySinkValueConstraintMap; 237 | DenseMap summarySourceValueConstraintMap; 238 | DenseMap summarySinkVargConstraintMap; 239 | DenseMap summarySourceVargConstraintMap; 240 | 241 | DenseMap &getOrCreateValueConstraintMap(const ContextID); 242 | DenseMap &getOrCreateVargConstraintMap(const ContextID); 243 | 244 | virtual const Unit signatureForExternalCall(const ImmutableCallSite & cs, const Unit input); 245 | 246 | void constrainFlowRecord(const FlowRecord &); 247 | 248 | const std::string kindFromImplicitSink(bool implicit, bool sink) const; 249 | 250 | const ConsElem &getOrCreateConsElem(const ContextID, const Value &); 251 | void putOrConstrainConsElem(bool imp, bool sink, const ContextID, const Value &, const ConsElem &); 252 | const ConsElem &getOrCreateConsElemSummarySource(const Value &); 253 | void putOrConstrainConsElemSummarySource(std::string, const Value &, const ConsElem &); 254 | const ConsElem &getOrCreateConsElemSummarySink(const Value &); 255 | void putOrConstrainConsElemSummarySink(std::string, const Value &, const ConsElem &); 256 | const ConsElem &getOrCreateConsElem(const Value &); 257 | const ConsElem &getOrCreateConsElem(const AbstractLoc &); 258 | void putOrConstrainConsElem(bool imp, bool sink, const Value &, const ConsElem &); 259 | void putOrConstrainConsElem(bool imp, bool sink, const AbstractLoc &, const ConsElem &); 260 | 261 | const ConsElem &getOrCreateVargConsElem(const ContextID, const Function &); 262 | void putOrConstrainVargConsElem(bool imp, bool sink, const ContextID, const Function &, const ConsElem &); 263 | const ConsElem &getOrCreateVargConsElemSummarySource(const Function &); 264 | void putOrConstrainVargConsElemSummarySource(std::string, const Function &, const ConsElem &); 265 | const ConsElem &getOrCreateVargConsElemSummarySink(const Function &); 266 | void putOrConstrainVargConsElemSummarySink(std::string, const Function &, const ConsElem &); 267 | const ConsElem &getOrCreateVargConsElem(const Function &); 268 | void putOrConstrainVargConsElem(bool imp, bool sink, const Function &, const ConsElem &); 269 | 270 | void generateFunctionConstraints(const Function &); 271 | void generateBasicBlockConstraints(const BasicBlock &, Flows &); 272 | void getInstructionFlowsInternal(const Instruction &, bool callees, Flows &); 273 | 274 | void operandsAndPCtoValue(const Instruction &, Flows &); 275 | 276 | void constrainMemoryLocation(bool imp, bool sink, const Value &, const ConsElem &); 277 | void constrainReachableMemoryLocations(bool imp, bool sink, const Value &, const ConsElem &); 278 | const ConsElem &getOrCreateMemoryConsElem(const Value &); 279 | const ConsElem &getOrCreateReachableMemoryConsElem(const Value &); 280 | 281 | void constrainConditionalSuccessors(const TerminatorInst &, FlowRecord & rec); 282 | 283 | void constrainAtomicCmpXchgInst(const AtomicCmpXchgInst &, Flows &); 284 | void constrainAtomicRMWInst(const AtomicRMWInst &, Flows &); 285 | void constrainBinaryOperator(const BinaryOperator &, Flows &); 286 | void constrainCallInst(const CallInst &, bool callees, Flows &); 287 | void constrainCmpInst(const CmpInst &, Flows &); 288 | void constrainExtractElementInst(const ExtractElementInst &, Flows &); 289 | void constrainFenceInst(const FenceInst &, Flows &); 290 | void constrainGetElementPtrInst(const GetElementPtrInst &, Flows &); 291 | void constrainInsertElementInst(const InsertElementInst &, Flows &); 292 | void constrainInsertValueInst(const InsertValueInst &, Flows &); 293 | void constrainLandingPadInst(const LandingPadInst &, Flows &); 294 | void constrainPHINode(const PHINode &, Flows &); 295 | void constrainSelectInst(const SelectInst &, Flows &); 296 | void constrainShuffleVectorInst(const ShuffleVectorInst &, Flows &); 297 | void constrainStoreInst(const StoreInst &, Flows &); 298 | void constrainTerminatorInst(const TerminatorInst &, bool callees, Flows &); 299 | void constrainUnaryInstruction(const UnaryInstruction &, Flows &); 300 | void constrainAllocaInst(const AllocaInst &, Flows &); 301 | void constrainCastInst(const CastInst &, Flows &); 302 | void constrainExtractValueInst(const ExtractValueInst &, Flows &); 303 | void constrainLoadInst(const LoadInst &, Flows &); 304 | void constrainVAArgInst(const VAArgInst &, Flows &); 305 | void constrainBranchInst(const BranchInst &, Flows &); 306 | void constrainIndirectBrInst(const IndirectBrInst &, Flows &); 307 | void constrainInvokeInst(const InvokeInst &, bool callees, Flows &); 308 | void constrainReturnInst(const ReturnInst &, Flows &); 309 | void constrainResumeInst(const ResumeInst &, Flows &); 310 | void constrainSwitchInst(const SwitchInst &, Flows &); 311 | void constraintUnreachableInst(const UnreachableInst &, Flows &); 312 | 313 | void constrainCallSite(const ImmutableCallSite & cs, bool callees, Flows &); 314 | void constrainCallee(const ContextID calleeContext, const Function & callee, const ImmutableCallSite & cs, Flows &); 315 | void constrainIntrinsic(const IntrinsicInst &, Flows &); 316 | }; 317 | 318 | } 319 | 320 | #endif /* INFOFLOW_H */ 321 | -------------------------------------------------------------------------------- /include/InfoflowSignature.h: -------------------------------------------------------------------------------- 1 | //===-- InfoflowSignature.h -------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines an interface for creating and registering information 11 | // flow signatures. A signature registrar maintains a list of signatures. 12 | // When a call to unknown code is encountered, the registrar invokes the 13 | // signatures in order until a summary of the call's information flows is 14 | // generated. 15 | // 16 | //===----------------------------------------------------------------------===// 17 | 18 | #ifndef INFOFLOWSIGNATURE_H_ 19 | #define INFOFLOWSIGNATURE_H_ 20 | 21 | #include "CallContext.h" 22 | #include 23 | #include 24 | 25 | namespace deps { 26 | 27 | using namespace llvm; 28 | 29 | class FlowRecord; 30 | 31 | /// The public interface of an information flow signature. 32 | class Signature { 33 | public: 34 | /// Accept should return true if this signature is valid for the given call 35 | /// site and false otherwise. If a signature accepts a call site, it's 36 | /// result may be used as a summary for the given call. 37 | virtual bool accept(const ContextID ctxt, const ImmutableCallSite cs) const = 0; 38 | /// Process takes as input an llvm call site and returns a FlowRecord 39 | /// summarizing the information flows that occur as a result of the call. 40 | /// Process may only be invoked if the signature accepted the call site. 41 | virtual std::vector process(const ContextID ctxt, const ImmutableCallSite cs) const = 0; 42 | 43 | virtual ~Signature() {} 44 | }; 45 | 46 | struct SigInfo; 47 | 48 | /// A SignatureRegistrar maintains a list of signatures and finds an 49 | /// appropriate signature for a given call site. 50 | class SignatureRegistrar { 51 | public: 52 | typedef std::vector::iterator sig_iterator; 53 | SignatureRegistrar(); 54 | ~SignatureRegistrar(); 55 | /// Do not call directly. Used by RegisterSignature to register 56 | /// new signature types. 57 | void registerSignature(const SigInfo si); 58 | 59 | /// For a given call site, returns a summary of the information flows 60 | /// that may occur as a result of the call. 61 | /// Currently uses the first signature to accept the call, in order 62 | /// of signature registration. 63 | std::vector process(const ContextID ctxt, const ImmutableCallSite cs); 64 | private: 65 | std::vector sigs; 66 | }; 67 | 68 | //////////////////////////////////////////////////////////////////////////////// 69 | /// Signature registration 70 | //////////////////////////////////////////////////////////////////////////////// 71 | 72 | /// A helper structure for quickly registering signatures. 73 | struct SigInfo { 74 | public: 75 | typedef Signature* (*SigCtor_t)(); 76 | SigInfo(const SigCtor_t ctor) : ctor(ctor) { } 77 | Signature *makeSignature() const { return ctor(); } 78 | private: 79 | const SigCtor_t ctor; 80 | }; 81 | 82 | /// A helper template 83 | template 84 | Signature *callDefaultCtor() { return new sig(); } 85 | 86 | /// Based on LLVM's RegisterPass template. 87 | /// To register a signature of class MySignature with theRegistrar, invoke: 88 | /// RegisterSignature TMP(theRegistrar); 89 | /// where TMP is a fresh TMP variable. 90 | template 91 | struct RegisterSignature : SigInfo { 92 | RegisterSignature(SignatureRegistrar & registrar) 93 | : SigInfo(SigInfo::SigCtor_t(callDefaultCtor)) { 94 | registrar.registerSignature(*this); 95 | } 96 | }; 97 | 98 | } 99 | 100 | #endif /* INFOFLOWSIGNATURE_H_ */ 101 | -------------------------------------------------------------------------------- /include/InterProcAnalysisPass.h: -------------------------------------------------------------------------------- 1 | //===- InterProcAnalysisPass.h ----------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines the InterProcAnalysisPass template, which can be extended 11 | // to implement context-sensitive inter-procedural analyses. 12 | // 13 | // An analysis using this template is similar to a FunctionPass, but each 14 | // function may be analyzed multiple times, once for each _context_ in which 15 | // it is analyzed. 16 | // 17 | // If the module contains a main function, it will be analyzed first using 18 | // the given initialContext. If the module does not contain a main function, 19 | // all externally linkable functions will be analyzed in their initialContext. 20 | // Other functions are analyzed on demand via calls to getAnalysisResult(..). 21 | // 22 | //===----------------------------------------------------------------------===// 23 | 24 | #ifndef INTERPROC_ANALYSIS_PASS_H 25 | #define INTERPROC_ANALYSIS_PASS_H 26 | 27 | #include "assistDS/DataStructureCallGraph.h" 28 | 29 | #include "llvm/Pass.h" 30 | #include "llvm/Module.h" 31 | #include "llvm/Analysis/CallGraph.h" 32 | #include "llvm/Support/raw_ostream.h" 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | namespace llvm { 39 | 40 | /// An AnalysisUnit represents a Function to be analyzed and a context 41 | /// in which to analyze it. 42 | template 43 | class AnalysisUnit { 44 | public: 45 | explicit AnalysisUnit(const C ctx, const Function & fun) : ctx(ctx), fun(fun) { } 46 | const Function &function() const { return fun; } 47 | const C context() const { return ctx; } 48 | bool operator<(const AnalysisUnit & unit) const { 49 | if (&this->fun != &unit.fun) 50 | return &this->fun < &unit.fun; 51 | return this->ctx < unit.ctx; 52 | } 53 | private: 54 | const C ctx; 55 | const Function & fun; 56 | }; 57 | 58 | /// An AnalysisRecord stores the current analysis result for each AnalysisUnit. 59 | /// The input used to compute the output is stored so that a fixpoint can be found. 60 | template 61 | class AnalysisRecord { 62 | public: 63 | AnalysisRecord() { } 64 | AnalysisRecord(const I in) : in(in) { } 65 | AnalysisRecord(const I in, const O out) : in(in), out(out) { } 66 | AnalysisRecord(const AnalysisRecord & rec) : in(rec.in), out(rec.out) { } 67 | AnalysisRecord & operator= (const AnalysisRecord & other) { 68 | in = other.in; 69 | out = other.out; 70 | return *this; 71 | } 72 | const I input() const { return in; } 73 | const O output() const { return out; } 74 | bool operator<(const AnalysisRecord & rec) const { 75 | if (this->input() < rec.input()) return true; 76 | return this->output() < rec.output(); 77 | } 78 | private: 79 | I in; 80 | O out; 81 | }; 82 | 83 | /// The InterProcWorkQueue manages AnalysisUnits that still need 84 | /// to be processed. Each AnalysisUnit may appear at most once in 85 | /// the work queue (though it can be added again). 86 | template 87 | class InterProcWorkQueue { 88 | public: 89 | typedef AnalysisUnit AUnitType; 90 | typedef typename std::set::iterator AUnitIterator; 91 | 92 | bool empty() { return queue.empty(); } 93 | 94 | void enqueue(AUnitType unit) { 95 | if (set.find(unit) == set.end()) { 96 | set.insert(unit); 97 | queue.push_back(unit); 98 | } 99 | } 100 | 101 | void enqueue(AUnitIterator start, AUnitIterator end) { 102 | for (; start != end; ++start) { 103 | enqueue(*start); 104 | } 105 | } 106 | 107 | AUnitType dequeue() { 108 | assert(!queue.empty()); 109 | AUnitType unit = *queue.begin(); 110 | queue.pop_front(); 111 | set.erase(unit); 112 | return unit; 113 | } 114 | 115 | private: 116 | std::set set; 117 | std::deque queue; 118 | }; 119 | 120 | /// InterProcAnalysisPass can be extended to implement interprocedural 121 | /// analysis for different contexts and analysis input/output types. 122 | /// 123 | /// The context type, C, must be default and copy constructible, assignable, 124 | /// and have a valid < operator. 125 | /// 126 | /// The input and output types must implement the operators for 127 | /// <=, ==, and !=, and be default constructible. 128 | /// Furthermore, each should implement: 129 | /// const T upperBound(const T & other) const 130 | /// Where the output should be the join of the instances. 131 | template 132 | class InterProcAnalysisPass : public ModulePass { 133 | public: 134 | typedef AnalysisUnit AUnitType; 135 | typedef typename std::set::iterator AUnitIterator; 136 | 137 | explicit InterProcAnalysisPass(char &pid) : ModulePass(pid) {} 138 | 139 | /// bottomInput - This method should be implemented by the subclass as the 140 | /// initial input to use for each analysis unit. It should represent the 141 | /// "bottom" element of the p.o. of inputs 142 | virtual const I bottomInput() const = 0; 143 | /// bottomOutput - This method should be implemented by the subclass as the 144 | /// initial output to use for each analysis unit. It should represent the 145 | /// "bottom" element of the p.o. of summaries 146 | virtual const O bottomOutput() const = 0; 147 | 148 | /// initialContext - This method will be called to create an initial context 149 | /// for analyzing the initial functions of a module (main, or the externally 150 | /// linked functions). 151 | virtual C initialContext(const Function &) = 0; 152 | /// updateContext - This method will be called to create a new context 153 | /// by extending the current context with a new function call. 154 | virtual C updateContext(const C, const ImmutableCallSite &) = 0; 155 | virtual C updateIndirectContext(const C, const ImmutableCallSite &) = 0; 156 | 157 | /// runOnContext - This method should be implemented by the subclass to 158 | /// perform the desired analysis on the current analysis unit. 159 | virtual const O runOnContext(const AUnitType unit, const I input) = 0; 160 | /// doInitialization - This method is called before any analysis units are 161 | /// analyzed, allowing the pass to do initialization. 162 | virtual void doInitialization() { } 163 | /// doInitialization - This method is called after all analysis units of the 164 | /// module have been analyzed, allowing the pass to do required cleanup. 165 | virtual void doFinalization() { } 166 | 167 | /// getAnalysisResult - Returns the current summary for the analysis unit 168 | /// and schedules reanalysis of the unit if required. 169 | const O getAnalysisResult(const AUnitType unit, const I input) { 170 | // First, check if we have analyzed (or added to the queue) the 171 | // requested analysis unit. Create an entry if one does not exist. 172 | bool validOutput = true; 173 | if (analysisRecords.find(unit) == analysisRecords.end()) { 174 | analysisRecords[unit] = AnalysisRecord(bottomInput()); 175 | validOutput = false; 176 | } 177 | ARecord rec = analysisRecords[unit]; 178 | 179 | // Is the existing result suitable? 180 | if (validOutput && input <= rec.input()) { 181 | // If so, just return it 182 | return rec.output(); 183 | } else { 184 | // Otherwise, put it in the queue and return a "good enough" answer 185 | // If the answer improves, we'll re-analyze the caller with the new 186 | // answer. 187 | requestProcessing(unit, input); 188 | rec = analysisRecords[unit]; 189 | return rec.output(); 190 | } 191 | } 192 | 193 | /// getCurrentContext - returns the context for which we're analyzing 194 | /// the current function. (i.e., what context are we currently executing 195 | /// runOnContext(..) for?) 196 | const C getCurrentContext() const { 197 | if (currentAnalysisUnit != NULL) { 198 | return currentAnalysisUnit->context(); 199 | } else { 200 | return C(); 201 | } 202 | } 203 | 204 | /// getAnalysisUsage - InterProcAnalysisPass requires and preserves the 205 | /// call graph. Derived methods must call this implementation. 206 | virtual void getAnalysisUsage(AnalysisUsage &Info) const { 207 | Info.addRequired(); 208 | Info.addPreserved(); 209 | } 210 | 211 | /// runOnModule - the work queue "driver". Continues analyzing 212 | /// AnalysisUnits until there is no more work to be done. 213 | bool runOnModule(Module &M) { 214 | doInitialization(); 215 | 216 | analyzedFunctions.clear(); 217 | 218 | // Add the main function to the queue. If there isn't 219 | // a main function, add any externally linkable functions. 220 | addStartItemsToWorkQueue(); 221 | // Do work until we're done. 222 | while (!workQueue.empty()) { 223 | AnalysisUnit unit = workQueue.dequeue(); 224 | processAnalysisUnit(unit); 225 | } 226 | 227 | // Some functions may not have been analyzed because they 228 | // appear unreachable. Analyze them now just in case. 229 | addUnanalyzedFunctionsToWorkQueue(); 230 | while (!workQueue.empty()) { 231 | AnalysisUnit unit = workQueue.dequeue(); 232 | processAnalysisUnit(unit); 233 | } 234 | 235 | currentAnalysisUnit = NULL; 236 | 237 | doFinalization(); 238 | return false; 239 | } 240 | 241 | private: 242 | typedef AnalysisRecord ARecord; 243 | typedef typename std::map::iterator ARecordIterator; 244 | typedef typename std::map >::iterator DependencyIterator; 245 | 246 | InterProcWorkQueue workQueue; 247 | std::map analysisRecords; 248 | /// For each analysis unit, we track the analysis units that requested 249 | /// its analysis results. If those results change, we reanalyze all 250 | /// dependencies. 251 | std::map > dependencies; 252 | const AUnitType *currentAnalysisUnit; 253 | std::set analyzedFunctions; 254 | 255 | /// Adds entry points to the module to the work queue. 256 | void addStartItemsToWorkQueue() { 257 | const CallGraph & cg = getAnalysis(); 258 | const CallGraphNode *root = cg.getRoot(); 259 | const Function *rootFun = root->getFunction(); 260 | 261 | std::set startItems; 262 | if (rootFun) { 263 | // The module has a main function, start analysis here 264 | startItems.insert(AnalysisUnit(initialContext(*rootFun), *rootFun)); 265 | } else { 266 | // The module has no main, start analysis with any functions with 267 | // external linkage 268 | for (CallGraphNode::const_iterator f = root->begin(), end = root->end(); 269 | f != end; ++f) { 270 | Function *startFun = f->second->getFunction(); 271 | startItems.insert(AnalysisUnit(initialContext(*startFun), *startFun)); 272 | } 273 | } 274 | 275 | // Add each start item to the work queue with the bottom input. 276 | const I initInput = bottomInput(); 277 | for (AUnitIterator item = startItems.begin(), end = startItems.end(); 278 | item != end; ++item) { 279 | analysisRecords[*item] = AnalysisRecord(initInput); 280 | workQueue.enqueue(*item); 281 | } 282 | } 283 | 284 | void addUnanalyzedFunctionsToWorkQueue() { 285 | std::set startItems; 286 | 287 | // For each function in the module, check if it was analyzed already. 288 | // If it wasn't and it has code, add it to the workqueue 289 | const CallGraph & cg = getAnalysis(); 290 | Module & m = cg.getModule(); 291 | for (Module::iterator fun = m.begin(), end = m.end(); fun != end; ++fun) { 292 | if (analyzedFunctions.find(fun) == analyzedFunctions.end()) { 293 | if (!fun->isDeclaration()) { 294 | startItems.insert(AnalysisUnit(initialContext(*fun), *fun)); 295 | } 296 | } 297 | } 298 | 299 | // Add each start item to the work queue with the bottom input. 300 | const I initInput = bottomInput(); 301 | for (AUnitIterator item = startItems.begin(), end = startItems.end(); 302 | item != end; ++item) { 303 | analysisRecords[*item] = AnalysisRecord(initInput); 304 | workQueue.enqueue(*item); 305 | } 306 | } 307 | 308 | /// Analyzes an analysis unit by invoking runOnContext(..). 309 | /// If the result changes, adds the invalidated dependencies 310 | /// to the work queue. 311 | void processAnalysisUnit(const AUnitType unit) { 312 | currentAnalysisUnit = &unit; 313 | ARecordIterator rec = analysisRecords.find(unit); 314 | assert(rec != analysisRecords.end() && "No input!"); 315 | const O prevOutput = rec->second.output(); 316 | const I input = rec->second.input(); 317 | const O output = runOnContext(unit, input); 318 | analyzedFunctions.insert(&unit.function()); 319 | 320 | analysisRecords[unit] = AnalysisRecord(input, output); 321 | 322 | // Did the result change? 323 | if (prevOutput != output) { 324 | // need to add any consumers back to the workQueue 325 | workQueue.enqueue(dependencies[unit].begin(), dependencies[unit].end()); 326 | } 327 | } 328 | 329 | /// Adds an analysis unit to the work queue. Takes care of navigating the 330 | /// lattice of analysis inputs. 331 | void requestProcessing(const AUnitType unit, const I input) { 332 | // If we've analyzed this record before, we need to join the currently 333 | // requested input with the input we used before (to reach a fixpoint 334 | // in the analysis). 335 | ARecord rec = analysisRecords[unit]; 336 | I newInput = input.upperBound(rec.input()); 337 | analysisRecords[unit] = AnalysisRecord(newInput, rec.output()); 338 | 339 | // Add the current analysis unit to the dependencies for the requested 340 | // analysis unit. That way we can re-analyze the current unit if the 341 | // result for the requested unit changes. 342 | dependencies[unit].insert(*currentAnalysisUnit); 343 | 344 | workQueue.enqueue(unit); 345 | } 346 | }; 347 | 348 | } 349 | 350 | #endif /* INTERPROC_ANALYSIS_PASS_H */ 351 | -------------------------------------------------------------------------------- /include/PointsToInterface.h: -------------------------------------------------------------------------------- 1 | //===------- PointsToInterface.h Simple points-to analysis interface ------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares a simple interface for querying points-to information. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | 15 | #ifndef POINTSTOINTERFACE_H_ 16 | #define POINTSTOINTERFACE_H_ 17 | 18 | #include "dsa/DataStructure.h" 19 | #include "assistDS/DSNodeEquivs.h" 20 | 21 | #include "llvm/Pass.h" 22 | #include "llvm/Value.h" 23 | #include "llvm/ADT/EquivalenceClasses.h" 24 | 25 | #include 26 | #include 27 | 28 | using namespace llvm; 29 | 30 | namespace deps { 31 | 32 | // 33 | // An abstract memory location that represents the target of a pointer. 34 | // 35 | typedef DSNode AbstractLoc; 36 | 37 | typedef std::set AbstractLocSet; 38 | 39 | // 40 | // This pass provides an interface to a points-to analysis (currently DSA) that 41 | // returns sets of abstracts locations for pointer expressions. 42 | // 43 | class PointsToInterface : public ModulePass { 44 | private: 45 | static const AbstractLocSet EmptySet; 46 | 47 | std::map ClassForLeader; 48 | std::map ReachablesForLeader; 49 | DenseMap LeaderForValue; 50 | 51 | EquivalenceClasses MergedLeaders; 52 | 53 | const EquivalenceClasses *Classes; 54 | DSNodeEquivs *EquivsAnalysis; 55 | 56 | void mergeAllIncomplete(); 57 | const DSNode *getMergedLeaderForValue(const Value *V); 58 | void findReachableAbstractLocSetForNode(AbstractLocSet &S, const DSNode *Nd); 59 | 60 | public: 61 | static char ID; 62 | 63 | PointsToInterface() : ModulePass(ID) {} 64 | 65 | virtual bool runOnModule(Module &M); 66 | 67 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 68 | AU.addRequiredTransitive(); 69 | AU.setPreservesAll(); 70 | } 71 | 72 | // 73 | // For a given value in the module, returns a pointer to a set representing 74 | // the set of abstract memory locations that the value can point to. 75 | // 76 | const AbstractLocSet *getAbstractLocSetForValue(const Value *V); 77 | 78 | // 79 | // For a given value in the module, returns the set of all abstract memory 80 | // locations reachable from that value. 81 | // 82 | const AbstractLocSet *getReachableAbstractLocSetForValue(const Value *V); 83 | }; 84 | 85 | } 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /include/SignatureLibrary.h: -------------------------------------------------------------------------------- 1 | //===-- SignatureLibrary.h --------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains a library of information flow signatures that can be 11 | // registered with the Infoflow signature registrar. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef SIGNATURELIBRARY_H_ 16 | #define SIGNATURELIBRARY_H_ 17 | 18 | #include "InfoflowSignature.h" 19 | 20 | namespace deps { 21 | 22 | using namespace llvm; 23 | 24 | /// Description: A conservative signature that taints all reachable sinks with 25 | /// all reachable sources (ignoring that callees may be memory-unsafe). 26 | /// Accepts: all call sites. 27 | /// Flows: 28 | /// - Implicit flow from pc and function pointer at the call site to all sinks 29 | /// - All arguments are sources 30 | /// - The reachable objects from all pointer arguments are sources 31 | /// - The reachable objects from all pointer arguments are sinks 32 | /// - The return value (if applicable) is a sink 33 | class TaintReachable : public Signature { 34 | public: 35 | virtual bool accept(const ContextID ctxt, const ImmutableCallSite cs) const; 36 | virtual std::vector process(const ContextID ctxt, const ImmutableCallSite cs) const; 37 | }; 38 | 39 | /// Description: A dummy signature that assumes no information flows happen 40 | /// as a result of the call. (Not very useful.) 41 | /// Accepts: all call sites. 42 | /// Flows: 43 | /// - None 44 | class NoFlows : public Signature { 45 | public: 46 | virtual bool accept(const ContextID ctxt, const ImmutableCallSite cs) const; 47 | virtual std::vector process(const ContextID ctxt, const ImmutableCallSite cs) const; 48 | }; 49 | 50 | class ArgsToRet : public Signature { 51 | public: 52 | virtual bool accept(const ContextID ctxt, const ImmutableCallSite cs) const; 53 | virtual std::vector process(const ContextID ctxt, const ImmutableCallSite cs) const; 54 | }; 55 | 56 | 57 | // StdLib - Signature generation for StdLib calls 58 | struct CallSummary; 59 | class StdLib: public Signature { 60 | std::vector Calls; 61 | void initCalls(); 62 | bool findEntry(const ImmutableCallSite cs, const CallSummary *& S) const; 63 | public: 64 | StdLib() : Signature() { initCalls(); } 65 | virtual bool accept(const ContextID ctxt, const ImmutableCallSite cs) const; 66 | virtual std::vector process(const ContextID ctxt, const ImmutableCallSite cs) const; 67 | }; 68 | 69 | // OverflowChecks 70 | // Description: Signatures for the "____jf_check" family of overflow checks 71 | // Accepts: All callees starting with "____jf_check" 72 | // Flows: From all arguments to return value, no direct/reachable pointers. 73 | class OverflowChecks : public Signature { 74 | public: 75 | virtual bool accept(const ContextID ctxt, const ImmutableCallSite cs) const; 76 | virtual std::vector process(const ContextID ctxt, const ImmutableCallSite cs) const; 77 | }; 78 | 79 | } 80 | 81 | #endif /* SIGNATURELIBRARY_H_ */ 82 | -------------------------------------------------------------------------------- /include/Slice.h: -------------------------------------------------------------------------------- 1 | //===-- Slice.h -------------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef SLICE_H_ 15 | #define SLICE_H_ 16 | 17 | #include "Infoflow.h" 18 | #include "SourceSinkAnalysis.h" 19 | #include "FlowRecord.h" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace deps { 26 | 27 | using namespace llvm; 28 | 29 | class Slice { 30 | public: 31 | Slice(Infoflow & info, 32 | std::string name, 33 | FlowRecord sourcesAndSinks, 34 | bool cutAfterSinks); 35 | bool valueInSlice(const Value & value); 36 | bool directPtrInSlice(const Value & value); 37 | bool reachPtrInSlice(const Value & value); 38 | bool vargInSlice(const Function & fun); 39 | ~Slice(); 40 | private: 41 | bool cutAfterSinks; 42 | Infoflow & infoflow; 43 | InfoflowSolution *forward; 44 | InfoflowSolution *backward; 45 | }; 46 | 47 | class MultiSlice { 48 | public: 49 | MultiSlice(Infoflow & info, 50 | InfoflowSolution *backward, 51 | std::string kindPrefix, 52 | FlowRecord sinks, 53 | std::vector & sources, 54 | bool cutAfterSinks); 55 | 56 | ~MultiSlice(); 57 | 58 | bool sourceReachable(const Value* Source, const FlowRecord &FR); 59 | 60 | // XXX: These arguments are backwards from above 61 | bool valueInSlice(const Value & value, const Value* source) { 62 | assert(forward.count(source)); 63 | return forward[source]->isTainted(value) && !backward->isTainted(value); 64 | } 65 | bool directPtrInSlice(const Value & value, const Value* source) { 66 | assert(forward.count(source)); 67 | return forward[source]->isDirectPtrTainted(value) && 68 | !backward->isDirectPtrTainted(value); 69 | } 70 | bool reachPtrInSlice(const Value & value, const Value* source) { 71 | assert(forward.count(source)); 72 | return forward[source]->isReachPtrTainted(value) && 73 | !backward->isReachPtrTainted(value); 74 | } 75 | bool vargInSlice(const Function & fun, const Value* source) { 76 | assert(forward.count(source)); 77 | return forward[source]->isVargTainted(fun) && 78 | !backward->isVargTainted(fun); 79 | } 80 | private: 81 | bool cutAfterSinks; 82 | Infoflow & infoflow; 83 | // InfoflowSolutions for each overflow, sigh :). 84 | llvm::DenseMap forward; 85 | InfoflowSolution *backward; 86 | }; 87 | 88 | } 89 | 90 | #endif /* SLICE_H_ */ 91 | -------------------------------------------------------------------------------- /include/SourceSinkAnalysis.h: -------------------------------------------------------------------------------- 1 | //===------- SourceSinkAnalysis.h -- Identify taint sources and sinks ----===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file declares a pass to identify source and sink values in programs. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef SOURCESINKANALYSIS_H_ 15 | #define SOURCESINKANALYSIS_H_ 16 | 17 | #include "llvm/Pass.h" 18 | #include "llvm/Support/CallSite.h" 19 | #include "FlowRecord.h" 20 | 21 | #include 22 | #include 23 | 24 | using namespace llvm; 25 | 26 | namespace deps { 27 | 28 | class SourceSinkAnalysis : public ModulePass { 29 | public: 30 | static char ID; 31 | 32 | SourceSinkAnalysis() : ModulePass(ID) {} 33 | 34 | void visitCallInst(CallInst &CI); 35 | 36 | virtual bool runOnModule(Module &M); 37 | 38 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 39 | AU.setPreservesAll(); 40 | } 41 | 42 | // Moved over from MISO so we can get at it from Infoflow... 43 | const FlowRecord & getSourcesAndSinks() const; 44 | 45 | // Accessors for infoflow to get at sinks quickly 46 | bool valueIsSink(const Value &) const; 47 | bool vargIsSink(const Function &) const; 48 | bool directPtrIsSink(const Value &) const; 49 | bool reachPtrIsSink(const Value &) const; 50 | 51 | // 52 | // Determine the source taint information for an external function call. 53 | // 54 | // Inputs 55 | // CS is the call site to analyze. 56 | // TaintedValues will be filled with all values that should be considered 57 | // taint sources after the call occurs. 58 | // TaintedDirectPointers will be filled with all pointers only whose 59 | // directly reachable memory locations should be considered taint sources 60 | // after the call occurs. 61 | // TaintedRootPointers will be filled with all pointers whose reachable 62 | // memory locations should be considered taint sources after the call 63 | // occurs. 64 | // 65 | void identifySourcesForCallSite( 66 | const CallSite &CS, 67 | std::set &TaintedValues, 68 | std::set &TaintedDirectPointers, 69 | std::set &TaintedRootPointers 70 | ); 71 | 72 | // 73 | // Determine the sink taint information for an external function call. 74 | // 75 | // Inputs 76 | // CS is the call site to analyze. 77 | // TaintedValues will be filled with all values that should be considered 78 | // taint sinks during the call. 79 | // TaintedDirectPointers will be filled with all pointers only whose 80 | // directly reachable memory locations should be considered taint sinks 81 | // during the call. 82 | // TaintedRootPointers will be filled with all pointers whose reachable 83 | // memory locations should be considered taint sinks during the call. 84 | // 85 | void identifySinksForCallSite( 86 | const CallSite &CS, 87 | std::set &TaintedValues, 88 | std::set &TaintedDirectPointers, 89 | std::set &TaintedRootPointers 90 | ); 91 | 92 | // 93 | // Determine the source taint information for an internal function. 94 | // 95 | // NOTE: Currently only adds taint information for main 96 | // 97 | // Inputs 98 | // F is the function to analyze. 99 | // TaintedValues will be filled with all arguments that should be 100 | // considered tainted sources during a call to the function. 101 | // TaintedDirectPointers will be filled with all arguments that are 102 | // pointers and only whose directly reachable memory locations should be 103 | // considered a taint source during a call to the function. 104 | // TaintedRootPointers will be filled with all arguments that are pointers 105 | // and whose reachable memory should be considered a taint source during 106 | // a call to the function. 107 | // 108 | void identifySourcesForFunction( 109 | const Function &F, 110 | std::set &TaintedValues, 111 | std::set &TaintedDirectPointers, 112 | std::set &TaintedRootPointers 113 | ); 114 | 115 | private: 116 | FlowRecord sourcesAndSinks; 117 | }; 118 | 119 | } 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /lib/Constraints/LHConsSoln.cpp: -------------------------------------------------------------------------------- 1 | //===-- LHConsSoln.cpp ------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Constraints/LHConsSoln.h" 15 | #include "Constraints/LHConstraint.h" 16 | #include "Constraints/LHConstraintKit.h" 17 | #include "llvm/Support/Casting.h" 18 | #include "llvm/Support/ErrorHandling.h" 19 | #include "llvm/Support/raw_ostream.h" 20 | 21 | namespace deps { 22 | 23 | LHConsSoln::LHConsSoln(LHConstraintKit & kit, const LHConstant & defaultValue, std::vector *constraints) : 24 | kit(kit), defaultValue(defaultValue), constraints(constraints), solved(false) {} 25 | 26 | const LHConstant &LHConsSoln::subst(const ConsElem & elem) { 27 | solve(); 28 | if (const LHConsVar *var = llvm::dyn_cast(&elem)) { 29 | const LHConstant & other = (defaultValue == LHConstant::low()) ? 30 | LHConstant::high() : LHConstant::low(); 31 | return changed.count(var) ? other : defaultValue; 32 | } else if (const LHConstant *var = llvm::dyn_cast(&elem)) { 33 | return *var; 34 | } else if (const LHJoin *join = llvm::dyn_cast(&elem)) { 35 | const std::set & elements = join->elements(); 36 | const LHConstant *substVal = &defaultValue; 37 | for (std::set::iterator elem = elements.begin(), end = elements.end(); elem != end; ++elem) { 38 | substVal = &(substVal->join(subst(**elem))); 39 | } 40 | return *substVal; 41 | } else { 42 | assert("Unknown security policy"); 43 | } 44 | llvm_unreachable("Unknown security policy"); 45 | } 46 | 47 | void LHConsSoln::enqueueConstraints(const std::vector & constraints) { 48 | for (std::vector::const_iterator elem = constraints.begin(), end = constraints.end(); elem != end; ++elem) { 49 | if (queueSet.insert(*elem).second) 50 | queue.push_back(*elem); 51 | } 52 | } 53 | 54 | const LHConstraint &LHConsSoln::dequeueConstraint() { 55 | const LHConstraint & front = *(queue.front()); 56 | queue.pop_front(); 57 | queueSet.erase(&front); 58 | return front; 59 | } 60 | 61 | void LHConsSoln::solve(void) { 62 | if (solved) return; 63 | 64 | //llvm::errs() << "Solving "; 65 | //llvm::errs() << constraints.size(); 66 | //llvm::errs() << " constraints\n"; 67 | solved = true; 68 | // Add all of the constraint to the queue 69 | enqueueConstraints(*constraints); 70 | 71 | unsigned int number = 0; 72 | while (!queue.empty()) { 73 | number++; 74 | const LHConstraint &c = dequeueConstraint(); 75 | const ConsElem & left = c.lhs(); 76 | const ConsElem & right = c.rhs(); 77 | if (subst(left).leq(subst(right))) { 78 | // The constraint is already satisfied! 79 | } else { 80 | // Need to satisfy the constraint 81 | satisfyConstraint(c, left, right); 82 | } 83 | } 84 | //llvm::errs() << "Solved after "; 85 | //llvm::errs() << number; 86 | //llvm::errs() << " iterations\n"; 87 | 88 | // Free contrainsts and other unneeded datastructures 89 | delete constraints; 90 | constraints = NULL; 91 | releaseMemory(); 92 | } 93 | 94 | LHConsSoln::~LHConsSoln() { 95 | delete constraints; 96 | } 97 | 98 | 99 | LHConsLeastSoln::LHConsLeastSoln(LHConstraintKit & kit, std::vector * constraints) : 100 | LHConsSoln(kit, LHConstant::low(), constraints) { 101 | std::set leftVariables; 102 | for (std::vector::iterator cons = constraints->begin(), end = constraints->end(); 103 | cons != end; ++cons) { 104 | leftVariables.clear(); 105 | (*cons)->lhs().variables(leftVariables); 106 | 107 | for (std::set::iterator var = leftVariables.begin(), 108 | end = leftVariables.end(); var != end; ++var) { 109 | addInvalidIfIncreased(*var, *cons); 110 | } 111 | } 112 | } 113 | 114 | void LHConsLeastSoln::satisfyConstraint(const LHConstraint & constraint, const ConsElem & left, const ConsElem & right) { 115 | std::set vars; 116 | right.variables(vars); 117 | const LHConstant & L = subst(left); 118 | for (std::set::iterator var = vars.begin(), end = vars.end(); var != end; ++var) { 119 | const LHConstant & R = subst(**var); 120 | if (!L.leq(R)) { 121 | changed.insert(*var); 122 | // add every constraint that may now be invalidated by changing var 123 | enqueueConstraints(getOrCreateInvalidIfIncreasedSet(*var)); 124 | } 125 | } 126 | } 127 | 128 | std::vector &LHConsLeastSoln::getOrCreateInvalidIfIncreasedSet(const ConsVar *var) { 129 | return invalidIfIncreased[var]; 130 | } 131 | 132 | void LHConsLeastSoln::addInvalidIfIncreased(const ConsVar *var, const LHConstraint *c) { 133 | std::vector &varSet = getOrCreateInvalidIfIncreasedSet(var); 134 | varSet.push_back(c); 135 | } 136 | 137 | 138 | 139 | LHConsGreatestSoln::LHConsGreatestSoln(LHConstraintKit & kit, std::vector * constraints) : 140 | LHConsSoln(kit, LHConstant::high(), constraints) { 141 | std::set rightVariables; 142 | for (std::vector::iterator cons = constraints->begin(), end = constraints->end(); 143 | cons != end; ++cons) { 144 | rightVariables.clear(); 145 | (*cons)->rhs().variables(rightVariables); 146 | 147 | for (std::set::iterator var = rightVariables.begin(), 148 | end = rightVariables.end(); var != end; ++var) { 149 | addInvalidIfDecreased(*var, *cons); 150 | } 151 | } 152 | } 153 | 154 | void LHConsGreatestSoln::satisfyConstraint(const LHConstraint & constraint, const ConsElem & left, const ConsElem & right) { 155 | std::set vars; 156 | left.variables(vars); 157 | const LHConstant & R = subst(right); 158 | for (std::set::iterator var = vars.begin(), end = vars.end(); var != end; ++var) { 159 | const LHConstant &L = subst(**var); 160 | if (L.leq(R)) { 161 | // nothing to do, the variable is already low enough 162 | } else if (R.leq(L)) { 163 | // lower the variable var 164 | changed.insert(*var); 165 | // add every constraint that may now be invalidated by changing var 166 | enqueueConstraints(getOrCreateInvalidIfDecreasedSet(*var)); 167 | } else { 168 | assert(false && "Meets not supported yet... not sure what to do..."); 169 | } 170 | } 171 | } 172 | 173 | std::vector &LHConsGreatestSoln::getOrCreateInvalidIfDecreasedSet(const ConsVar *var) { 174 | return invalidIfDecreased[var]; 175 | } 176 | 177 | void LHConsGreatestSoln::addInvalidIfDecreased(const ConsVar *var, const LHConstraint *c) { 178 | std::vector &varSet = getOrCreateInvalidIfDecreasedSet(var); 179 | varSet.push_back(c); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /lib/Constraints/LHConstraintKit.cpp: -------------------------------------------------------------------------------- 1 | //===-- LHConstraintKit.cpp -------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #define DEBUG_TYPE "deps" 15 | 16 | #include "Constraints/LHConstraintKit.h" 17 | #include "Constraints/LHConstraints.h" 18 | #include "Constraints/LHConsSoln.h" 19 | #include "Constraints/PartialSolution.h" 20 | 21 | #include "llvm/Support/Casting.h" 22 | #include "llvm/ADT/Statistic.h" 23 | 24 | namespace deps { 25 | 26 | STATISTIC(explicitLHConstraints, "Number of explicit flow constraints"); 27 | STATISTIC(implicitLHConstraints, "Number of implicit flow constraints"); 28 | 29 | LHConstraintKit::LHConstraintKit() {} 30 | 31 | LHConstraintKit::~LHConstraintKit() { 32 | // Delete all associated LHConsVars 33 | for (std::vector::iterator var = vars.begin(), end = vars.end(); 34 | var != end; ++var) { 35 | delete(*var); 36 | } 37 | 38 | for (llvm::StringMap::iterator I = leastSolutions.begin(), 39 | E = leastSolutions.end(); I != E; ++I) 40 | delete I->second; 41 | for (llvm::StringMap::iterator I = greatestSolutions.begin(), 42 | E = greatestSolutions.end(); I != E; ++I) 43 | delete I->second; 44 | } 45 | 46 | const ConsVar &LHConstraintKit::newVar(const std::string description) { 47 | LHConsVar *var = new LHConsVar(description); 48 | vars.push_back(var); 49 | return *var; 50 | } 51 | 52 | const ConsElem &LHConstraintKit::lowConstant() const { 53 | return LHConstant::low(); 54 | } 55 | 56 | const ConsElem &LHConstraintKit::highConstant() const { 57 | return LHConstant::high(); 58 | } 59 | 60 | const ConsElem &LHConstraintKit::upperBound(const ConsElem &e1, const ConsElem &e2) { 61 | const LHJoin *join = LHJoin::create(e1, e2); 62 | std::set::iterator J = joins.insert(*join).first; 63 | delete join; 64 | return *J; 65 | } 66 | 67 | const ConsElem *LHConstraintKit::upperBound(const ConsElem *e1, const ConsElem *e2) { 68 | if (e1 == NULL) return e2; 69 | if (e2 == NULL) return e1; 70 | 71 | const LHJoin *join = LHJoin::create(*e1, *e2); 72 | std::set::iterator J = joins.insert(*join).first; 73 | delete join; 74 | return &*J; 75 | } 76 | 77 | const ConsElem &LHConstraintKit::upperBound(std::set elems) { 78 | const LHJoin join = LHJoin(elems); 79 | std::set::iterator J = joins.insert(join).first; 80 | return *J; 81 | } 82 | 83 | std::vector &LHConstraintKit::getOrCreateConstraintSet( 84 | const std::string kind) { 85 | return constraints.GetOrCreateValue(kind).getValue(); 86 | } 87 | 88 | void LHConstraintKit::addConstraint(const std::string kind, 89 | const ConsElem &lhs, const ConsElem &rhs) { 90 | if (lockedConstraintKinds.find(kind) != lockedConstraintKinds.end()) { 91 | assert(false && "Have already started solving this kind and cannot add more constraints."); 92 | } 93 | 94 | if (kind == "default") explicitLHConstraints++; 95 | if (kind == "implicit") implicitLHConstraints++; 96 | 97 | std::vector &set = getOrCreateConstraintSet(kind); 98 | 99 | assert(!llvm::isa(&rhs) && "We shouldn't have joins on rhs!"); 100 | 101 | if (const LHJoin *left = llvm::dyn_cast(&lhs)) { 102 | std::set elems = left->elements(); 103 | for (std::set::iterator elem = elems.begin(), 104 | end = elems.end(); elem != end; ++elem) { 105 | const LHConstraint c(**elem, rhs); 106 | set.push_back(c); 107 | } 108 | } else { 109 | LHConstraint c(lhs, rhs); 110 | set.push_back(c); 111 | } 112 | } 113 | 114 | ConsSoln *LHConstraintKit::leastSolution(const std::set kinds) { 115 | PartialSolution *PS = NULL; 116 | for (std::set::iterator kind = kinds.begin(), end = kinds.end(); kind != end; ++kind) { 117 | if (!leastSolutions.count(*kind)) { 118 | lockedConstraintKinds.insert(*kind); 119 | leastSolutions[*kind] = new PartialSolution(getOrCreateConstraintSet(*kind), false); 120 | freeUnneededConstraints(*kind); 121 | } 122 | PartialSolution *P = leastSolutions[*kind]; 123 | 124 | if (!PS) PS = new PartialSolution(*P); 125 | else PS->mergeIn(*P); 126 | } 127 | assert(PS && "No kinds given?"); 128 | return PS; 129 | } 130 | 131 | ConsSoln *LHConstraintKit::greatestSolution(const std::set kinds) { 132 | PartialSolution *PS = NULL; 133 | for (std::set::iterator kind = kinds.begin(), end = kinds.end(); kind != end; ++kind) { 134 | if (!greatestSolutions.count(*kind)) { 135 | lockedConstraintKinds.insert(*kind); 136 | greatestSolutions[*kind] = new PartialSolution(getOrCreateConstraintSet(*kind), true); 137 | freeUnneededConstraints(*kind); 138 | } 139 | PartialSolution *P = greatestSolutions[*kind]; 140 | 141 | if (!PS) PS = new PartialSolution(*P); 142 | else PS->mergeIn(*P); 143 | } 144 | assert(PS && "No kinds given?"); 145 | return PS; 146 | } 147 | 148 | void LHConstraintKit::freeUnneededConstraints(std::string kind) { 149 | // If we have the two kinds of PartialSolutions already generated 150 | // for this kind, then we no longer need the original constraints 151 | if (lockedConstraintKinds.count(kind) && 152 | leastSolutions.count(kind) && 153 | greatestSolutions.count(kind)) { 154 | // Clear out the constraints for this kind! 155 | getOrCreateConstraintSet(kind).clear(); 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /lib/Constraints/LHConstraints.cpp: -------------------------------------------------------------------------------- 1 | //===-- LHConstraints.cpp ---------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Constraints/LHConstraints.h" 15 | #include "llvm/Support/Casting.h" 16 | 17 | namespace deps { 18 | 19 | LHConstant *LHConstant::lowSingleton = NULL; 20 | LHConstant *LHConstant::highSingleton = NULL; 21 | 22 | LHConstant::LHConstant(LHLevel level) : level(level) { } 23 | 24 | const LHConstant &LHConstant::low() { 25 | if (LHConstant::lowSingleton == NULL) { 26 | LHConstant::lowSingleton = new LHConstant(LOW); 27 | } 28 | return *LHConstant::lowSingleton; 29 | } 30 | const LHConstant &LHConstant::high() { 31 | if (LHConstant::highSingleton == NULL) { 32 | LHConstant::highSingleton = new LHConstant(HIGH); 33 | } 34 | return *LHConstant::highSingleton; 35 | } 36 | 37 | bool LHConstant::leq(const ConsElem &elem) const { 38 | const LHConstant *other; 39 | // TODO not sure if dyn_cast support is set up properly 40 | if ((other = llvm::dyn_cast(&elem))) { 41 | return (this->level == LOW) || (other->level == HIGH); 42 | } else { 43 | return false; 44 | } 45 | } 46 | 47 | const LHConstant &LHConstant::join(const LHConstant & other) const { 48 | return (level == LOW) ? other : *this; 49 | } 50 | 51 | bool LHConstant::operator== (const ConsElem& elem) const { 52 | if (const LHConstant *other = llvm::dyn_cast(&elem)) { 53 | return (this->level == other->level); 54 | } else { 55 | return false; 56 | } 57 | } 58 | 59 | 60 | LHConsVar::LHConsVar(const std::string description) : desc(description) { } 61 | 62 | bool LHConsVar::leq(const ConsElem &elem) const { 63 | return false; 64 | } 65 | 66 | bool LHConsVar::operator== (const ConsElem& elem) const { 67 | if (const LHConsVar *other = llvm::dyn_cast(&elem)) { 68 | return this == other; 69 | } else { 70 | return false; 71 | } 72 | } 73 | 74 | LHJoin::LHJoin(std::set elements) : elems(elements) { } 75 | 76 | bool LHJoin::leq(const ConsElem &other) const { 77 | for (std::set::iterator elem = elems.begin(), end = elems.end(); elem != end; ++elem) { 78 | if (!(*elem)->leq(other)) { 79 | return false; 80 | } 81 | } 82 | return true; 83 | } 84 | 85 | void LHJoin::variables(std::set & vars) const { 86 | for (std::set::iterator elem = elems.begin(), end = elems.end(); elem != end; ++elem) { 87 | (*elem)->variables(vars); 88 | } 89 | } 90 | 91 | const LHJoin *LHJoin::create(const ConsElem &e1, const ConsElem &e2) { 92 | std::set elements; 93 | 94 | if (const LHJoin *j1 = llvm::dyn_cast(&e1)) { 95 | const std::set & j1elements = j1->elements(); 96 | elements.insert(j1elements.begin(), j1elements.end()); 97 | } else { 98 | elements.insert(&e1); 99 | } 100 | 101 | if (const LHJoin *j2 = llvm::dyn_cast(&e2)) { 102 | const std::set & j2elements = j2->elements(); 103 | elements.insert(j2elements.begin(), j2elements.end()); 104 | } else { 105 | elements.insert(&e2); 106 | } 107 | 108 | return new LHJoin(elements); 109 | } 110 | 111 | bool LHJoin::operator== (const ConsElem& elem) const { 112 | if (const LHJoin *other = llvm::dyn_cast(&elem)) { 113 | return this == other; 114 | } else { 115 | return false; 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /lib/Constraints/MTSolve.cpp: -------------------------------------------------------------------------------- 1 | //===-- MTSolve.cpp ---------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Solve for greatest and least using two threads. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Infoflow.h" 15 | #include "Constraints/LHConstraintKit.h" 16 | #include "Constraints/LHConstraints.h" 17 | #include "Constraints/PartialSolution.h" 18 | #include "Constraints/SolverThread.h" 19 | 20 | #include "llvm/Support/Threading.h" 21 | #include "llvm/Support/Atomic.h" 22 | #include 23 | 24 | using namespace llvm; 25 | 26 | namespace deps { 27 | 28 | SolverThread* SolverThread::spawn(Constraints &C, bool greatest) { 29 | SolverThread *T = new SolverThread(C, greatest); 30 | 31 | if (::pthread_create(&T->thread, NULL, solve, T)) { 32 | assert(0 && "Failed to create thread?!"); 33 | } 34 | 35 | return T; 36 | } 37 | 38 | void* SolverThread::solve(void* arg) { 39 | assert(arg); 40 | SolverThread *T = (SolverThread*)arg; 41 | PartialSolution *P = new PartialSolution(T->C, T->greatest); 42 | return (void*)P; 43 | } 44 | 45 | void SolverThread::join(PartialSolution*& P) { 46 | ::pthread_join(thread, (void**)&P); 47 | } 48 | 49 | void LHConstraintKit::solveMT(std::string kind) { 50 | assert(lockedConstraintKinds.insert(kind).second && "Already solved"); 51 | assert(!leastSolutions.count(kind)); 52 | assert(!greatestSolutions.count(kind)); 53 | 54 | PartialSolution*& G = greatestSolutions[kind]; 55 | PartialSolution*& L = leastSolutions[kind]; 56 | 57 | Constraints &C = getOrCreateConstraintSet(kind); 58 | 59 | SolverThread *TG = SolverThread::spawn(C, true); 60 | SolverThread *TL = SolverThread::spawn(C, false); 61 | 62 | TG->join(G); 63 | TL->join(L); 64 | 65 | delete TG; 66 | delete TL; 67 | 68 | assert(leastSolutions.count(kind)); 69 | assert(greatestSolutions.count(kind)); 70 | 71 | // Cleanup 72 | freeUnneededConstraints(kind); 73 | } 74 | 75 | 76 | struct MergeInfo { 77 | PartialSolution * Default; 78 | PartialSolution * DefaultSinks; 79 | bool useDefaultSinks; 80 | std::vector Mergees; 81 | }; 82 | 83 | void* merge(void *arg) { 84 | MergeInfo *MI = (MergeInfo*)arg; 85 | for (std::vector::iterator I = MI->Mergees.begin(), 86 | E = MI->Mergees.end(); I != E; ++I) { 87 | (*I)->mergeIn(*MI->Default); 88 | if (MI->useDefaultSinks) { 89 | (*I)->mergeIn(*MI->DefaultSinks); 90 | } 91 | } 92 | return NULL; 93 | } 94 | 95 | std::vector 96 | LHConstraintKit::solveLeastMT(std::vector kinds, bool useDefaultSinks) { 97 | assert(leastSolutions.count("default")); 98 | 99 | PartialSolution *P = leastSolutions["default"]; 100 | PartialSolution *DS = leastSolutions["default-sinks"]; 101 | std::vector ToMerge; 102 | for (std::vector::iterator kind = kinds.begin(), end = kinds.end(); 103 | kind != end; ++kind) { 104 | assert(lockedConstraintKinds.insert(*kind).second && "Already solved"); 105 | assert(!leastSolutions.count(*kind)); 106 | leastSolutions[*kind] = new PartialSolution(getOrCreateConstraintSet(*kind), false); 107 | ToMerge.push_back(new PartialSolution(*leastSolutions[*kind])); 108 | } 109 | 110 | // Make copy of the set of solutions for returning when we're done 111 | std::vector Merged(ToMerge); 112 | 113 | const unsigned T = 16; 114 | // Now kick off up to 'T' jobs, each with a vector of merges to do 115 | MergeInfo MI[T]; 116 | 117 | // Make sure all threads know the default solution: 118 | for (unsigned i = 0; i < T; ++i) { 119 | MI[i].Default = P; 120 | MI[i].DefaultSinks = DS; 121 | MI[i].useDefaultSinks = useDefaultSinks; 122 | } 123 | 124 | // And round-robin hand out merge jobs: 125 | unsigned TID = 0; 126 | while (!ToMerge.empty()) { 127 | MergeInfo* M = &MI[TID]; 128 | TID = (TID + 1) % T; 129 | 130 | M->Mergees.push_back(ToMerge.back()); 131 | ToMerge.pop_back(); 132 | } 133 | 134 | // Finally, kick off all the threads 135 | // with non-empty work queues 136 | std::vector Threads; 137 | for (unsigned i = 0; i < T; ++i) { 138 | MergeInfo *M = &MI[i]; 139 | if (!M->Mergees.empty()) { 140 | pthread_t Thread; 141 | if (::pthread_create(&Thread, NULL, merge, M)) { 142 | assert(0 && "Failed to create thread!"); 143 | } 144 | Threads.push_back(Thread); 145 | } 146 | } 147 | 148 | // Wait for them all to finish 149 | while (!Threads.empty()) { 150 | ::pthread_join(Threads.back(), NULL); 151 | Threads.pop_back(); 152 | } 153 | 154 | return Merged; 155 | } 156 | 157 | std::vector 158 | Infoflow::solveLeastMT(std::vector kinds, bool useDefaultSinks) { 159 | std::vector PS = kit->solveLeastMT(kinds, useDefaultSinks); 160 | 161 | std::vector Solns; 162 | for (std::vector::iterator I = PS.begin(), E = PS.end(); 163 | I != E; ++I) { 164 | Solns.push_back(new InfoflowSolution(*this, 165 | *I, 166 | kit->highConstant(), 167 | false, /* default to untainted */ 168 | summarySinkValueConstraintMap, 169 | locConstraintMap, 170 | summarySinkVargConstraintMap)); 171 | } 172 | 173 | return Solns; 174 | } 175 | 176 | } // end namespace deps 177 | -------------------------------------------------------------------------------- /lib/Constraints/Makefile: -------------------------------------------------------------------------------- 1 | LEVEL = ../.. 2 | 3 | LIBRARYNAME = Constraints 4 | BUILD_ARCHIVE = 1 5 | LOADABLE_MODULE = 1 6 | 7 | include $(LEVEL)/Makefile.common 8 | -------------------------------------------------------------------------------- /lib/Constraints/PartialSolution.cpp: -------------------------------------------------------------------------------- 1 | //===-- PartialSolution.cpp -------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Constraints/PartialSolution.h" 15 | 16 | #include "llvm/Support/Casting.h" 17 | 18 | #include 19 | 20 | using namespace deps; 21 | using namespace llvm; 22 | 23 | // Helper function 24 | static const LHConstant & boolToLHC(bool B) { 25 | return B ? LHConstant::high() : LHConstant::low(); 26 | } 27 | 28 | bool PartialSolution::isChanged(const ConsVar *V) { 29 | for (std::vector::iterator CI = Chained.begin(), 30 | CE = Chained.end(); CI != CE; ++CI) { 31 | if ((*CI)->VSet.count(V)) return true; 32 | } 33 | return false; 34 | } 35 | 36 | const LHConstant& PartialSolution::subst(const ConsElem& E) { 37 | // If this is a variable, look it up in VSet: 38 | if (const LHConsVar* V = dyn_cast(&E)) 39 | return boolToLHC(initial != isChanged(V)); 40 | 41 | // If this is already a constant, return it 42 | if (const LHConstant *LHC = dyn_cast(&E)) 43 | return *LHC; 44 | 45 | // Otherwise, this better be a join (asserting cast) 46 | const LHJoin *J = cast(&E); 47 | // Find all elements of the join, and evaluate it recursively 48 | const std::set & elements = J->elements(); 49 | 50 | // XXX: LHConsSoln starts with substVal as the defaultValue, 51 | // which ...seems wrong? Seems like this would make all join's 52 | // evaluate to 'high' unconditionally when solving for greatest. 53 | // Curiously, however, I'm not seeing any differences in the solutions 54 | // produced across various CINT2006 benchmarks. Oh well. 55 | const LHConstant *substVal = &LHConstant::low(); 56 | 57 | for (std::set::iterator elem = elements.begin(), 58 | end = elements.end(); elem != end; ++elem) { 59 | substVal = &(substVal->join(subst(**elem))); 60 | } 61 | 62 | return *substVal; 63 | } 64 | 65 | // Copy constructor 66 | PartialSolution::PartialSolution(PartialSolution &P) { 67 | initial = P.initial; 68 | 69 | // Chain to it 70 | Chained.push_back(this); 71 | Chained.insert(Chained.end(), P.Chained.begin(), P.Chained.end()); 72 | std::sort(Chained.begin(), Chained.end()); 73 | Chained.erase(std::unique(Chained.begin(), Chained.end()), Chained.end()); 74 | 75 | assert(std::find(Chained.begin(), Chained.end(), &P) != Chained.end()); 76 | 77 | } 78 | 79 | // Merging constructor 80 | void PartialSolution::mergeIn(PartialSolution &P) { 81 | // Sanity check 82 | assert(initial == P.initial); 83 | 84 | // Chain to it 85 | Chained.insert(Chained.end(), P.Chained.begin(), P.Chained.end()); 86 | 87 | std::sort(Chained.begin(), Chained.end()); 88 | Chained.erase(std::unique(Chained.begin(), Chained.end()), Chained.end()); 89 | 90 | assert(std::find(Chained.begin(), Chained.end(), &P) != Chained.end()); 91 | 92 | // And propagate 93 | propagate(); 94 | } 95 | 96 | // Only run for normal constructor. 97 | // Scan constraints for non-initial, building up seed VarSet. 98 | void PartialSolution::initialize(Constraints & C) { 99 | 100 | // Add ourselves to the chained list 101 | Chained.push_back(this); 102 | 103 | // Build propagation map 104 | std::set vars; 105 | std::set targets; 106 | // Build propagation map 107 | for (Constraints::iterator I = C.begin(), E = C.end(); I != E; ++I) { 108 | vars.clear(); 109 | targets.clear(); 110 | const ConsElem &From = initial ? I->rhs() : I->lhs(); 111 | const ConsElem &To = initial ? I->lhs() : I->rhs(); 112 | 113 | From.variables(vars); 114 | To.variables(targets); 115 | 116 | if (targets.empty()) continue; 117 | 118 | for (std::set::iterator var = vars.begin(), 119 | end = vars.end(); var != end; ++var) { 120 | // Update PMap for this var 121 | P[*var].insert(P[*var].end(), targets.begin(), targets.end()); 122 | } 123 | 124 | // Initialize varset: 125 | if (initial) { 126 | if (subst(From).leq(LHConstant::low())) { 127 | // A <= B, 'B' is low 128 | // Mark all in 'A' as low also 129 | VSet.insert(targets.begin(), targets.end()); 130 | } 131 | } else { 132 | if (!subst(From).leq(LHConstant::low())) { 133 | // A <= B, 'A' is high 134 | // Mark all in 'B' as high also 135 | VSet.insert(targets.begin(), targets.end()); 136 | } 137 | } 138 | } 139 | 140 | } 141 | 142 | void PartialSolution::propagate() { 143 | std::deque workList; 144 | 145 | assert(!Chained.empty()); 146 | assert(std::find(Chained.begin(), Chained.end(), this) != Chained.end()); 147 | 148 | // Enqueue all known changed variables 149 | for (std::vector::iterator CI = Chained.begin(), 150 | CE = Chained.end(); CI != CE; ++CI) { 151 | workList.insert(workList.end(), 152 | (*CI)->VSet.begin(), (*CI)->VSet.end()); 153 | } 154 | 155 | // Compute transitive closure of the non-default variables, 156 | // using all propagation maps in PMaps. 157 | while (!workList.empty()) { 158 | // Dequeue variable 159 | const ConsVar * V = workList.front(); 160 | workList.pop_front(); 161 | 162 | for (std::vector::iterator CI = Chained.begin(), 163 | CE = Chained.end(); CI != CE; ++CI) { 164 | PartialSolution &PS = **CI; 165 | 166 | PMap::iterator I = PS.P.find(V); 167 | if (I == PS.P.end()) continue; // Not in map 168 | 169 | std::vector &Updates = I->second; 170 | // For each such variable... 171 | for (std::vector::iterator I = Updates.begin(), 172 | E = Updates.end(); I != E; ++I) { 173 | // If we haven't changed it already, add it to the worklist: 174 | if (!isChanged(*I)) { 175 | VSet.insert(*I); 176 | workList.push_back(*I); 177 | } 178 | } 179 | } 180 | } 181 | } 182 | 183 | -------------------------------------------------------------------------------- /lib/Constraints/Test.cpp: -------------------------------------------------------------------------------- 1 | //===-- Test.cpp ------------------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO Description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Constraints/LHConstraintKit.h" 15 | #include "llvm/Support/Casting.h" 16 | #include 17 | 18 | using namespace deps; 19 | 20 | void test(void) { 21 | 22 | LHConstraintKit kit; 23 | 24 | const ConsElem & a = kit.newVar("a"); 25 | const ConsElem & b = kit.newVar("b"); 26 | //const ConsElem & c = kit.newVar("c"); 27 | 28 | kit.addConstraint("default", a, b); 29 | kit.addConstraint("default", a, kit.lowConstant()); 30 | kit.addConstraint("default", kit.highConstant(), b); 31 | 32 | std::set kinds; 33 | kinds.insert("default"); 34 | 35 | std::cout << "Least solution" << std::endl; 36 | 37 | ConsSoln *soln = kit.leastSolution(kinds); 38 | 39 | delete(soln); 40 | 41 | /*if (soln->subst(a) == kit.lowConstant()) { 42 | std::cout << "a : L\n"; 43 | } else if (soln->subst(a) == kit.highConstant()) { 44 | std::cout << "a : H\n"; 45 | } else { 46 | std::cout << "a : ?\n"; 47 | } 48 | 49 | if (soln->subst(b) == kit.lowConstant()) { 50 | std::cout << "b : L\n"; 51 | } else if (soln->subst(b) == kit.highConstant()) { 52 | std::cout << "b : H\n"; 53 | } else { 54 | std::cout << "b : ?\n"; 55 | } 56 | 57 | if (soln->subst(c) == kit.lowConstant()) { 58 | std::cout << "c : L\n"; 59 | } else if (soln->subst(c) == kit.highConstant()) { 60 | std::cout << "c : H\n"; 61 | } else { 62 | std::cout << "c : ?\n"; 63 | } 64 | 65 | std::cout << "Greatest solution" << std::endl; 66 | 67 | delete soln; 68 | 69 | soln = kit.greatestSolution(kinds); 70 | 71 | if (soln->subst(a) == kit.lowConstant()) { 72 | std::cout << "a : L\n"; 73 | } else if (soln->subst(a) == kit.highConstant()) { 74 | std::cout << "a : H\n"; 75 | } else { 76 | std::cout << "a : ?\n"; 77 | } 78 | 79 | if (soln->subst(b) == kit.lowConstant()) { 80 | std::cout << "b : L\n"; 81 | } else if (soln->subst(b) == kit.highConstant()) { 82 | std::cout << "b : H\n"; 83 | } else { 84 | std::cout << "b : ?\n"; 85 | } 86 | 87 | if (soln->subst(c) == kit.lowConstant()) { 88 | std::cout << "c : L\n"; 89 | } else if (soln->subst(c) == kit.highConstant()) { 90 | std::cout << "c : H\n"; 91 | } else { 92 | std::cout << "c : ?\n"; 93 | } 94 | 95 | delete soln;*/ 96 | } 97 | 98 | int main(void) { 99 | test(); 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /lib/Deps/CallContext.cpp: -------------------------------------------------------------------------------- 1 | //===-- CallContext.cpp ---------------------------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Defines ContextManager for uniqueing and generating opaque ContextID's, 11 | // as well as myriad of Context types to use with CallSensitiveAnalysisPass. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #include "CallContext.h" 16 | 17 | #include "llvm/Function.h" 18 | #include "llvm/Support/CallSite.h" 19 | #include "llvm/Support/raw_ostream.h" 20 | 21 | using namespace llvm; 22 | 23 | void CallerContext::dump() const { 24 | for (unsigned i = 0; i < callers.size(); ++i) 25 | errs() << callers[i]->getName() << " "; 26 | } 27 | 28 | void CallSiteContext::dump() const { 29 | for (unsigned i = 0; i < sites.size(); ++i) 30 | errs() << sites[i].getCaller()->getName() << " "; 31 | } 32 | -------------------------------------------------------------------------------- /lib/Deps/InfoflowSignature.cpp: -------------------------------------------------------------------------------- 1 | //===-- InfoflowSignature.cpp -----------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file defines an interface for creating and registering information 11 | // flow signatures. A signature registrar maintains a list of signatures. 12 | // When a call to unknown code is encountered, the registrar invokes the 13 | // signatures in order until a summary of the call's information flows is 14 | // generated. 15 | // 16 | //===----------------------------------------------------------------------===// 17 | 18 | #include "InfoflowSignature.h" 19 | #include "FlowRecord.h" 20 | 21 | namespace deps { 22 | 23 | using namespace llvm; 24 | 25 | SignatureRegistrar::SignatureRegistrar() { } 26 | 27 | SignatureRegistrar::~SignatureRegistrar() { 28 | for (sig_iterator sig = sigs.begin(), end = sigs.end(); 29 | sig != end; ++sig) { 30 | delete(*sig); 31 | } 32 | } 33 | 34 | void 35 | SignatureRegistrar::registerSignature(const SigInfo si) { 36 | sigs.push_back(si.makeSignature()); 37 | } 38 | 39 | std::vector 40 | SignatureRegistrar::process(const ContextID ctxt, const ImmutableCallSite cs) { 41 | for (sig_iterator sig = sigs.begin(), end = sigs.end(); sig != end; ++sig) { 42 | if ((*sig)->accept(ctxt, cs)) { 43 | return (*sig)->process(ctxt, cs); 44 | } 45 | } 46 | assert(false && "No signature matched call site."); 47 | return std::vector(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /lib/Deps/Makefile: -------------------------------------------------------------------------------- 1 | LEVEL = ../.. 2 | 3 | LIBRARYNAME = Deps 4 | BUILD_ARCHIVE = 1 5 | LOADABLE_MODULE = 1 6 | 7 | include $(LEVEL)/Makefile.common 8 | -------------------------------------------------------------------------------- /lib/Deps/SignatureLibrary.cpp: -------------------------------------------------------------------------------- 1 | //===-- SignatureLibrary.cpp -----------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains a library of information flow signatures that can be 11 | // registered with the Infoflow signature registrar. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #include "SignatureLibrary.h" 16 | #include "FlowRecord.h" 17 | 18 | #include "llvm/Function.h" 19 | #include "llvm/Instruction.h" 20 | #include "llvm/IntrinsicInst.h" 21 | #include "llvm/Support/Debug.h" 22 | #include "llvm/Support/raw_ostream.h" 23 | 24 | namespace deps { 25 | 26 | bool 27 | TaintReachable::accept(const ContextID ctxt, const ImmutableCallSite cs) const { return true; } 28 | 29 | std::vector 30 | TaintReachable::process(const ContextID ctxt, const ImmutableCallSite cs) const { 31 | DEBUG(errs() << "Using taint reachable signature for: " << *cs.getInstruction() << "\n"); 32 | 33 | FlowRecord exp(false,ctxt,ctxt); 34 | FlowRecord imp(true,ctxt,ctxt); 35 | 36 | // implicit from the pc of the call site and the function pointer 37 | imp.addSourceValue(*cs->getParent()); 38 | imp.addSourceValue(*cs.getCalledValue()); 39 | 40 | // Sources and sinks of the args 41 | for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end(); 42 | arg != end; ++arg) { 43 | // every argument's value is a source 44 | exp.addSourceValue(**arg); 45 | // if the argument is a pointer, everything it reaches is a source 46 | // and everything it reaches is a sink 47 | if ((*arg)->getType()->isPointerTy()) { 48 | exp.addSourceReachablePtr(**arg); 49 | imp.addSourceValue(**arg); 50 | 51 | exp.addSinkReachablePtr(**arg); 52 | imp.addSinkReachablePtr(**arg); 53 | } 54 | } 55 | 56 | // if the function has a return value it is a sink 57 | if (!cs->getType()->isVoidTy()) { 58 | imp.addSinkValue(*cs.getInstruction()); 59 | exp.addSinkValue(*cs.getInstruction()); 60 | } 61 | 62 | std::vector flows; 63 | flows.push_back(imp); 64 | flows.push_back(exp); 65 | return flows; 66 | } 67 | 68 | bool 69 | ArgsToRet::accept(const ContextID ctxt, const ImmutableCallSite cs) const { return true; } 70 | 71 | std::vector 72 | ArgsToRet::process(const ContextID ctxt, const ImmutableCallSite cs) const { 73 | DEBUG(errs() << "Using ArgsToRet reachable signature for: " << *cs.getInstruction() << "\n"); 74 | 75 | std::vector flows; 76 | 77 | if (!cs->getType()->isVoidTy()) { 78 | FlowRecord exp(false,ctxt,ctxt); 79 | 80 | // Sources and sinks of the args 81 | for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end(); 82 | arg != end; ++arg) { 83 | // every argument's value is a source 84 | exp.addSourceValue(**arg); 85 | } 86 | 87 | // if the function has a return value it is a sink 88 | exp.addSinkValue(*cs.getInstruction()); 89 | 90 | flows.push_back(exp); 91 | } 92 | 93 | return flows; 94 | } 95 | 96 | 97 | bool 98 | NoFlows::accept(const ContextID ctxt, const ImmutableCallSite cs) const { return true; } 99 | 100 | std::vector 101 | NoFlows::process(const ContextID ctxt, const ImmutableCallSite cs) const { 102 | DEBUG(errs() << "Using no flows signature...\n"); 103 | return std::vector(); 104 | } 105 | 106 | bool 107 | OverflowChecks::accept(const ContextID ctxt, const ImmutableCallSite cs) const { 108 | const Function * F = cs.getCalledFunction(); 109 | return F && F->getName().startswith("____jf_check"); 110 | } 111 | 112 | std::vector 113 | OverflowChecks::process(const ContextID ctxt, const ImmutableCallSite cs) const { 114 | DEBUG(errs() << "Using OverflowChecks signature...\n"); 115 | 116 | FlowRecord exp(false,ctxt,ctxt); 117 | FlowRecord imp(true,ctxt,ctxt); 118 | 119 | imp.addSourceValue(*cs->getParent()); 120 | 121 | // Add all argument values as sources 122 | for (ImmutableCallSite::arg_iterator arg = cs.arg_begin(), end = cs.arg_end(); 123 | arg != end; ++arg) 124 | exp.addSourceValue(**arg); 125 | assert(!cs->getType()->isVoidTy() && "Found 'void' overflow check?"); 126 | 127 | // And the return value as a sink 128 | exp.addSinkValue(*cs.getInstruction()); 129 | imp.addSinkValue(*cs.getInstruction()); 130 | 131 | std::vector flows; 132 | flows.push_back(imp); 133 | flows.push_back(exp); 134 | return flows; 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /lib/Deps/Slice.cpp: -------------------------------------------------------------------------------- 1 | //===- Slice.cpp - Sample Pass --------------------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file was developed by the LLVM research group and is distributed under 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // TODO description 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "Slice.h" 15 | 16 | #include 17 | 18 | namespace deps { 19 | 20 | using namespace llvm; 21 | 22 | Slice::Slice(Infoflow & info, 23 | std::string name, 24 | FlowRecord rec, 25 | bool cutSinks) : cutAfterSinks(cutSinks), infoflow(info) { 26 | std::string sourceKind = name + "-sources"; 27 | std::string sinkKind = name + "-sinks"; 28 | 29 | // Use the source and sink sets to generate constraints 30 | for (FlowRecord::value_iterator value = rec.source_value_begin(), end = rec.source_value_end(); 31 | value != end; ++value) { 32 | infoflow.setTainted(sourceKind, **value); 33 | } 34 | for (FlowRecord::value_iterator value = rec.source_directptr_begin(), end = rec.source_directptr_end(); 35 | value != end; ++value) { 36 | infoflow.setDirectPtrTainted(sourceKind, **value); 37 | } 38 | for (FlowRecord::value_iterator value = rec.source_reachptr_begin(), end = rec.source_reachptr_end(); 39 | value != end; ++value) { 40 | infoflow.setReachPtrTainted(sourceKind, **value); 41 | } 42 | for (FlowRecord::fun_iterator fun = rec.source_varg_begin(), end = rec.source_varg_end(); 43 | fun != end; ++fun) { 44 | infoflow.setVargTainted(sourceKind, **fun); 45 | } 46 | 47 | for (FlowRecord::value_iterator value = rec.sink_value_begin(), end = rec.sink_value_end(); 48 | value != end; ++value) { 49 | infoflow.setUntainted(sinkKind, **value); 50 | } 51 | for (FlowRecord::value_iterator value = rec.sink_directptr_begin(), end = rec.sink_directptr_end(); 52 | value != end; ++value) { 53 | infoflow.setDirectPtrUntainted(sinkKind, **value); 54 | } 55 | for (FlowRecord::value_iterator value = rec.sink_reachptr_begin(), end = rec.sink_reachptr_end(); 56 | value != end; ++value) { 57 | infoflow.setReachPtrUntainted(sinkKind, **value); 58 | } 59 | for (FlowRecord::fun_iterator fun = rec.sink_varg_begin(), end = rec.sink_varg_end(); 60 | fun != end; ++fun) { 61 | infoflow.setVargUntainted(sinkKind, **fun); 62 | } 63 | 64 | std::set sourceKinds; 65 | sourceKinds.insert(sourceKind); 66 | forward = infoflow.leastSolution(sourceKinds, false, !cutAfterSinks); 67 | 68 | std::set sinkKinds; 69 | sinkKinds.insert(sinkKind); 70 | backward = infoflow.greatestSolution(sinkKinds, false); 71 | } 72 | 73 | Slice::~Slice() { 74 | delete forward; 75 | delete backward; 76 | } 77 | 78 | bool 79 | Slice::valueInSlice(const Value & value) { 80 | return forward->isTainted(value) && !backward->isTainted(value); 81 | } 82 | 83 | bool 84 | Slice::directPtrInSlice(const Value & value) { 85 | return forward->isDirectPtrTainted(value) && !backward->isDirectPtrTainted(value); 86 | } 87 | 88 | bool 89 | Slice::reachPtrInSlice(const Value & value) { 90 | return forward->isReachPtrTainted(value) && !backward->isReachPtrTainted(value); 91 | } 92 | 93 | bool 94 | Slice::vargInSlice(const Function & fun) { 95 | return forward->isVargTainted(fun) && !backward->isVargTainted(fun); 96 | } 97 | 98 | bool 99 | MultiSlice::sourceReachable(const Value *Overflow, const FlowRecord & record) { 100 | assert(forward.count(Overflow)); 101 | // Is one of the flow sources reachable from the given overflow 102 | // Check sources that are values 103 | for (FlowRecord::value_iterator source = record.source_value_begin(), end = record.source_value_end(); 104 | source != end; ++source) { 105 | if (valueInSlice(**source, Overflow)) return true; 106 | } 107 | // Check sources that are directly pointed to locations 108 | for (FlowRecord::value_iterator source = record.source_directptr_begin(), end = record.source_directptr_end(); 109 | source != end; ++source) { 110 | if (directPtrInSlice(**source, Overflow)) return true; 111 | } 112 | // Check sources that are all reachable locations 113 | for (FlowRecord::value_iterator source = record.source_reachptr_begin(), end = record.source_reachptr_end(); 114 | source != end; ++source) { 115 | if (reachPtrInSlice(**source, Overflow)) return true; 116 | } 117 | // Check sources that are varargs 118 | for (FlowRecord::fun_iterator source = record.source_varg_begin(), end = record.source_varg_end(); 119 | source != end; ++source) { 120 | if (vargInSlice(**source, Overflow)) return true; 121 | } 122 | return false; 123 | } 124 | 125 | MultiSlice::MultiSlice(Infoflow & info, InfoflowSolution *backward, 126 | std::string kindPrefix, 127 | FlowRecord sinks, 128 | std::vector & sources, 129 | bool cutSinks) : cutAfterSinks(cutSinks), infoflow(info), backward(backward) { 130 | std::string sourceKindPrefix = kindPrefix + "-sources"; 131 | 132 | // Give each overflow a unique id, even across MultiSlice objects. 133 | static uint64_t unique_id = 0; 134 | 135 | // Add constraints for these sources: 136 | DenseMap kindMap; 137 | std::vector sourceKinds; 138 | for (std::vector::iterator src = sources.begin(), 139 | end = sources.end(); src != end; ++src) { 140 | std::stringstream SS; 141 | SS << unique_id++; 142 | std::string sourceKind = sourceKindPrefix + SS.str(); 143 | kindMap[*src] = sourceKind; 144 | sourceKinds.push_back(sourceKind); 145 | infoflow.setTainted(sourceKind, **src); 146 | } 147 | 148 | // Ask IF to solve these all at once 149 | std::vector Solns = infoflow.solveLeastMT(sourceKinds, !cutAfterSinks); 150 | 151 | // Now extract the InfoflowSolution objects: 152 | unsigned index = 0; 153 | for (std::vector::iterator src = sources.begin(), 154 | end = sources.end(); src != end; ++src, ++index) { 155 | forward[*src] = Solns[index]; 156 | } 157 | } 158 | 159 | MultiSlice::~MultiSlice() { 160 | for (DenseMap::iterator I = forward.begin(), 161 | E = forward.end(); I != E; ++I) 162 | delete I->second; 163 | } 164 | 165 | } // end namespace deps 166 | 167 | -------------------------------------------------------------------------------- /lib/Deps/StdLibSignatures.cpp: -------------------------------------------------------------------------------- 1 | //===-- StdLibSignatures.cpp ----------------------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file contains a library of information flow signatures for 11 | // common stdlib functions as well as a few other common runtime calls. 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #include "SignatureLibrary.h" 16 | 17 | // Support code that makes the table descriptions work 18 | #include "StdLibSignatures.h" 19 | 20 | #include "FlowRecord.h" 21 | 22 | #include "llvm/Function.h" 23 | #include "llvm/Support/CallSite.h" 24 | 25 | namespace deps { 26 | 27 | // typdef for more compact table writing 28 | typedef CallSummary C; 29 | 30 | // Descriptions of various StdLib calls 31 | // TODO: Review these again, carefully, and remove this line :) 32 | static const C CallTable[] = { 33 | //===-- Allocation --------------------------------------------------------===// 34 | C("calloc", Source(AllArgs), Sink(Ret, V), Sink(Ret, D)), 35 | C("free"), 36 | C("malloc", Source(AllArgs), Sink(Ret, V), Sink(Ret, D)), 37 | C("realloc", Source(AllArgs, D), Sink(AllArgs, D), Sink(Ret, D)), 38 | //===-- I/O ---------------------------------------------------------------===// 39 | C("_IO_getc", Source(AllArgs), Sink(Ret)), 40 | C("_IO_putc", Source(AllArgs), Sink(Ret)), 41 | C("close", Source(AllArgs), Sink(Ret)), 42 | C("fclose", Source(AllArgs), Sink(Ret)), 43 | C("feof", Source(AllArgs), Sink(Ret)), 44 | C("ferror", Source(AllArgs), Sink(Ret)), 45 | C("fflush", Source(Arg0), Sink(Ret)), 46 | C("fgetc", Source(AllArgs), Sink(Ret)), 47 | C("fileno", Source(AllArgs), Sink(Ret)), 48 | C("fopen", Source(AllArgs, D), Source(AllArgs, V), Sink(Ret)), 49 | C("fprintf", Source(AllArgs, D), Source(AllArgs), Sink(Ret)), 50 | C("fputc", Source(AllArgs), Sink(Ret)), 51 | C("fputs", Source(AllArgs, D), Source(AllArgs), Sink(Ret)), 52 | C("fread", Source(AllArgs), Sink(Ret), Sink(Arg0, D)), 53 | C("fwrite", Source(Arg0, D), Source(AllArgs), Sink(Ret)), 54 | C("getc", Source(AllArgs), Sink(Ret)), 55 | C("open", Source(AllArgs), Sink(Ret)), 56 | C("printf", Source(AllArgs, D), Source(AllArgs), Sink(Ret)), 57 | C("putc", Source(AllArgs), Sink(Ret)), 58 | C("putchar", Source(AllArgs), Sink(Ret)), 59 | C("puts", Source(Arg0, D), Sink(Ret)), 60 | C("read", Source(AllArgs), Sink(Ret), Sink(Arg1, D)), 61 | C("ungetc", Source(AllArgs), Sink(Ret)), 62 | C("vprintf", Source(AllArgs), Source(AllArgs, D), Sink(Ret)), 63 | 64 | // TODO: 65 | C("fseek"), 66 | C("ftell"), 67 | C("lseek"), 68 | C("write"), 69 | //===-- String/Memory -----------------------------------------------------===// 70 | C("strlen", Source(AllArgs, D), Sink(Ret)), 71 | C("strcpy", Source(Arg1, D), Sink(Arg0, D)), 72 | C("strcmp", Source(AllArgs, D), Sink(Ret)), 73 | C("strncmp", Source(AllArgs, D), Sink(Ret)), 74 | C("strchr", Source(AllArgs, D), Sink(Ret)), 75 | C("strrchr", Source(AllArgs, D), Sink(Ret)), 76 | C("memchr", Source(AllArgs, D), Sink(Ret)), 77 | C("sprintf", Source(AllArgs, D), Sink(Arg0, R), Sink(Ret)), 78 | C("snprintf", Source(AllArgs, D), Sink(Arg0, R), Sink(Ret)), 79 | C("strtod", Source(AllArgs, D), Sink(Arg1, R)), 80 | // TODO: 81 | C("atof"), 82 | C("memcmp"), 83 | C("strcat"), 84 | C("strcspn"), 85 | C("strerror"), 86 | C("strncat"), 87 | C("strncpy"), 88 | C("strpbrk"), 89 | C("strspn"), 90 | C("strstr"), 91 | C("strtok"), 92 | C("strtol"), 93 | C("strtoul"), 94 | C("vsprintf"), 95 | //===-- System ------------------------------------------------------------===// 96 | C("abort"), 97 | C("clock"), 98 | C("exit"), 99 | C("_exit"), 100 | C("fork"), 101 | C("signal"), 102 | C("unlink"), 103 | C("time"), 104 | 105 | // TODO: 106 | C("getcwd"), 107 | C("getenv"), 108 | C("getpagesize"), 109 | C("getpwd"), 110 | C("localtime"), 111 | C("strftime"), 112 | //===-- Math --------------------------------------------------------------===// 113 | C("ceil", Source(AllArgs), Sink(Ret)), 114 | C("cos", Source(AllArgs), Sink(Ret)), 115 | C("exp", Source(AllArgs), Sink(Ret)), 116 | C("floor", Source(AllArgs), Sink(Ret)), 117 | C("log", Source(AllArgs), Sink(Ret)), 118 | C("pow", Source(AllArgs), Sink(Ret)), 119 | C("powf", Source(AllArgs), Sink(Ret)), 120 | C("sin", Source(AllArgs), Sink(Ret)), 121 | C("sqrt", Source(AllArgs), Sink(Ret)), 122 | C("tan", Source(AllArgs), Sink(Ret)), 123 | 124 | // TODO: 125 | C("exp2"), 126 | C("fabs"), 127 | C("ldexp"), 128 | C("log10"), 129 | //===-- Misc --------------------------------------------------------------===// 130 | C("__errno_location"), 131 | C("qsort"), 132 | C("____jf_return_arg", Source(AllArgs), Sink(Ret)), 133 | //===-- TODO/Unsorted -----------------------------------------------------===// 134 | 135 | // Common C++ stuff (some, we'll probably want more) 136 | C("_ZNSo3putEc"), 137 | C("_ZNSo5flushEv"), 138 | C("_ZNSolsEi"), 139 | C("_ZSt17__throw_bad_allocv"), 140 | C("_ZSt9terminatev"), 141 | C("_ZdaPv"), 142 | C("_Znam"), 143 | C("__cxa_allocate_exception"), 144 | C("__cxa_begin_catch"), 145 | C("__cxa_end_catch"), 146 | C("__cxa_free_exception"), 147 | C("__cxa_throw"), 148 | 149 | // Not sure 150 | C("__isoc99_fscanf"), 151 | C("__ctype_b_loc"), 152 | 153 | // Exceptions 154 | C("_setjmp"), 155 | C("longjmp"), 156 | C("setjmp"), 157 | //===-- End-of-list Sentinel ----------------------------------------------===// 158 | C("") // Sentinel 159 | }; 160 | 161 | // Compare summaries by their name 162 | static bool NameCompare(const CallSummary *LHS, const CallSummary *RHS) { 163 | return LHS->Name < RHS->Name; 164 | } 165 | // Same, but used for searching to find entry matching given StringRef name 166 | static bool NameSearch(const CallSummary *LHS, const StringRef RHS) { 167 | return LHS->Name < RHS; 168 | } 169 | 170 | void 171 | StdLib::initCalls() { 172 | // Store and sort pointers to the summaries for faster/easier searching 173 | unsigned i = 0; 174 | while(!CallTable[i].Name.empty()) 175 | Calls.push_back(&CallTable[i++]); 176 | 177 | // Sort so we can use binary search to find 178 | std::sort(Calls.begin(), Calls.end(), NameCompare); 179 | } 180 | 181 | // Helper to locate a matching entry, if any 182 | bool 183 | StdLib::findEntry(const ImmutableCallSite cs, const CallSummary *& S) const { 184 | const Function *F = cs.getCalledFunction(); 185 | if (!F) return false; 186 | 187 | StringRef Name = F->getName(); 188 | 189 | std::vector::const_iterator I = 190 | std::lower_bound(Calls.begin(), Calls.end(), Name, NameSearch); 191 | 192 | if (I == Calls.end() || (*I)->Name != Name) return false; 193 | 194 | // Found it! Set output argument and return 195 | S = *I; 196 | return true; 197 | } 198 | 199 | // Helper to find the set of values described by a TSpecifier 200 | std::set 201 | getValues(const ImmutableCallSite cs, TSpecifier TS) { 202 | std::set Values; 203 | switch (TS) { 204 | case Ret: 205 | assert(!cs.getInstruction()->getType()->isVoidTy()); 206 | Values.insert(cs.getInstruction()); 207 | break; 208 | case Arg0: 209 | assert(0 < cs.arg_size()); 210 | Values.insert(cs.getArgument(0)); 211 | break; 212 | case Arg1: 213 | assert(1 < cs.arg_size()); 214 | Values.insert(cs.getArgument(1)); 215 | break; 216 | case Arg2: 217 | assert(2 < cs.arg_size()); 218 | Values.insert(cs.getArgument(2)); 219 | break; 220 | case Arg3: 221 | assert(3 < cs.arg_size()); 222 | Values.insert(cs.getArgument(3)); 223 | break; 224 | case Arg4: 225 | assert(4 < cs.arg_size()); 226 | Values.insert(cs.getArgument(4)); 227 | break; 228 | case AllArgs: 229 | assert(!cs.arg_empty()); 230 | for (unsigned i = 0; i < cs.arg_size(); ++i) 231 | Values.insert(cs.getArgument(i)); 232 | break; 233 | case VarArgs: { 234 | const Value *Callee = cs.getCalledValue()->stripPointerCasts(); 235 | FunctionType *CalleeType = 236 | dyn_cast( 237 | dyn_cast(Callee->getType())->getElementType() 238 | ); 239 | for (unsigned i = CalleeType->getNumParams(); i < cs.arg_size(); ++i) 240 | Values.insert(cs.getArgument(i)); 241 | break; 242 | } 243 | } 244 | return Values; 245 | } 246 | 247 | bool 248 | StdLib::accept(const ContextID ctxt, const ImmutableCallSite cs) const { 249 | const CallSummary *S; 250 | return findEntry(cs, S); 251 | } 252 | 253 | std::vector 254 | StdLib::process(const ContextID ctxt, const ImmutableCallSite cs) const { 255 | const CallSummary *S; 256 | bool found = findEntry(cs, S); 257 | assert(found); 258 | 259 | std::vector flows; 260 | 261 | // If there are no flows for this call, return empty vector 262 | // Similarly if the call has no arguments we already know 263 | // it has no sources so just return empty vector. 264 | if (S->Sources.empty() || cs.arg_empty()) { 265 | return flows; 266 | } 267 | 268 | // Otherwise, build up a flow record for this summary 269 | FlowRecord flow(ctxt, ctxt); 270 | 271 | // First, process all sources 272 | for (std::vector::const_iterator I = S->Sources.begin(), 273 | E = S->Sources.end(); I != E; ++I) { 274 | const TaintDecl & TD = *I; 275 | assert(TD.end == T_Source); 276 | 277 | std::set Values = getValues(cs, TD.which); 278 | switch (TD.what) { 279 | case V: // Value 280 | flow.addSourceValue(Values.begin(), Values.end()); 281 | break; 282 | case D: // DirectPtr 283 | flow.addSourceDirectPtr(Values.begin(), Values.end()); 284 | break; 285 | case R: // Reachable 286 | flow.addSourceReachablePtr(Values.begin(), Values.end()); 287 | break; 288 | } 289 | } 290 | 291 | // Then add all sinks 292 | for (std::vector::const_iterator I = S->Sinks.begin(), 293 | E = S->Sinks.end(); I != E; ++I) { 294 | const TaintDecl & TD = *I; 295 | assert(TD.end == T_Sink); 296 | 297 | std::set Values = getValues(cs, TD.which); 298 | switch (TD.what) { 299 | case V: // Value 300 | flow.addSinkValue(Values.begin(), Values.end()); 301 | break; 302 | case D: // DirectPtr 303 | flow.addSinkDirectPtr(Values.begin(), Values.end()); 304 | break; 305 | case R: // Reachable 306 | flow.addSinkReachablePtr(Values.begin(), Values.end()); 307 | break; 308 | } 309 | } 310 | 311 | // Finally, stash it in the vector and return 312 | flows.push_back(flow); 313 | return flows; 314 | } 315 | 316 | } // end namespace deps 317 | -------------------------------------------------------------------------------- /lib/Deps/StdLibSignatures.h: -------------------------------------------------------------------------------- 1 | //===-- StdLibSignatures.h --------------------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Support code for more readable StdLib summary information. 11 | // (Only meant to be included from StdLibSignatures.cpp) 12 | // 13 | //===----------------------------------------------------------------------===// 14 | 15 | #ifndef _STDLIB_SIGNATURES_H_ 16 | #define _STDLIB_SIGNATURES_H_ 17 | 18 | namespace deps { 19 | 20 | // What part of the call are we talking about? 21 | enum TSpecifier { 22 | Ret, 23 | Arg0, 24 | Arg1, 25 | Arg2, 26 | Arg3, 27 | Arg4, 28 | AllArgs, 29 | VarArgs 30 | }; 31 | 32 | // Value-only, Direct-pointer, or all reachable? 33 | enum TClass { V, D, R }; 34 | 35 | // Are we descring source or sink? 36 | enum TEnd { T_Source, T_Sink }; 37 | 38 | // Struct combining these enums 39 | struct TaintDecl { 40 | TSpecifier which; 41 | TClass what; 42 | TEnd end; 43 | }; 44 | // Subclasses for source/sink distinction 45 | struct Source : public TaintDecl { 46 | Source(TSpecifier TS, TClass TC=V) { 47 | which = TS; what = TC; end = T_Source; 48 | } 49 | }; 50 | struct Sink : public TaintDecl { 51 | Sink(TSpecifier TS=Ret, TClass TC=V) { 52 | which = TS; what = TC; end = T_Sink; 53 | } 54 | }; 55 | 56 | // Summary object: Name, Sources/Sinks 57 | // This is what we want for each stdlib call 58 | struct CallSummary { 59 | std::string Name; 60 | std::vector Sources; 61 | std::vector Sinks; 62 | 63 | // No flows 64 | CallSummary(std::string name) : Name(name) {} 65 | // Two args (need at least 1 source and 1 sink) 66 | CallSummary(std::string name, TaintDecl TD1, TaintDecl TD2) : Name(name) { 67 | process(TD1); process(TD2); 68 | verify(); 69 | } 70 | // Three element description 71 | CallSummary(std::string name, TaintDecl TD1, TaintDecl TD2, 72 | TaintDecl TD3) : Name(name) { 73 | process(TD1); process(TD2); process(TD3); 74 | verify(); 75 | } 76 | // Four element description 77 | CallSummary(std::string name, TaintDecl TD1, TaintDecl TD2, 78 | TaintDecl TD3, TaintDecl TD4) : Name(name) { 79 | process(TD1); process(TD2); process(TD3); process(TD4); 80 | verify(); 81 | } 82 | 83 | // Add the description to the appropriate list 84 | void process(TaintDecl TD) { 85 | if (TD.end == T_Source) 86 | Sources.push_back(TD); 87 | else 88 | Sinks.push_back(TD); 89 | } 90 | 91 | // Quick verification that things are as they should be 92 | void verify() { 93 | assert(!Sources.empty() && "Must have a source!"); 94 | assert(!Sinks.empty() && "Must have a sink!"); 95 | } 96 | }; 97 | } 98 | 99 | 100 | #endif // _STDLIB_SIGNATURES_H_ 101 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | LEVEL = .. 2 | 3 | DIRS = Constraints PointsToInterface SourceSinkAnalysis Deps 4 | 5 | include $(LEVEL)/Makefile.common 6 | 7 | -------------------------------------------------------------------------------- /lib/PointsToInterface/Makefile: -------------------------------------------------------------------------------- 1 | LEVEL = ../.. 2 | 3 | LIBRARYNAME = pointstointerface 4 | BUILD_ARCHIVE = 1 5 | LOADABLE_MODULE = 1 6 | 7 | include $(LEVEL)/Makefile.common 8 | -------------------------------------------------------------------------------- /lib/PointsToInterface/PointsToInterface.cpp: -------------------------------------------------------------------------------- 1 | //===- PointsToInterface.cpp ----------------------------------------------===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // Implementation of the basic points-to interface. 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #include "PointsToInterface.h" 15 | 16 | #include "dsa/DSGraphTraits.h" 17 | #include "llvm/Module.h" 18 | #include "llvm/ADT/DepthFirstIterator.h" 19 | 20 | namespace deps { 21 | 22 | static RegisterPass 23 | X("pointstointerface", "Basic points-to interface"); 24 | 25 | char PointsToInterface::ID; 26 | 27 | const AbstractLocSet PointsToInterface::EmptySet; 28 | 29 | // 30 | // To preserve soundness, we need to go over the computed equivalence classes 31 | // and merge together those which contain incomplete DSNodes. We don't merge 32 | // the classes explicitly, but only merge the sets of of leader nodes of the 33 | // classes. 34 | // 35 | void PointsToInterface::mergeAllIncomplete() { 36 | // This node is a representative of an equivalence class which contains an 37 | // incomplete node. 38 | const DSNode *IncompleteRepresentative = 0; 39 | 40 | // Iterate over all nodes in the classes, and find and merge the class 41 | // leaders for those nodes which are incomplete. 42 | EquivalenceClasses::iterator EqIt = Classes->begin(); 43 | EquivalenceClasses::iterator EqItEnd = Classes->end(); 44 | for (; EqIt != EqItEnd; ++EqIt) { 45 | // Insert all leaders into the merged leader equivalence classes. 46 | if (EqIt->isLeader()) 47 | MergedLeaders.insert(EqIt->getData()); 48 | 49 | // Get the DSNode and check if the node is incomplete. 50 | const DSNode *N = EqIt->getData(); 51 | if (!N->isIncompleteNode() && !N->isExternalNode() && !N->isUnknownNode()) 52 | continue; 53 | 54 | // Get the leader of this node's class. 55 | const DSNode *Leader = Classes->getLeaderValue(N); 56 | if (IncompleteRepresentative == 0) 57 | IncompleteRepresentative = Leader; 58 | 59 | // Merge the leader with the class that contains other leaders with 60 | // incomplete class members. 61 | MergedLeaders.unionSets(Leader, IncompleteRepresentative); 62 | } 63 | } 64 | 65 | bool PointsToInterface::runOnModule(Module &M) { 66 | EquivsAnalysis = &getAnalysis(); 67 | Classes = &EquivsAnalysis->getEquivalenceClasses(); 68 | mergeAllIncomplete(); 69 | 70 | // Does not modify module. 71 | return false; 72 | } 73 | 74 | // 75 | // Given a value in the program, returns a pointer to a set of abstract 76 | // locations that the value points to. 77 | // 78 | const AbstractLocSet * 79 | PointsToInterface::getAbstractLocSetForValue(const Value *V) { 80 | const DSNode *MergedLeader = getMergedLeaderForValue(V); 81 | 82 | // If the class for the value doesn't exist, return the empty set. 83 | if (MergedLeader == 0) 84 | return &EmptySet; 85 | 86 | // Find or build the set for the merged class leader. 87 | if (ClassForLeader.find(MergedLeader) == ClassForLeader.end()) 88 | ClassForLeader[MergedLeader].insert(MergedLeader); 89 | 90 | return &ClassForLeader[MergedLeader]; 91 | } 92 | 93 | // 94 | // Given a value in the program, returns a pointer to a set of abstract 95 | // locations that are reachable from the value. 96 | // 97 | const AbstractLocSet * 98 | PointsToInterface::getReachableAbstractLocSetForValue(const Value *V) { 99 | const DSNode *MergedLeader = getMergedLeaderForValue(V); 100 | 101 | // If the class for the value doesn't exist, return the empty set. 102 | if (MergedLeader == 0) 103 | return &EmptySet; 104 | 105 | // Check if the reachable set has been computed. 106 | if (ReachablesForLeader.find(MergedLeader) != ReachablesForLeader.end()) 107 | return &ReachablesForLeader[MergedLeader]; 108 | 109 | // Otherwise, for each element in each equivalence class merged in with 110 | // MergedLeader, we need to compute its reachable set. 111 | AbstractLocSet ReachableSet; 112 | 113 | EquivalenceClasses::member_iterator 114 | MIt = MergedLeaders.member_begin(MergedLeaders.findValue(MergedLeader)), 115 | MItEnd = MergedLeaders.member_end(); 116 | 117 | for (; MIt != MItEnd; ++MIt) { 118 | const DSNode *Leader = *MIt; 119 | 120 | EquivalenceClasses::member_iterator 121 | ClassesIt = Classes->member_begin(Classes->findValue(Leader)), 122 | ClassesItEnd = Classes->member_end(); 123 | 124 | for (; ClassesIt != ClassesItEnd; ++ClassesIt) { 125 | const DSNode *Node = *ClassesIt; 126 | findReachableAbstractLocSetForNode(ReachableSet, Node); 127 | } 128 | } 129 | 130 | // ReachableSet now contains all DSNodes reachable from V. We cut this down 131 | // to the set of merged equivalence class leaders of these nodes. 132 | AbstractLocSet &Result = ReachablesForLeader[MergedLeader]; 133 | AbstractLocSet::iterator ReachableIt = ReachableSet.begin(); 134 | AbstractLocSet::iterator ReachableEnd = ReachableSet.end(); 135 | for (; ReachableIt != ReachableEnd; ++ReachableIt) { 136 | const DSNode *Node = *ReachableIt; 137 | const DSNode *ClassLeader = Classes->getLeaderValue(Node); 138 | const DSNode *MergedLeader = MergedLeaders.getLeaderValue(ClassLeader); 139 | Result.insert(MergedLeader); 140 | } 141 | 142 | return &Result; 143 | } 144 | 145 | // 146 | // Return the DSNode that represents the leader of the given value's DSNode 147 | // equivalence class after the classes have been merged to account for 148 | // incomplete nodes. Returns null if the value's DSNode doesn't exist. 149 | // 150 | const DSNode * 151 | PointsToInterface::getMergedLeaderForValue(const Value *V) { 152 | const DSNode *Node; 153 | 154 | if (LeaderForValue.count(V)) 155 | return LeaderForValue[V]; 156 | 157 | // Get the node for V and return null if it doesn't exist. 158 | Node = EquivsAnalysis->getMemberForValue(V); 159 | if (Node == 0) 160 | return LeaderForValue[V] = 0; 161 | 162 | // Search for the equivalence class of Node. 163 | assert(Classes->findValue(Node) != Classes->end() && "Class not found!"); 164 | const DSNode *NodeLeader = Classes->getLeaderValue(Node); 165 | const DSNode *MergedLeader = MergedLeaders.getLeaderValue(NodeLeader); 166 | 167 | return LeaderForValue[V] = MergedLeader; 168 | } 169 | 170 | // 171 | // Add to the given set all nodes reachable from the given DSNode that are not 172 | // in the set already. 173 | // 174 | void 175 | PointsToInterface::findReachableAbstractLocSetForNode(AbstractLocSet &Set, 176 | const DSNode *Node) { 177 | df_ext_iterator DFIt = df_ext_begin(Node, Set); 178 | df_ext_iterator DFEnd = df_ext_end(Node, Set); 179 | for (; DFIt != DFEnd; ++DFIt) 180 | ; 181 | } 182 | 183 | } 184 | -------------------------------------------------------------------------------- /lib/SourceSinkAnalysis/Makefile: -------------------------------------------------------------------------------- 1 | LEVEL = ../.. 2 | 3 | LIBRARYNAME = sourcesinkanalysis 4 | BUILD_ARCHIVE = 1 5 | LOADABLE_MODULE = 1 6 | 7 | include $(LEVEL)/Makefile.common 8 | -------------------------------------------------------------------------------- /runtime/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a sample Makefile for a project that uses LLVM. 3 | # 4 | 5 | # 6 | # Indicates our relative path to the top of the project's root directory. 7 | # 8 | LEVEL = .. 9 | 10 | # 11 | # Directories that needs to be built. 12 | # 13 | DIRS = 14 | 15 | # 16 | # Include the Master Makefile that knows how to build all. 17 | # 18 | include $(LEVEL)/Makefile.common 19 | 20 | --------------------------------------------------------------------------------