Internal version is an LLVM 2.8 with 2 patches backported from LLVM 2.9 to fix a
crash on AVX chips.
So drop support for building with external LLVM 2.8, and add support for
building with external LLVM 2.9 instead.
Caveat:
stack smashing protection is broken on LLVM 2.9 so it is disabled
Example on Debian:
apt-get install llvm-2.9-dev
./configure --enable-llvm --with-system-llvm=/usr/bin/llvm-config-2.9
... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Fri May 6 16:16:00 EEST 2011 (edwin) |
|
2 |
+------------------------------------ |
|
3 |
+ * libclamav/c++: add support for building with external LLVM 2.9, and drop external 2.8 support |
|
4 |
+ |
|
1 | 5 |
Thu May 5 01:07:57 CEST 2011 (acab) |
2 | 6 |
------------------------------------ |
3 | 7 |
* clamd: log request ip address for instream scans #bb2592 |
... | ... |
@@ -30,8 +30,14 @@ |
30 | 30 |
#include "llvm/Analysis/DebugInfo.h" |
31 | 31 |
#include "llvm/Analysis/Dominators.h" |
32 | 32 |
#include "llvm/Analysis/ConstantFolding.h" |
33 |
-#include "llvm/Analysis/LiveValues.h" |
|
33 |
+//#include "llvm/Analysis/LiveValues.h" |
|
34 |
+// |
|
35 |
+#ifdef LLVM29 |
|
36 |
+#include "llvm/Analysis/ValueTracking.h" |
|
37 |
+#include "PointerTracking.h" |
|
38 |
+#else |
|
34 | 39 |
#include "llvm/Analysis/PointerTracking.h" |
40 |
+#endif |
|
35 | 41 |
#include "llvm/Analysis/ScalarEvolution.h" |
36 | 42 |
#include "llvm/Analysis/ScalarEvolutionExpressions.h" |
37 | 43 |
#include "llvm/Analysis/ScalarEvolutionExpander.h" |
... | ... |
@@ -54,13 +60,22 @@ |
54 | 54 |
#include "llvm/Transforms/Utils/BasicBlockUtils.h" |
55 | 55 |
#include "llvm/Support/Debug.h" |
56 | 56 |
|
57 |
+#ifndef LLVM28 |
|
57 | 58 |
#define LLVM28 |
59 |
+#endif |
|
58 | 60 |
#ifdef LLVM28 |
59 | 61 |
#define DEFINEPASS(passname) passname() : FunctionPass(ID) |
60 | 62 |
#else |
61 | 63 |
#define DEFINEPASS(passname) passname() : FunctionPass(&ID) |
62 | 64 |
#endif |
65 |
+ |
|
63 | 66 |
using namespace llvm; |
67 |
+#ifndef LLVM29 |
|
68 |
+static Value *GetUnderlyingObject(Value *P, TargetData *TD) |
|
69 |
+{ |
|
70 |
+ return P->getUnderlyingObject(); |
|
71 |
+} |
|
72 |
+#endif |
|
64 | 73 |
namespace { |
65 | 74 |
|
66 | 75 |
class PtrVerifier : public FunctionPass { |
... | ... |
@@ -275,7 +290,7 @@ namespace { |
275 | 275 |
if (BaseMap.count(P)) { |
276 | 276 |
return BaseMap[Ptr] = BaseMap[P]; |
277 | 277 |
} |
278 |
- Value *P2 = P->getUnderlyingObject(); |
|
278 |
+ Value *P2 = GetUnderlyingObject(P, TD); |
|
279 | 279 |
if (P2 != P) { |
280 | 280 |
Value *V = getPointerBase(P2); |
281 | 281 |
return BaseMap[Ptr] = V; |
... | ... |
@@ -334,7 +349,7 @@ namespace { |
334 | 334 |
} |
335 | 335 |
} |
336 | 336 |
if (LoadInst *LI = dyn_cast<LoadInst>(Base)) { |
337 |
- Value *V = LI->getPointerOperand()->stripPointerCasts()->getUnderlyingObject(); |
|
337 |
+ Value *V = GetUnderlyingObject(LI->getPointerOperand()->stripPointerCasts(), TD); |
|
338 | 338 |
if (Argument *A = dyn_cast<Argument>(V)) { |
339 | 339 |
if (A->getArgNo() == 0) { |
340 | 340 |
// pointers from hidden ctx are trusted to be at least the |
... | ... |
@@ -33,10 +33,11 @@ if BUILD_EXTERNAL_LLVM |
33 | 33 |
# we know this will be built with GNU make, so its safe to use GNU make specific |
34 | 34 |
# $(shell ...) |
35 | 35 |
#LLVM_DEPS=$(shell $(LLVM_CONFIG) --libfiles jit nativecodegen) |
36 |
-libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28 |
|
36 |
+libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28 -DLLVM29 |
|
37 | 37 |
libclamavcxx_la_LDFLAGS = @LLVMCONFIG_LDFLAGS@ @LLVMCONFIG_LIBS@ |
38 | 38 |
libclamavcxx_la_DEPENDENCIES = @LLVMCONFIG_LIBFILES@ |
39 | 39 |
noinst_LTLIBRARIES = libclamavcxx.la |
40 |
+libclamavcxx_la_SOURCES += PointerTracking.cpp |
|
40 | 41 |
|
41 | 42 |
else |
42 | 43 |
AM_CPPFLAGS += $(LLVM_INCLUDES) $(LLVM_DEFS) |
... | ... |
@@ -51,14 +51,15 @@ POST_UNINSTALL = : |
51 | 51 |
build_triplet = @build@ |
52 | 52 |
host_triplet = @host@ |
53 | 53 |
target_triplet = @target@ |
54 |
-@BUILD_EXTERNAL_LLVM_FALSE@am__append_1 = $(LLVM_INCLUDES) $(LLVM_DEFS) |
|
55 |
-@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_2 = libllvmx86codegen.la |
|
54 |
+@BUILD_EXTERNAL_LLVM_TRUE@am__append_1 = PointerTracking.cpp |
|
55 |
+@BUILD_EXTERNAL_LLVM_FALSE@am__append_2 = $(LLVM_INCLUDES) $(LLVM_DEFS) |
|
56 | 56 |
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_3 = libllvmx86codegen.la |
57 | 57 |
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_4 = libllvmx86codegen.la |
58 |
-@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_5 = libllvmpowerpccodegen.la |
|
58 |
+@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_5 = libllvmx86codegen.la |
|
59 | 59 |
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_6 = libllvmpowerpccodegen.la |
60 | 60 |
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_7 = libllvmpowerpccodegen.la |
61 |
-@BUILD_EXTERNAL_LLVM_FALSE@@MAINTAINER_MODE_TRUE@am__append_8 = $(TBLGENFILES) |
|
61 |
+@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_8 = libllvmpowerpccodegen.la |
|
62 |
+@BUILD_EXTERNAL_LLVM_FALSE@@MAINTAINER_MODE_TRUE@am__append_9 = $(TBLGENFILES) |
|
62 | 63 |
@BUILD_EXTERNAL_LLVM_FALSE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = tblgen$(EXEEXT) |
63 | 64 |
subdir = . |
64 | 65 |
DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ |
... | ... |
@@ -81,8 +82,14 @@ CONFIG_HEADER = clamavcxx-config.h |
81 | 81 |
CONFIG_CLEAN_FILES = |
82 | 82 |
CONFIG_CLEAN_VPATH_FILES = |
83 | 83 |
LTLIBRARIES = $(noinst_LTLIBRARIES) |
84 |
+am__libclamavcxx_la_SOURCES_DIST = bytecode2llvm.cpp \ |
|
85 |
+ ClamBCRTChecks.cpp ClamBCModule.h ClamBCDiagnostics.h \ |
|
86 |
+ detect.cpp PointerTracking.cpp |
|
87 |
+@BUILD_EXTERNAL_LLVM_TRUE@am__objects_1 = \ |
|
88 |
+@BUILD_EXTERNAL_LLVM_TRUE@ libclamavcxx_la-PointerTracking.lo |
|
84 | 89 |
am_libclamavcxx_la_OBJECTS = libclamavcxx_la-bytecode2llvm.lo \ |
85 |
- libclamavcxx_la-ClamBCRTChecks.lo libclamavcxx_la-detect.lo |
|
90 |
+ libclamavcxx_la-ClamBCRTChecks.lo libclamavcxx_la-detect.lo \ |
|
91 |
+ $(am__objects_1) |
|
86 | 92 |
libclamavcxx_la_OBJECTS = $(am_libclamavcxx_la_OBJECTS) |
87 | 93 |
AM_V_lt = $(am__v_lt_$(V)) |
88 | 94 |
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) |
... | ... |
@@ -798,7 +805,7 @@ SOURCES = $(libclamavcxx_la_SOURCES) $(libllvmcodegen_la_SOURCES) \ |
798 | 798 |
$(libllvmjit_la_SOURCES) $(libllvmpowerpccodegen_la_SOURCES) \ |
799 | 799 |
$(libllvmsystem_la_SOURCES) $(libllvmx86codegen_la_SOURCES) \ |
800 | 800 |
$(tblgen_SOURCES) |
801 |
-DIST_SOURCES = $(libclamavcxx_la_SOURCES) \ |
|
801 |
+DIST_SOURCES = $(am__libclamavcxx_la_SOURCES_DIST) \ |
|
802 | 802 |
$(am__libllvmcodegen_la_SOURCES_DIST) \ |
803 | 803 |
$(am__libllvmjit_la_SOURCES_DIST) \ |
804 | 804 |
$(am__libllvmpowerpccodegen_la_SOURCES_DIST) \ |
... | ... |
@@ -958,38 +965,34 @@ LLVM_INCLUDES = -I$(top_srcdir)/llvm/include -I$(top_builddir)/llvm/include |
958 | 958 |
# TODO: HP-UX should have -D_REENTRANT -D_HPUX_SOURCE |
959 | 959 |
LLVM_DEFS = -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D_DEBUG -D_GNU_SOURCE |
960 | 960 |
AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/.. \ |
961 |
- -I$(top_builddir)/../../ $(am__append_1) |
|
961 |
+ -I$(top_builddir)/../../ $(am__append_2) |
|
962 | 962 |
AM_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions |
963 | 963 |
ACLOCAL_AMFLAGS = -I m4 |
964 |
-libclamavcxx_la_SOURCES = bytecode2llvm.cpp\ |
|
965 |
- ClamBCRTChecks.cpp\ |
|
966 |
- ClamBCModule.h\ |
|
967 |
- ClamBCDiagnostics.h\ |
|
968 |
- detect.cpp |
|
969 |
- |
|
964 |
+libclamavcxx_la_SOURCES = bytecode2llvm.cpp ClamBCRTChecks.cpp \ |
|
965 |
+ ClamBCModule.h ClamBCDiagnostics.h detect.cpp $(am__append_1) |
|
970 | 966 |
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_CXXFLAGS = $(LLVM_CXXFLAGS) |
971 | 967 |
#$(LLVM_CONFIG): build-llvm |
972 | 968 |
# we know this will be built with GNU make, so its safe to use GNU make specific |
973 | 969 |
# $(shell ...) |
974 | 970 |
#LLVM_DEPS=$(shell $(LLVM_CONFIG) --libfiles jit nativecodegen) |
975 |
-@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28 |
|
971 |
+@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28 -DLLVM29 |
|
976 | 972 |
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_LDFLAGS = -no-undefined |
977 | 973 |
@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_LDFLAGS = @LLVMCONFIG_LDFLAGS@ @LLVMCONFIG_LIBS@ |
978 | 974 |
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_DEPENDENCIES = \ |
979 | 975 |
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmjit.la libllvmcodegen.la \ |
980 |
-@BUILD_EXTERNAL_LLVM_FALSE@ libllvmsystem.la $(am__append_3) \ |
|
981 |
-@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_6) |
|
976 |
+@BUILD_EXTERNAL_LLVM_FALSE@ libllvmsystem.la $(am__append_4) \ |
|
977 |
+@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_7) |
|
982 | 978 |
@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_DEPENDENCIES = \ |
983 | 979 |
@BUILD_EXTERNAL_LLVM_TRUE@ @LLVMCONFIG_LIBFILES@ \ |
984 |
-@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_3) $(am__append_6) |
|
980 |
+@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_4) $(am__append_7) |
|
985 | 981 |
@BUILD_EXTERNAL_LLVM_FALSE@noinst_LTLIBRARIES = libclamavcxx.la \ |
986 | 982 |
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmsystem.la libllvmcodegen.la \ |
987 |
-@BUILD_EXTERNAL_LLVM_FALSE@ libllvmjit.la $(am__append_4) \ |
|
988 |
-@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_7) |
|
983 |
+@BUILD_EXTERNAL_LLVM_FALSE@ libllvmjit.la $(am__append_5) \ |
|
984 |
+@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_8) |
|
989 | 985 |
@BUILD_EXTERNAL_LLVM_TRUE@noinst_LTLIBRARIES = libclamavcxx.la \ |
990 |
-@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_4) $(am__append_7) |
|
986 |
+@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_5) $(am__append_8) |
|
991 | 987 |
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_LIBADD = libllvmjit.la \ |
992 |
-@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_2) $(am__append_5) \ |
|
988 |
+@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_3) $(am__append_6) \ |
|
993 | 989 |
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmcodegen.la libllvmsystem.la |
994 | 990 |
@BUILD_EXTERNAL_LLVM_FALSE@LLVM_CXXFLAGS = -Woverloaded-virtual -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings |
995 | 991 |
@BUILD_EXTERNAL_LLVM_FALSE@unittest_CXXFLAGS = @NO_VARIADIC_MACROS@ @NO_MISSING_FIELD_INITIALIZERS@ -DGTEST_HAS_TR1_TUPLE=0 |
... | ... |
@@ -1001,7 +1004,7 @@ libclamavcxx_la_SOURCES = bytecode2llvm.cpp\ |
1001 | 1001 |
|
1002 | 1002 |
# Rule to rerun LLVM's configure if it changed, before building anything else |
1003 | 1003 |
# LLVM |
1004 |
-@BUILD_EXTERNAL_LLVM_FALSE@BUILT_SOURCES = $(am__append_8) \ |
|
1004 |
+@BUILD_EXTERNAL_LLVM_FALSE@BUILT_SOURCES = $(am__append_9) \ |
|
1005 | 1005 |
@BUILD_EXTERNAL_LLVM_FALSE@ llvm/config.status |
1006 | 1006 |
@BUILD_EXTERNAL_LLVM_FALSE@EXTRA_DIST = $(top_srcdir)/llvm llvmcheck.sh $(TBLGENFILES) |
1007 | 1007 |
@BUILD_EXTERNAL_LLVM_FALSE@libllvmsystem_la_LDFLAGS = @THREAD_LIBS@ |
... | ... |
@@ -1776,6 +1779,7 @@ distclean-compile: |
1776 | 1776 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VirtRegRewriter.Plo@am__quote@ |
1777 | 1777 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/circular_raw_ostream.Plo@am__quote@ |
1778 | 1778 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-ClamBCRTChecks.Plo@am__quote@ |
1779 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-PointerTracking.Plo@am__quote@ |
|
1779 | 1780 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-bytecode2llvm.Plo@am__quote@ |
1780 | 1781 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-detect.Plo@am__quote@ |
1781 | 1782 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmpowerpccodegen_la-PPCBranchSelector.Plo@am__quote@ |
... | ... |
@@ -2070,6 +2074,14 @@ libclamavcxx_la-detect.lo: detect.cpp |
2070 | 2070 |
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
2071 | 2071 |
@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamavcxx_la_CXXFLAGS) $(CXXFLAGS) -c -o libclamavcxx_la-detect.lo `test -f 'detect.cpp' || echo '$(srcdir)/'`detect.cpp |
2072 | 2072 |
|
2073 |
+libclamavcxx_la-PointerTracking.lo: PointerTracking.cpp |
|
2074 |
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamavcxx_la_CXXFLAGS) $(CXXFLAGS) -MT libclamavcxx_la-PointerTracking.lo -MD -MP -MF $(DEPDIR)/libclamavcxx_la-PointerTracking.Tpo -c -o libclamavcxx_la-PointerTracking.lo `test -f 'PointerTracking.cpp' || echo '$(srcdir)/'`PointerTracking.cpp |
|
2075 |
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamavcxx_la-PointerTracking.Tpo $(DEPDIR)/libclamavcxx_la-PointerTracking.Plo |
|
2076 |
+@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ |
|
2077 |
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PointerTracking.cpp' object='libclamavcxx_la-PointerTracking.lo' libtool=yes @AMDEPBACKSLASH@ |
|
2078 |
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
2079 |
+@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamavcxx_la_CXXFLAGS) $(CXXFLAGS) -c -o libclamavcxx_la-PointerTracking.lo `test -f 'PointerTracking.cpp' || echo '$(srcdir)/'`PointerTracking.cpp |
|
2080 |
+ |
|
2073 | 2081 |
ConstantFolding.lo: llvm/lib/Analysis/ConstantFolding.cpp |
2074 | 2082 |
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ConstantFolding.lo -MD -MP -MF $(DEPDIR)/ConstantFolding.Tpo -c -o ConstantFolding.lo `test -f 'llvm/lib/Analysis/ConstantFolding.cpp' || echo '$(srcdir)/'`llvm/lib/Analysis/ConstantFolding.cpp |
2075 | 2083 |
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ConstantFolding.Tpo $(DEPDIR)/ConstantFolding.Plo |
2076 | 2084 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,321 @@ |
0 |
+//===- PointerTracking.cpp - Pointer Bounds Tracking ------------*- C++ -*-===// |
|
1 |
+// |
|
2 |
+// The LLVM Compiler Infrastructure |
|
3 |
+// |
|
4 |
+// This file is distributed under the University of Illinois Open Source |
|
5 |
+// License. See LICENSE.TXT for details. |
|
6 |
+// |
|
7 |
+//===----------------------------------------------------------------------===// |
|
8 |
+// |
|
9 |
+// This file implements tracking of pointer bounds. |
|
10 |
+// |
|
11 |
+//===----------------------------------------------------------------------===// |
|
12 |
+ |
|
13 |
+#include "llvm/Analysis/ConstantFolding.h" |
|
14 |
+#include "llvm/Analysis/Dominators.h" |
|
15 |
+#include "llvm/Analysis/LoopInfo.h" |
|
16 |
+#include "llvm/Analysis/MemoryBuiltins.h" |
|
17 |
+#include "llvm/Analysis/ValueTracking.h" |
|
18 |
+#include "PointerTracking.h" |
|
19 |
+#include "llvm/Analysis/ScalarEvolution.h" |
|
20 |
+#include "llvm/Analysis/ScalarEvolutionExpressions.h" |
|
21 |
+#include "llvm/Constants.h" |
|
22 |
+#include "llvm/Module.h" |
|
23 |
+#include "llvm/Value.h" |
|
24 |
+#include "llvm/Support/CallSite.h" |
|
25 |
+#include "llvm/Support/InstIterator.h" |
|
26 |
+#include "llvm/Support/raw_ostream.h" |
|
27 |
+#include "llvm/Target/TargetData.h" |
|
28 |
+using namespace llvm; |
|
29 |
+namespace llvm { |
|
30 |
+ void initializePointerTrackingPass(llvm::PassRegistry&); |
|
31 |
+}; |
|
32 |
+INITIALIZE_PASS(PointerTracking, "pointertracking", |
|
33 |
+ "Track pointer bounds", false, true); |
|
34 |
+char PointerTracking::ID = 0; |
|
35 |
+PointerTracking::PointerTracking() : FunctionPass(ID) { |
|
36 |
+ initializePointerTrackingPass(*PassRegistry::getPassRegistry()); |
|
37 |
+} |
|
38 |
+ |
|
39 |
+bool PointerTracking::runOnFunction(Function &F) { |
|
40 |
+ predCache.clear(); |
|
41 |
+ assert(analyzing.empty()); |
|
42 |
+ FF = &F; |
|
43 |
+ TD = getAnalysisIfAvailable<TargetData>(); |
|
44 |
+ SE = &getAnalysis<ScalarEvolution>(); |
|
45 |
+ LI = &getAnalysis<LoopInfo>(); |
|
46 |
+ DT = &getAnalysis<DominatorTree>(); |
|
47 |
+ return false; |
|
48 |
+} |
|
49 |
+ |
|
50 |
+void PointerTracking::getAnalysisUsage(AnalysisUsage &AU) const { |
|
51 |
+ AU.addRequiredTransitive<DominatorTree>(); |
|
52 |
+ AU.addRequiredTransitive<LoopInfo>(); |
|
53 |
+ AU.addRequiredTransitive<ScalarEvolution>(); |
|
54 |
+ AU.setPreservesAll(); |
|
55 |
+} |
|
56 |
+ |
|
57 |
+bool PointerTracking::doInitialization(Module &M) { |
|
58 |
+ const Type *PTy = Type::getInt8PtrTy(M.getContext()); |
|
59 |
+ |
|
60 |
+ // Find calloc(i64, i64) or calloc(i32, i32). |
|
61 |
+ callocFunc = M.getFunction("calloc"); |
|
62 |
+ if (callocFunc) { |
|
63 |
+ const FunctionType *Ty = callocFunc->getFunctionType(); |
|
64 |
+ |
|
65 |
+ std::vector<const Type*> args, args2; |
|
66 |
+ args.push_back(Type::getInt64Ty(M.getContext())); |
|
67 |
+ args.push_back(Type::getInt64Ty(M.getContext())); |
|
68 |
+ args2.push_back(Type::getInt32Ty(M.getContext())); |
|
69 |
+ args2.push_back(Type::getInt32Ty(M.getContext())); |
|
70 |
+ const FunctionType *Calloc1Type = |
|
71 |
+ FunctionType::get(PTy, args, false); |
|
72 |
+ const FunctionType *Calloc2Type = |
|
73 |
+ FunctionType::get(PTy, args2, false); |
|
74 |
+ if (Ty != Calloc1Type && Ty != Calloc2Type) |
|
75 |
+ callocFunc = 0; // Give up |
|
76 |
+ } |
|
77 |
+ |
|
78 |
+ // Find realloc(i8*, i64) or realloc(i8*, i32). |
|
79 |
+ reallocFunc = M.getFunction("realloc"); |
|
80 |
+ if (reallocFunc) { |
|
81 |
+ const FunctionType *Ty = reallocFunc->getFunctionType(); |
|
82 |
+ std::vector<const Type*> args, args2; |
|
83 |
+ args.push_back(PTy); |
|
84 |
+ args.push_back(Type::getInt64Ty(M.getContext())); |
|
85 |
+ args2.push_back(PTy); |
|
86 |
+ args2.push_back(Type::getInt32Ty(M.getContext())); |
|
87 |
+ |
|
88 |
+ const FunctionType *Realloc1Type = |
|
89 |
+ FunctionType::get(PTy, args, false); |
|
90 |
+ const FunctionType *Realloc2Type = |
|
91 |
+ FunctionType::get(PTy, args2, false); |
|
92 |
+ if (Ty != Realloc1Type && Ty != Realloc2Type) |
|
93 |
+ reallocFunc = 0; // Give up |
|
94 |
+ } |
|
95 |
+ return false; |
|
96 |
+} |
|
97 |
+ |
|
98 |
+// Calculates the number of elements allocated for pointer P, |
|
99 |
+// the type of the element is stored in Ty. |
|
100 |
+const SCEV *PointerTracking::computeAllocationCount(Value *P, |
|
101 |
+ const Type *&Ty) const { |
|
102 |
+ Value *V = P->stripPointerCasts(); |
|
103 |
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) { |
|
104 |
+ Value *arraySize = AI->getArraySize(); |
|
105 |
+ Ty = AI->getAllocatedType(); |
|
106 |
+ // arraySize elements of type Ty. |
|
107 |
+ return SE->getSCEV(arraySize); |
|
108 |
+ } |
|
109 |
+ |
|
110 |
+ if (CallInst *CI = extractMallocCall(V)) { |
|
111 |
+ Value *arraySize = getMallocArraySize(CI, TD); |
|
112 |
+ const Type* AllocTy = getMallocAllocatedType(CI); |
|
113 |
+ if (!AllocTy || !arraySize) return SE->getCouldNotCompute(); |
|
114 |
+ Ty = AllocTy; |
|
115 |
+ // arraySize elements of type Ty. |
|
116 |
+ return SE->getSCEV(arraySize); |
|
117 |
+ } |
|
118 |
+ |
|
119 |
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { |
|
120 |
+ if (GV->hasDefinitiveInitializer()) { |
|
121 |
+ Constant *C = GV->getInitializer(); |
|
122 |
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) { |
|
123 |
+ Ty = ATy->getElementType(); |
|
124 |
+ return SE->getConstant(Type::getInt32Ty(P->getContext()), |
|
125 |
+ ATy->getNumElements()); |
|
126 |
+ } |
|
127 |
+ } |
|
128 |
+ Ty = GV->getType(); |
|
129 |
+ return SE->getConstant(Type::getInt32Ty(P->getContext()), 1); |
|
130 |
+ //TODO: implement more tracking for globals |
|
131 |
+ } |
|
132 |
+ |
|
133 |
+ if (CallInst *CI = dyn_cast<CallInst>(V)) { |
|
134 |
+ CallSite CS(CI); |
|
135 |
+ Function *F = dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts()); |
|
136 |
+ const Loop *L = LI->getLoopFor(CI->getParent()); |
|
137 |
+ if (F == callocFunc) { |
|
138 |
+ Ty = Type::getInt8Ty(P->getContext()); |
|
139 |
+ // calloc allocates arg0*arg1 bytes. |
|
140 |
+ return SE->getSCEVAtScope(SE->getMulExpr(SE->getSCEV(CS.getArgument(0)), |
|
141 |
+ SE->getSCEV(CS.getArgument(1))), |
|
142 |
+ L); |
|
143 |
+ } else if (F == reallocFunc) { |
|
144 |
+ Ty = Type::getInt8Ty(P->getContext()); |
|
145 |
+ // realloc allocates arg1 bytes. |
|
146 |
+ return SE->getSCEVAtScope(CS.getArgument(1), L); |
|
147 |
+ } |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ return SE->getCouldNotCompute(); |
|
151 |
+} |
|
152 |
+ |
|
153 |
+Value *PointerTracking::computeAllocationCountValue(Value *P, const Type *&Ty) const |
|
154 |
+{ |
|
155 |
+ Value *V = P->stripPointerCasts(); |
|
156 |
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) { |
|
157 |
+ Ty = AI->getAllocatedType(); |
|
158 |
+ // arraySize elements of type Ty. |
|
159 |
+ return AI->getArraySize(); |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ if (CallInst *CI = extractMallocCall(V)) { |
|
163 |
+ Ty = getMallocAllocatedType(CI); |
|
164 |
+ if (!Ty) |
|
165 |
+ return 0; |
|
166 |
+ Value *arraySize = getMallocArraySize(CI, TD); |
|
167 |
+ if (!arraySize) { |
|
168 |
+ Ty = Type::getInt8Ty(P->getContext()); |
|
169 |
+ return CI->getArgOperand(0); |
|
170 |
+ } |
|
171 |
+ // arraySize elements of type Ty. |
|
172 |
+ return arraySize; |
|
173 |
+ } |
|
174 |
+ |
|
175 |
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { |
|
176 |
+ if (GV->hasDefinitiveInitializer()) { |
|
177 |
+ Constant *C = GV->getInitializer(); |
|
178 |
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) { |
|
179 |
+ Ty = ATy->getElementType(); |
|
180 |
+ return ConstantInt::get(Type::getInt32Ty(P->getContext()), |
|
181 |
+ ATy->getNumElements()); |
|
182 |
+ } |
|
183 |
+ } |
|
184 |
+ Ty = cast<PointerType>(GV->getType())->getElementType(); |
|
185 |
+ return ConstantInt::get(Type::getInt32Ty(P->getContext()), 1); |
|
186 |
+ //TODO: implement more tracking for globals |
|
187 |
+ } |
|
188 |
+ |
|
189 |
+ if (CallInst *CI = dyn_cast<CallInst>(V)) { |
|
190 |
+ CallSite CS(CI); |
|
191 |
+ Function *F = dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts()); |
|
192 |
+ if (F == reallocFunc) { |
|
193 |
+ Ty = Type::getInt8Ty(P->getContext()); |
|
194 |
+ // realloc allocates arg1 bytes. |
|
195 |
+ return CS.getArgument(1); |
|
196 |
+ } |
|
197 |
+ } |
|
198 |
+ |
|
199 |
+ return 0; |
|
200 |
+} |
|
201 |
+ |
|
202 |
+// Calculates the number of elements of type Ty allocated for P. |
|
203 |
+const SCEV *PointerTracking::computeAllocationCountForType(Value *P, |
|
204 |
+ const Type *Ty) |
|
205 |
+ const { |
|
206 |
+ const Type *elementTy; |
|
207 |
+ const SCEV *Count = computeAllocationCount(P, elementTy); |
|
208 |
+ if (isa<SCEVCouldNotCompute>(Count)) |
|
209 |
+ return Count; |
|
210 |
+ if (elementTy == Ty) |
|
211 |
+ return Count; |
|
212 |
+ |
|
213 |
+ if (!TD) // need TargetData from this point forward |
|
214 |
+ return SE->getCouldNotCompute(); |
|
215 |
+ |
|
216 |
+ uint64_t elementSize = TD->getTypeAllocSize(elementTy); |
|
217 |
+ uint64_t wantSize = TD->getTypeAllocSize(Ty); |
|
218 |
+ if (elementSize == wantSize) |
|
219 |
+ return Count; |
|
220 |
+ if (elementSize % wantSize) //fractional counts not possible |
|
221 |
+ return SE->getCouldNotCompute(); |
|
222 |
+ return SE->getMulExpr(Count, SE->getConstant(Count->getType(), |
|
223 |
+ elementSize/wantSize)); |
|
224 |
+} |
|
225 |
+ |
|
226 |
+const SCEV *PointerTracking::getAllocationElementCount(Value *V) const { |
|
227 |
+ // We only deal with pointers. |
|
228 |
+ const PointerType *PTy = cast<PointerType>(V->getType()); |
|
229 |
+ return computeAllocationCountForType(V, PTy->getElementType()); |
|
230 |
+} |
|
231 |
+ |
|
232 |
+const SCEV *PointerTracking::getAllocationSizeInBytes(Value *V) const { |
|
233 |
+ return computeAllocationCountForType(V, Type::getInt8Ty(V->getContext())); |
|
234 |
+} |
|
235 |
+ |
|
236 |
+// Helper for isLoopGuardedBy that checks the swapped and inverted predicate too |
|
237 |
+enum SolverResult PointerTracking::isLoopGuardedBy(const Loop *L, |
|
238 |
+ Predicate Pred, |
|
239 |
+ const SCEV *A, |
|
240 |
+ const SCEV *B) const { |
|
241 |
+ if (SE->isLoopEntryGuardedByCond(L, Pred, A, B)) |
|
242 |
+ return AlwaysTrue; |
|
243 |
+ Pred = ICmpInst::getSwappedPredicate(Pred); |
|
244 |
+ if (SE->isLoopEntryGuardedByCond(L, Pred, B, A)) |
|
245 |
+ return AlwaysTrue; |
|
246 |
+ |
|
247 |
+ Pred = ICmpInst::getInversePredicate(Pred); |
|
248 |
+ if (SE->isLoopEntryGuardedByCond(L, Pred, B, A)) |
|
249 |
+ return AlwaysFalse; |
|
250 |
+ Pred = ICmpInst::getSwappedPredicate(Pred); |
|
251 |
+ if (SE->isLoopEntryGuardedByCond(L, Pred, A, B)) |
|
252 |
+ return AlwaysTrue; |
|
253 |
+ return Unknown; |
|
254 |
+} |
|
255 |
+ |
|
256 |
+enum SolverResult PointerTracking::checkLimits(const SCEV *Offset, |
|
257 |
+ const SCEV *Limit, |
|
258 |
+ BasicBlock *BB) |
|
259 |
+{ |
|
260 |
+ //FIXME: merge implementation |
|
261 |
+ return Unknown; |
|
262 |
+} |
|
263 |
+ |
|
264 |
+void PointerTracking::getPointerOffset(Value *Pointer, Value *&Base, |
|
265 |
+ const SCEV *&Limit, |
|
266 |
+ const SCEV *&Offset) const |
|
267 |
+{ |
|
268 |
+ Pointer = Pointer->stripPointerCasts(); |
|
269 |
+ Base = GetUnderlyingObject(Pointer, TD); |
|
270 |
+ Limit = getAllocationSizeInBytes(Base); |
|
271 |
+ if (isa<SCEVCouldNotCompute>(Limit)) { |
|
272 |
+ Base = 0; |
|
273 |
+ Offset = Limit; |
|
274 |
+ return; |
|
275 |
+ } |
|
276 |
+ |
|
277 |
+ Offset = SE->getMinusSCEV(SE->getSCEV(Pointer), SE->getSCEV(Base)); |
|
278 |
+ if (isa<SCEVCouldNotCompute>(Offset)) { |
|
279 |
+ Base = 0; |
|
280 |
+ Limit = Offset; |
|
281 |
+ } |
|
282 |
+} |
|
283 |
+ |
|
284 |
+void PointerTracking::print(raw_ostream &OS, const Module* M) const { |
|
285 |
+ // Calling some PT methods may cause caches to be updated, however |
|
286 |
+ // this should be safe for the same reason its safe for SCEV. |
|
287 |
+ PointerTracking &PT = *const_cast<PointerTracking*>(this); |
|
288 |
+ for (inst_iterator I=inst_begin(*FF), E=inst_end(*FF); I != E; ++I) { |
|
289 |
+ if (!I->getType()->isPointerTy()) |
|
290 |
+ continue; |
|
291 |
+ Value *Base; |
|
292 |
+ const SCEV *Limit, *Offset; |
|
293 |
+ getPointerOffset(&*I, Base, Limit, Offset); |
|
294 |
+ if (!Base) |
|
295 |
+ continue; |
|
296 |
+ |
|
297 |
+ if (Base == &*I) { |
|
298 |
+ const SCEV *S = getAllocationElementCount(Base); |
|
299 |
+ OS << *Base << " ==> " << *S << " elements, "; |
|
300 |
+ OS << *Limit << " bytes allocated\n"; |
|
301 |
+ continue; |
|
302 |
+ } |
|
303 |
+ OS << &*I << " -- base: " << *Base; |
|
304 |
+ OS << " offset: " << *Offset; |
|
305 |
+ |
|
306 |
+ enum SolverResult res = PT.checkLimits(Offset, Limit, I->getParent()); |
|
307 |
+ switch (res) { |
|
308 |
+ case AlwaysTrue: |
|
309 |
+ OS << " always safe\n"; |
|
310 |
+ break; |
|
311 |
+ case AlwaysFalse: |
|
312 |
+ OS << " always unsafe\n"; |
|
313 |
+ break; |
|
314 |
+ case Unknown: |
|
315 |
+ OS << " <<unknown>>\n"; |
|
316 |
+ break; |
|
317 |
+ } |
|
318 |
+ } |
|
319 |
+} |
|
320 |
+ |
0 | 321 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,132 @@ |
0 |
+//===- PointerTracking.h - Pointer Bounds Tracking --------------*- C++ -*-===// |
|
1 |
+// |
|
2 |
+// The LLVM Compiler Infrastructure |
|
3 |
+// |
|
4 |
+// This file is distributed under the University of Illinois Open Source |
|
5 |
+// License. See LICENSE.TXT for details. |
|
6 |
+// |
|
7 |
+//===----------------------------------------------------------------------===// |
|
8 |
+// |
|
9 |
+// This file implements tracking of pointer bounds. |
|
10 |
+// It knows that the libc functions "calloc" and "realloc" allocate memory, thus |
|
11 |
+// you should avoid using this pass if they mean something else for your |
|
12 |
+// language. |
|
13 |
+// |
|
14 |
+// All methods assume that the pointer is not NULL, if it is then the returned |
|
15 |
+// allocation size is wrong, and the result from checkLimits is wrong too. |
|
16 |
+// It also assumes that pointers are valid, and that it is not analyzing a |
|
17 |
+// use-after-free scenario. |
|
18 |
+// Due to these limitations the "size" returned by these methods should be |
|
19 |
+// considered as either 0 or the returned size. |
|
20 |
+// |
|
21 |
+// Another analysis pass should be used to find use-after-free/NULL dereference |
|
22 |
+// bugs. |
|
23 |
+// |
|
24 |
+//===----------------------------------------------------------------------===// |
|
25 |
+ |
|
26 |
+#ifndef LLVM_ANALYSIS_POINTERTRACKING_H |
|
27 |
+#define LLVM_ANALYSIS_POINTERTRACKING_H |
|
28 |
+ |
|
29 |
+#include "llvm/ADT/SmallPtrSet.h" |
|
30 |
+#include "llvm/Analysis/Dominators.h" |
|
31 |
+#include "llvm/Instructions.h" |
|
32 |
+#include "llvm/Pass.h" |
|
33 |
+#include "llvm/Support/PredIteratorCache.h" |
|
34 |
+ |
|
35 |
+namespace llvm { |
|
36 |
+ class DominatorTree; |
|
37 |
+ class ScalarEvolution; |
|
38 |
+ class SCEV; |
|
39 |
+ class Loop; |
|
40 |
+ class LoopInfo; |
|
41 |
+ class TargetData; |
|
42 |
+ |
|
43 |
+ // Result from solver, assuming pointer is not NULL, |
|
44 |
+ // and it is not a use-after-free situation. |
|
45 |
+ enum SolverResult { |
|
46 |
+ AlwaysFalse,// always false with above constraints |
|
47 |
+ AlwaysTrue,// always true with above constraints |
|
48 |
+ Unknown // it can sometimes be true, sometimes false, or it is undecided |
|
49 |
+ }; |
|
50 |
+ |
|
51 |
+ class PointerTracking : public FunctionPass { |
|
52 |
+ public: |
|
53 |
+ typedef ICmpInst::Predicate Predicate; |
|
54 |
+ static char ID; |
|
55 |
+ PointerTracking(); |
|
56 |
+ |
|
57 |
+ virtual bool doInitialization(Module &M); |
|
58 |
+ |
|
59 |
+ // If this pointer directly points to an allocation, return |
|
60 |
+ // the number of elements of type Ty allocated. |
|
61 |
+ // Otherwise return CouldNotCompute. |
|
62 |
+ // Since allocations can fail by returning NULL, the real element count |
|
63 |
+ // for every allocation is either 0 or the value returned by this function. |
|
64 |
+ const SCEV *getAllocationElementCount(Value *P) const; |
|
65 |
+ |
|
66 |
+ // Same as getAllocationSize() but returns size in bytes. |
|
67 |
+ // We consider one byte as 8 bits. |
|
68 |
+ const SCEV *getAllocationSizeInBytes(Value *V) const; |
|
69 |
+ |
|
70 |
+ // Given a Pointer, determine a base pointer of known size, and an offset |
|
71 |
+ // therefrom. |
|
72 |
+ // When unable to determine, sets Base to NULL, and Limit/Offset to |
|
73 |
+ // CouldNotCompute. |
|
74 |
+ // BaseSize, and Offset are in bytes: Pointer == Base + Offset |
|
75 |
+ void getPointerOffset(Value *Pointer, Value *&Base, const SCEV *& BaseSize, |
|
76 |
+ const SCEV *&Offset) const; |
|
77 |
+ |
|
78 |
+ // Compares the 2 scalar evolution expressions according to predicate, |
|
79 |
+ // and if it can prove that the result is always true or always false |
|
80 |
+ // return AlwaysTrue/AlwaysFalse. Otherwise it returns Unknown. |
|
81 |
+ enum SolverResult compareSCEV(const SCEV *A, Predicate Pred, const SCEV *B, |
|
82 |
+ const Loop *L); |
|
83 |
+ |
|
84 |
+ // Determines whether the condition LHS <Pred> RHS is sufficient |
|
85 |
+ // for the condition A <Pred> B to hold. |
|
86 |
+ // Currently only ULT/ULE is supported. |
|
87 |
+ // This errs on the side of returning false. |
|
88 |
+ bool conditionSufficient(const SCEV *LHS, Predicate Pred1, const SCEV *RHS, |
|
89 |
+ const SCEV *A, Predicate Pred2, const SCEV *B, |
|
90 |
+ const Loop *L); |
|
91 |
+ |
|
92 |
+ // Determines whether Offset is known to be always in [0, Limit) bounds. |
|
93 |
+ // This errs on the side of returning Unknown. |
|
94 |
+ enum SolverResult checkLimits(const SCEV *Offset, const SCEV *Limit, |
|
95 |
+ BasicBlock *BB); |
|
96 |
+ |
|
97 |
+ virtual bool runOnFunction(Function &F); |
|
98 |
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const; |
|
99 |
+ void print(raw_ostream &OS, const Module* = 0) const; |
|
100 |
+ Value *computeAllocationCountValue(Value *P, const Type *&Ty) const; |
|
101 |
+ private: |
|
102 |
+ Function *FF; |
|
103 |
+ TargetData *TD; |
|
104 |
+ ScalarEvolution *SE; |
|
105 |
+ LoopInfo *LI; |
|
106 |
+ DominatorTree *DT; |
|
107 |
+ |
|
108 |
+ Function *callocFunc; |
|
109 |
+ Function *reallocFunc; |
|
110 |
+ PredIteratorCache predCache; |
|
111 |
+ |
|
112 |
+ SmallPtrSet<const SCEV*, 1> analyzing; |
|
113 |
+ |
|
114 |
+ enum SolverResult isLoopGuardedBy(const Loop *L, Predicate Pred, |
|
115 |
+ const SCEV *A, const SCEV *B) const; |
|
116 |
+ static bool isMonotonic(const SCEV *S); |
|
117 |
+ bool scevPositive(const SCEV *A, const Loop *L, bool strict=true) const; |
|
118 |
+ bool conditionSufficient(Value *Cond, bool negated, |
|
119 |
+ const SCEV *A, Predicate Pred, const SCEV *B); |
|
120 |
+ Value *getConditionToReach(BasicBlock *A, |
|
121 |
+ DomTreeNodeBase<BasicBlock> *B, |
|
122 |
+ bool &negated); |
|
123 |
+ Value *getConditionToReach(BasicBlock *A, |
|
124 |
+ BasicBlock *B, |
|
125 |
+ bool &negated); |
|
126 |
+ const SCEV *computeAllocationCount(Value *P, const Type *&Ty) const; |
|
127 |
+ const SCEV *computeAllocationCountForType(Value *P, const Type *Ty) const; |
|
128 |
+ }; |
|
129 |
+} |
|
130 |
+#endif |
|
131 |
+ |
... | ... |
@@ -59,13 +59,29 @@ |
59 | 59 |
#include "llvm/Support/SourceMgr.h" |
60 | 60 |
#include "llvm/Support/IRBuilder.h" |
61 | 61 |
#include "llvm/Support/PrettyStackTrace.h" |
62 |
+ |
|
63 |
+#ifdef LLVM29 |
|
64 |
+#include "llvm/Support/DataTypes.h" |
|
65 |
+#include "llvm/Support/FileSystem.h" |
|
66 |
+#include "llvm/Support/Host.h" |
|
67 |
+#include "llvm/Support/Memory.h" |
|
68 |
+#include "llvm/Support/Mutex.h" |
|
69 |
+#include "llvm/Support/Signals.h" |
|
70 |
+#include "llvm/Support/Threading.h" |
|
71 |
+#include "llvm/Support/ThreadLocal.h" |
|
72 |
+#include "llvm/IntrinsicInst.h" |
|
73 |
+#include "llvm/PassRegistry.h" |
|
74 |
+#else |
|
62 | 75 |
#include "llvm/System/DataTypes.h" |
63 | 76 |
#include "llvm/System/Host.h" |
64 | 77 |
#include "llvm/System/Memory.h" |
65 | 78 |
#include "llvm/System/Mutex.h" |
66 | 79 |
#include "llvm/System/Signals.h" |
67 |
-#include "llvm/Support/Timer.h" |
|
68 | 80 |
#include "llvm/System/Threading.h" |
81 |
+#include "llvm/System/ThreadLocal.h" |
|
82 |
+#endif |
|
83 |
+ |
|
84 |
+#include "llvm/Support/Timer.h" |
|
69 | 85 |
|
70 | 86 |
extern "C" { |
71 | 87 |
void LLVMInitializeX86AsmPrinter(); |
... | ... |
@@ -78,7 +94,6 @@ void LLVMInitializePowerPCAsmPrinter(); |
78 | 78 |
#include "llvm/Transforms/Scalar.h" |
79 | 79 |
#include "llvm/Transforms/IPO.h" |
80 | 80 |
#include "llvm/Transforms/Utils/BasicBlockUtils.h" |
81 |
-#include "llvm/System/ThreadLocal.h" |
|
82 | 81 |
#include <cstdlib> |
83 | 82 |
#include <csetjmp> |
84 | 83 |
#include <new> |
... | ... |
@@ -133,6 +148,11 @@ struct cli_bcengine { |
133 | 133 |
}; |
134 | 134 |
|
135 | 135 |
extern "C" uint8_t cli_debug_flag; |
136 |
+#ifdef LLVM29 |
|
137 |
+namespace llvm { |
|
138 |
+ void initializeRuntimeLimitsPass(PassRegistry&); |
|
139 |
+}; |
|
140 |
+#endif |
|
136 | 141 |
namespace { |
137 | 142 |
|
138 | 143 |
#ifndef LLVM28 |
... | ... |
@@ -149,6 +169,10 @@ namespace { |
149 | 149 |
#define DEFINEPASS(passname) passname() : FunctionPass(&ID) |
150 | 150 |
#endif |
151 | 151 |
|
152 |
+#ifdef LLVM29 |
|
153 |
+#define NORETURN LLVM_ATTRIBUTE_NORETURN |
|
154 |
+#endif |
|
155 |
+ |
|
152 | 156 |
static sys::ThreadLocal<const jmp_buf> ExceptionReturn; |
153 | 157 |
|
154 | 158 |
static void UpgradeCall(CallInst *&C, Function *Intr) |
... | ... |
@@ -526,7 +550,12 @@ class RuntimeLimits : public FunctionPass { |
526 | 526 |
|
527 | 527 |
public: |
528 | 528 |
static char ID; |
529 |
- DEFINEPASS(RuntimeLimits) {} |
|
529 |
+ DEFINEPASS(RuntimeLimits) { |
|
530 |
+#ifdef LLVM29 |
|
531 |
+ PassRegistry &Registry = *PassRegistry::getPassRegistry(); |
|
532 |
+ initializeRuntimeLimitsPass(Registry); |
|
533 |
+#endif |
|
534 |
+ } |
|
530 | 535 |
|
531 | 536 |
virtual bool runOnFunction(Function &F) { |
532 | 537 |
BBSetTy BackedgeTargets; |
... | ... |
@@ -1043,12 +1072,18 @@ public: |
1043 | 1043 |
// Have an alloca -> some instruction uses its address otherwise |
1044 | 1044 |
// mem2reg would have converted it to an SSA register. |
1045 | 1045 |
// Enable stack protector for this function. |
1046 |
+#ifndef LLVM29 |
|
1047 |
+ // LLVM 2.9 has broken SSP, it does a 'mov 0x28, $rax', which tries |
|
1048 |
+ // to read from the address 0x28 and crashes |
|
1046 | 1049 |
F->addFnAttr(Attribute::StackProtectReq); |
1050 |
+#endif |
|
1047 | 1051 |
} |
1048 | 1052 |
// always add stackprotect attribute (bb #2239), so we know this |
1049 | 1053 |
// function was verified. If there is no alloca it won't actually add |
1050 | 1054 |
// stack protector in emitted code so this won't slow down the app. |
1055 |
+#ifndef LLVM29 |
|
1051 | 1056 |
F->addFnAttr(Attribute::StackProtect); |
1057 |
+#endif |
|
1052 | 1058 |
} |
1053 | 1059 |
|
1054 | 1060 |
Value *GEPOperand(Value *V) { |
... | ... |
@@ -1830,6 +1865,13 @@ static void addFunctionProtos(struct CommonFunctions *CF, ExecutionEngine *EE, M |
1830 | 1830 |
} |
1831 | 1831 |
|
1832 | 1832 |
} |
1833 |
+#ifdef LLVM29 |
|
1834 |
+INITIALIZE_PASS_BEGIN(RuntimeLimits, "rl", "Runtime Limits", false, false) |
|
1835 |
+INITIALIZE_PASS_DEPENDENCY(LoopInfo) |
|
1836 |
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolution) |
|
1837 |
+INITIALIZE_PASS_DEPENDENCY(DominatorTree) |
|
1838 |
+INITIALIZE_PASS_END(RuntimeLimits, "rl" ,"Runtime Limits", false, false) |
|
1839 |
+#endif |
|
1833 | 1840 |
|
1834 | 1841 |
static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER; |
1835 | 1842 |
static pthread_cond_t watchdog_cond = PTHREAD_COND_INITIALIZER; |
... | ... |
@@ -2179,7 +2221,9 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs) |
2179 | 2179 |
PM.add(createCFGSimplificationPass()); |
2180 | 2180 |
PM.add(createGlobalOptimizerPass()); |
2181 | 2181 |
PM.add(createConstantMergePass()); |
2182 |
- PM.add(new RuntimeLimits()); |
|
2182 |
+ |
|
2183 |
+ RuntimeLimits *RL = new RuntimeLimits(); |
|
2184 |
+ PM.add(RL); |
|
2183 | 2185 |
TimerWrapper pmTimer2("Transform passes"); |
2184 | 2186 |
pmTimer2.startTimer(); |
2185 | 2187 |
PM.run(*M); |
... | ... |
@@ -2327,7 +2371,17 @@ void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx) |
2327 | 2327 |
if (I == LinePrinter.files.end()) { |
2328 | 2328 |
lines = new linesTy; |
2329 | 2329 |
std::string ErrorMessage; |
2330 |
+#ifdef LLVM29 |
|
2331 |
+ OwningPtr<MemoryBuffer> File; |
|
2332 |
+ error_code ec = MemoryBuffer::getFile(path, File); |
|
2333 |
+ if (ec) { |
|
2334 |
+ ErrorMessage = ec.message(); |
|
2335 |
+ lines->buffer = 0; |
|
2336 |
+ } else |
|
2337 |
+ lines->buffer = File.take(); |
|
2338 |
+#else |
|
2330 | 2339 |
lines->buffer = MemoryBuffer::getFile(path, &ErrorMessage); |
2340 |
+#endif |
|
2331 | 2341 |
if (!lines->buffer) { |
2332 | 2342 |
errs() << "Unable to open file '" << path << "'\n"; |
2333 | 2343 |
return ; |
... | ... |
@@ -2401,6 +2455,117 @@ void stop(const char *msg, llvm::Function* F, llvm::Instruction* I) |
2401 | 2401 |
} |
2402 | 2402 |
} |
2403 | 2403 |
|
2404 |
+#ifdef LLVM29 |
|
2405 |
+static Value *findDbgGlobalDeclare(GlobalVariable *V) { |
|
2406 |
+ const Module *M = V->getParent(); |
|
2407 |
+ NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"); |
|
2408 |
+ if (!NMD) |
|
2409 |
+ return 0; |
|
2410 |
+ |
|
2411 |
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { |
|
2412 |
+ DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i))); |
|
2413 |
+ if (!DIG.isGlobalVariable()) |
|
2414 |
+ continue; |
|
2415 |
+ if (DIGlobalVariable(DIG).getGlobal() == V) |
|
2416 |
+ return DIG; |
|
2417 |
+ } |
|
2418 |
+ return 0; |
|
2419 |
+} |
|
2420 |
+ |
|
2421 |
+/// Find the debug info descriptor corresponding to this function. |
|
2422 |
+static Value *findDbgSubprogramDeclare(Function *V) { |
|
2423 |
+ const Module *M = V->getParent(); |
|
2424 |
+ NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"); |
|
2425 |
+ if (!NMD) |
|
2426 |
+ return 0; |
|
2427 |
+ |
|
2428 |
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { |
|
2429 |
+ DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i))); |
|
2430 |
+ if (!DIG.isSubprogram()) |
|
2431 |
+ continue; |
|
2432 |
+ if (DISubprogram(DIG).getFunction() == V) |
|
2433 |
+ return DIG; |
|
2434 |
+ } |
|
2435 |
+ return 0; |
|
2436 |
+} |
|
2437 |
+ |
|
2438 |
+/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any. |
|
2439 |
+/// It looks through pointer casts too. |
|
2440 |
+static const DbgDeclareInst *findDbgDeclare(const Value *V) { |
|
2441 |
+ V = V->stripPointerCasts(); |
|
2442 |
+ |
|
2443 |
+ if (!isa<Instruction>(V) && !isa<Argument>(V)) |
|
2444 |
+ return 0; |
|
2445 |
+ |
|
2446 |
+ const Function *F = NULL; |
|
2447 |
+ if (const Instruction *I = dyn_cast<Instruction>(V)) |
|
2448 |
+ F = I->getParent()->getParent(); |
|
2449 |
+ else if (const Argument *A = dyn_cast<Argument>(V)) |
|
2450 |
+ F = A->getParent(); |
|
2451 |
+ |
|
2452 |
+ for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) |
|
2453 |
+ for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end(); |
|
2454 |
+ BI != BE; ++BI) |
|
2455 |
+ if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) |
|
2456 |
+ if (DDI->getAddress() == V) |
|
2457 |
+ return DDI; |
|
2458 |
+ |
|
2459 |
+ return 0; |
|
2460 |
+} |
|
2461 |
+static bool getLocationInfo(const Value *V, std::string &DisplayName, |
|
2462 |
+ std::string &Type, unsigned &LineNo, |
|
2463 |
+ std::string &File, std::string &Dir) { |
|
2464 |
+ DICompileUnit Unit; |
|
2465 |
+ DIType TypeD; |
|
2466 |
+ |
|
2467 |
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(const_cast<Value*>(V))) { |
|
2468 |
+ Value *DIGV = findDbgGlobalDeclare(GV); |
|
2469 |
+ if (!DIGV) return false; |
|
2470 |
+ DIGlobalVariable Var(cast<MDNode>(DIGV)); |
|
2471 |
+ |
|
2472 |
+ StringRef D = Var.getDisplayName(); |
|
2473 |
+ if (!D.empty()) |
|
2474 |
+ DisplayName = D; |
|
2475 |
+ LineNo = Var.getLineNumber(); |
|
2476 |
+ Unit = Var.getCompileUnit(); |
|
2477 |
+ TypeD = Var.getType(); |
|
2478 |
+ } else if (Function *F = dyn_cast<Function>(const_cast<Value*>(V))){ |
|
2479 |
+ Value *DIF = findDbgSubprogramDeclare(F); |
|
2480 |
+ if (!DIF) return false; |
|
2481 |
+ DISubprogram Var(cast<MDNode>(DIF)); |
|
2482 |
+ |
|
2483 |
+ StringRef D = Var.getDisplayName(); |
|
2484 |
+ if (!D.empty()) |
|
2485 |
+ DisplayName = D; |
|
2486 |
+ LineNo = Var.getLineNumber(); |
|
2487 |
+ Unit = Var.getCompileUnit(); |
|
2488 |
+ TypeD = Var.getType(); |
|
2489 |
+ } else { |
|
2490 |
+ const DbgDeclareInst *DDI = findDbgDeclare(V); |
|
2491 |
+ if (!DDI) return false; |
|
2492 |
+ DIVariable Var(cast<MDNode>(DDI->getVariable())); |
|
2493 |
+ |
|
2494 |
+ StringRef D = Var.getName(); |
|
2495 |
+ if (!D.empty()) |
|
2496 |
+ DisplayName = D; |
|
2497 |
+ LineNo = Var.getLineNumber(); |
|
2498 |
+ Unit = Var.getCompileUnit(); |
|
2499 |
+ TypeD = Var.getType(); |
|
2500 |
+ } |
|
2501 |
+ |
|
2502 |
+ StringRef T = TypeD.getName(); |
|
2503 |
+ if (!T.empty()) |
|
2504 |
+ Type = T; |
|
2505 |
+ StringRef F = Unit.getFilename(); |
|
2506 |
+ if (!F.empty()) |
|
2507 |
+ File = F; |
|
2508 |
+ StringRef D = Unit.getDirectory(); |
|
2509 |
+ if (!D.empty()) |
|
2510 |
+ Dir = D; |
|
2511 |
+ return true; |
|
2512 |
+} |
|
2513 |
+#endif |
|
2514 |
+ |
|
2404 | 2515 |
void printValue(llvm::Value *V, bool a, bool b) { |
2405 | 2516 |
std::string DisplayName; |
2406 | 2517 |
std::string Type; |
... | ... |
@@ -15370,8 +15370,8 @@ if test "${with_system_llvm+set}" = set; then : |
15370 | 15370 |
*) |
15371 | 15371 |
llvmconfig="$withval" |
15372 | 15372 |
llvmver=`$llvmconfig --version` |
15373 |
- if test "$llvmver" != "2.8" -a "$llvmver" != "2.8svn" -a "$llvmver" != "2.8rc"; then |
|
15374 |
- as_fn_error $? "LLVM 2.8 or 2.8svn required, but \"$llvmver\" found" "$LINENO" 5 |
|
15373 |
+ if test "$llvmver" != "2.9"; then |
|
15374 |
+ as_fn_error $? "LLVM 2.9 required, but \"$llvmver\" found" "$LINENO" 5 |
|
15375 | 15375 |
fi |
15376 | 15376 |
LLVMCONFIG_CXXFLAGS=`$llvmconfig --cxxflags` |
15377 | 15377 |
|
... | ... |
@@ -59,8 +59,8 @@ AC_ARG_WITH([system-llvm], AC_HELP_STRING([-with-system-llvm], |
59 | 59 |
*) |
60 | 60 |
llvmconfig="$withval" |
61 | 61 |
llvmver=`$llvmconfig --version` |
62 |
- if test "$llvmver" != "2.8" -a "$llvmver" != "2.8svn" -a "$llvmver" != "2.8rc"; then |
|
63 |
- AC_MSG_ERROR([LLVM 2.8 or 2.8svn required, but "$llvmver" found]) |
|
62 |
+ if test "$llvmver" != "2.9"; then |
|
63 |
+ AC_MSG_ERROR([LLVM 2.9 required, but "$llvmver" found]) |
|
64 | 64 |
fi |
65 | 65 |
AC_SUBST(LLVMCONFIG_CXXFLAGS, [`$llvmconfig --cxxflags`]) |
66 | 66 |
AC_SUBST(LLVMCONFIG_LDFLAGS, [`$llvmconfig --ldflags`]) |
... | ... |
@@ -22,9 +22,16 @@ |
22 | 22 |
|
23 | 23 |
#include "llvm/ADT/Triple.h" |
24 | 24 |
#include "llvm/Support/raw_ostream.h" |
25 |
+#ifdef LLVM29 |
|
26 |
+#include "llvm/Support/Host.h" |
|
27 |
+#include "llvm/Support/DataTypes.h" |
|
28 |
+#include "llvm/Support/Memory.h" |
|
29 |
+#else |
|
25 | 30 |
#include "llvm/System/Host.h" |
26 | 31 |
#include "llvm/System/DataTypes.h" |
27 | 32 |
#include "llvm/System/Memory.h" |
33 |
+#endif |
|
34 |
+ |
|
28 | 35 |
#include "llvm/Config/config.h" |
29 | 36 |
|
30 | 37 |
extern "C" { |
... | ... |
@@ -137,7 +144,9 @@ void cli_detect_env_jit(struct cli_environment *env) |
137 | 137 |
CASE_OS(Linux, os_linux); |
138 | 138 |
CASE_OS(Lv2, os_unknown); |
139 | 139 |
CASE_OS(MinGW32, os_win32); |
140 |
+#ifndef LLVM29 |
|
140 | 141 |
CASE_OS(MinGW64, os_win64); |
142 |
+#endif |
|
141 | 143 |
CASE_OS(NetBSD, os_bsd); |
142 | 144 |
CASE_OS(OpenBSD, os_bsd); |
143 | 145 |
CASE_OS(Psp, os_unknown); |
... | ... |
@@ -1,4 +1,5 @@ |
1 | 1 |
<?xml version="1.0" encoding="utf-8"?> |
2 |
+ |
|
2 | 3 |
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
3 | 4 |
<ItemGroup Label="ProjectConfigurations"> |
4 | 5 |
<ProjectConfiguration Include="Debug|Win32"> |
... | ... |
@@ -332,7 +333,7 @@ |
332 | 332 |
<ClCompile Include="compat\net.c"/> |
333 | 333 |
<ClCompile Include="compat\random.c"/> |
334 | 334 |
<ClCompile Include="compat\snprintf.c"/> |
335 |
- <ClCompile Include="compat\utf8_util.c" /> |
|
335 |
+ <ClCompile Include="compat\utf8_util.c"/> |
|
336 | 336 |
<ClCompile Include="compat\w32_errno.c"/> |
337 | 337 |
<ClCompile Include="compat\w32_stat.c"/> |
338 | 338 |
</ItemGroup> |
... | ... |
@@ -356,4 +357,4 @@ |
356 | 356 |
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/> |
357 | 357 |
<ImportGroup Label="ExtensionTargets"> |
358 | 358 |
</ImportGroup> |
359 |
-</Project> |
|
360 | 359 |
\ No newline at end of file |
360 |
+</Project> |
... | ... |
@@ -20,6 +20,7 @@ |
20 | 20 |
</ProjectConfiguration> |
21 | 21 |
</ItemGroup> |
22 | 22 |
<ItemGroup> |
23 |
+ <ClCompile Include="..\libclamav\c++\PointerTracking.cpp"/> |
|
23 | 24 |
<ClCompile Include="..\libclamav\c++\detect.cpp"/> |
24 | 25 |
<ClCompile Include="..\libclamav\c++\bytecode2llvm.cpp"/> |
25 | 26 |
<ClCompile Include="..\libclamav\c++\ClamBCRTChecks.cpp"/> |