Support building with external LLVM 2.9, and drop support for building with external 2.8

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
remotes/push_mirror/cliemu_dump
Török Edvin 15 years ago
parent 0e34854a7b
commit 0c79cc5529
  1. 4
      ChangeLog
  2. 21
      libclamav/c++/ClamBCRTChecks.cpp
  3. 3
      libclamav/c++/Makefile.am
  4. 56
      libclamav/c++/Makefile.in
  5. 321
      libclamav/c++/PointerTracking.cpp
  6. 132
      libclamav/c++/PointerTracking.h
  7. 173
      libclamav/c++/bytecode2llvm.cpp
  8. 4
      libclamav/c++/configure
  9. 4
      libclamav/c++/configure.ac
  10. 9
      libclamav/c++/detect.cpp
  11. 2
      win32/clamav-config.h
  12. 5
      win32/libclamav.vcxproj
  13. 1
      win32/libclamavcxx.vcxproj

@ -1,3 +1,7 @@
Fri May 6 16:16:00 EEST 2011 (edwin)
------------------------------------
* libclamav/c++: add support for building with external LLVM 2.9, and drop external 2.8 support
Thu May 5 01:07:57 CEST 2011 (acab)
------------------------------------
* clamd: log request ip address for instream scans #bb2592

@ -30,8 +30,14 @@
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/LiveValues.h"
//#include "llvm/Analysis/LiveValues.h"
//
#ifdef LLVM29
#include "llvm/Analysis/ValueTracking.h"
#include "PointerTracking.h"
#else
#include "llvm/Analysis/PointerTracking.h"
#endif
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/ScalarEvolutionExpander.h"
@ -54,13 +60,22 @@
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/Debug.h"
#ifndef LLVM28
#define LLVM28
#endif
#ifdef LLVM28
#define DEFINEPASS(passname) passname() : FunctionPass(ID)
#else
#define DEFINEPASS(passname) passname() : FunctionPass(&ID)
#endif
using namespace llvm;
#ifndef LLVM29
static Value *GetUnderlyingObject(Value *P, TargetData *TD)
{
return P->getUnderlyingObject();
}
#endif
namespace {
class PtrVerifier : public FunctionPass {
@ -275,7 +290,7 @@ namespace {
if (BaseMap.count(P)) {
return BaseMap[Ptr] = BaseMap[P];
}
Value *P2 = P->getUnderlyingObject();
Value *P2 = GetUnderlyingObject(P, TD);
if (P2 != P) {
Value *V = getPointerBase(P2);
return BaseMap[Ptr] = V;
@ -334,7 +349,7 @@ namespace {
}
}
if (LoadInst *LI = dyn_cast<LoadInst>(Base)) {
Value *V = LI->getPointerOperand()->stripPointerCasts()->getUnderlyingObject();
Value *V = GetUnderlyingObject(LI->getPointerOperand()->stripPointerCasts(), TD);
if (Argument *A = dyn_cast<Argument>(V)) {
if (A->getArgNo() == 0) {
// pointers from hidden ctx are trusted to be at least the

@ -33,10 +33,11 @@ if BUILD_EXTERNAL_LLVM
# we know this will be built with GNU make, so its safe to use GNU make specific
# $(shell ...)
#LLVM_DEPS=$(shell $(LLVM_CONFIG) --libfiles jit nativecodegen)
libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28
libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28 -DLLVM29
libclamavcxx_la_LDFLAGS = @LLVMCONFIG_LDFLAGS@ @LLVMCONFIG_LIBS@
libclamavcxx_la_DEPENDENCIES = @LLVMCONFIG_LIBFILES@
noinst_LTLIBRARIES = libclamavcxx.la
libclamavcxx_la_SOURCES += PointerTracking.cpp
else
AM_CPPFLAGS += $(LLVM_INCLUDES) $(LLVM_DEFS)

@ -51,14 +51,15 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
@BUILD_EXTERNAL_LLVM_FALSE@am__append_1 = $(LLVM_INCLUDES) $(LLVM_DEFS)
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_2 = libllvmx86codegen.la
@BUILD_EXTERNAL_LLVM_TRUE@am__append_1 = PointerTracking.cpp
@BUILD_EXTERNAL_LLVM_FALSE@am__append_2 = $(LLVM_INCLUDES) $(LLVM_DEFS)
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_3 = libllvmx86codegen.la
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_4 = libllvmx86codegen.la
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_5 = libllvmpowerpccodegen.la
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_X86_TRUE@am__append_5 = libllvmx86codegen.la
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_6 = libllvmpowerpccodegen.la
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_7 = libllvmpowerpccodegen.la
@BUILD_EXTERNAL_LLVM_FALSE@@MAINTAINER_MODE_TRUE@am__append_8 = $(TBLGENFILES)
@BUILD_EXTERNAL_LLVM_FALSE@@BUILD_PPC_TRUE@am__append_8 = libllvmpowerpccodegen.la
@BUILD_EXTERNAL_LLVM_FALSE@@MAINTAINER_MODE_TRUE@am__append_9 = $(TBLGENFILES)
@BUILD_EXTERNAL_LLVM_FALSE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = tblgen$(EXEEXT)
subdir = .
DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
@ -81,8 +82,14 @@ CONFIG_HEADER = clamavcxx-config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
am__libclamavcxx_la_SOURCES_DIST = bytecode2llvm.cpp \
ClamBCRTChecks.cpp ClamBCModule.h ClamBCDiagnostics.h \
detect.cpp PointerTracking.cpp
@BUILD_EXTERNAL_LLVM_TRUE@am__objects_1 = \
@BUILD_EXTERNAL_LLVM_TRUE@ libclamavcxx_la-PointerTracking.lo
am_libclamavcxx_la_OBJECTS = libclamavcxx_la-bytecode2llvm.lo \
libclamavcxx_la-ClamBCRTChecks.lo libclamavcxx_la-detect.lo
libclamavcxx_la-ClamBCRTChecks.lo libclamavcxx_la-detect.lo \
$(am__objects_1)
libclamavcxx_la_OBJECTS = $(am_libclamavcxx_la_OBJECTS)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@ -798,7 +805,7 @@ SOURCES = $(libclamavcxx_la_SOURCES) $(libllvmcodegen_la_SOURCES) \
$(libllvmjit_la_SOURCES) $(libllvmpowerpccodegen_la_SOURCES) \
$(libllvmsystem_la_SOURCES) $(libllvmx86codegen_la_SOURCES) \
$(tblgen_SOURCES)
DIST_SOURCES = $(libclamavcxx_la_SOURCES) \
DIST_SOURCES = $(am__libclamavcxx_la_SOURCES_DIST) \
$(am__libllvmcodegen_la_SOURCES_DIST) \
$(am__libllvmjit_la_SOURCES_DIST) \
$(am__libllvmpowerpccodegen_la_SOURCES_DIST) \
@ -958,38 +965,34 @@ LLVM_INCLUDES = -I$(top_srcdir)/llvm/include -I$(top_builddir)/llvm/include
# TODO: HP-UX should have -D_REENTRANT -D_HPUX_SOURCE
LLVM_DEFS = -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D_DEBUG -D_GNU_SOURCE
AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/.. \
-I$(top_builddir)/../../ $(am__append_1)
-I$(top_builddir)/../../ $(am__append_2)
AM_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions
ACLOCAL_AMFLAGS = -I m4
libclamavcxx_la_SOURCES = bytecode2llvm.cpp\
ClamBCRTChecks.cpp\
ClamBCModule.h\
ClamBCDiagnostics.h\
detect.cpp
libclamavcxx_la_SOURCES = bytecode2llvm.cpp ClamBCRTChecks.cpp \
ClamBCModule.h ClamBCDiagnostics.h detect.cpp $(am__append_1)
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_CXXFLAGS = $(LLVM_CXXFLAGS)
#$(LLVM_CONFIG): build-llvm
# we know this will be built with GNU make, so its safe to use GNU make specific
# $(shell ...)
#LLVM_DEPS=$(shell $(LLVM_CONFIG) --libfiles jit nativecodegen)
@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28
@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_CXXFLAGS = $(AM_CPPFLAGS) @LLVMCONFIG_CXXFLAGS@ -fexceptions -DLLVM28 -DLLVM29
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_LDFLAGS = -no-undefined
@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_LDFLAGS = @LLVMCONFIG_LDFLAGS@ @LLVMCONFIG_LIBS@
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_DEPENDENCIES = \
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmjit.la libllvmcodegen.la \
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmsystem.la $(am__append_3) \
@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_6)
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmsystem.la $(am__append_4) \
@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_7)
@BUILD_EXTERNAL_LLVM_TRUE@libclamavcxx_la_DEPENDENCIES = \
@BUILD_EXTERNAL_LLVM_TRUE@ @LLVMCONFIG_LIBFILES@ \
@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_3) $(am__append_6)
@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_4) $(am__append_7)
@BUILD_EXTERNAL_LLVM_FALSE@noinst_LTLIBRARIES = libclamavcxx.la \
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmsystem.la libllvmcodegen.la \
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmjit.la $(am__append_4) \
@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_7)
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmjit.la $(am__append_5) \
@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_8)
@BUILD_EXTERNAL_LLVM_TRUE@noinst_LTLIBRARIES = libclamavcxx.la \
@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_4) $(am__append_7)
@BUILD_EXTERNAL_LLVM_TRUE@ $(am__append_5) $(am__append_8)
@BUILD_EXTERNAL_LLVM_FALSE@libclamavcxx_la_LIBADD = libllvmjit.la \
@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_2) $(am__append_5) \
@BUILD_EXTERNAL_LLVM_FALSE@ $(am__append_3) $(am__append_6) \
@BUILD_EXTERNAL_LLVM_FALSE@ libllvmcodegen.la libllvmsystem.la
@BUILD_EXTERNAL_LLVM_FALSE@LLVM_CXXFLAGS = -Woverloaded-virtual -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings
@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\
# Rule to rerun LLVM's configure if it changed, before building anything else
# LLVM
@BUILD_EXTERNAL_LLVM_FALSE@BUILT_SOURCES = $(am__append_8) \
@BUILD_EXTERNAL_LLVM_FALSE@BUILT_SOURCES = $(am__append_9) \
@BUILD_EXTERNAL_LLVM_FALSE@ llvm/config.status
@BUILD_EXTERNAL_LLVM_FALSE@EXTRA_DIST = $(top_srcdir)/llvm llvmcheck.sh $(TBLGENFILES)
@BUILD_EXTERNAL_LLVM_FALSE@libllvmsystem_la_LDFLAGS = @THREAD_LIBS@
@ -1776,6 +1779,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VirtRegRewriter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/circular_raw_ostream.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-ClamBCRTChecks.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-PointerTracking.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-bytecode2llvm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamavcxx_la-detect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmpowerpccodegen_la-PPCBranchSelector.Plo@am__quote@
@ -2070,6 +2074,14 @@ libclamavcxx_la-detect.lo: detect.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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
libclamavcxx_la-PointerTracking.lo: PointerTracking.cpp
@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
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamavcxx_la-PointerTracking.Tpo $(DEPDIR)/libclamavcxx_la-PointerTracking.Plo
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='PointerTracking.cpp' object='libclamavcxx_la-PointerTracking.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@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
ConstantFolding.lo: llvm/lib/Analysis/ConstantFolding.cpp
@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
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ConstantFolding.Tpo $(DEPDIR)/ConstantFolding.Plo

@ -0,0 +1,321 @@
//===- PointerTracking.cpp - Pointer Bounds Tracking ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements tracking of pointer bounds.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ValueTracking.h"
#include "PointerTracking.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Value.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
using namespace llvm;
namespace llvm {
void initializePointerTrackingPass(llvm::PassRegistry&);
};
INITIALIZE_PASS(PointerTracking, "pointertracking",
"Track pointer bounds", false, true);
char PointerTracking::ID = 0;
PointerTracking::PointerTracking() : FunctionPass(ID) {
initializePointerTrackingPass(*PassRegistry::getPassRegistry());
}
bool PointerTracking::runOnFunction(Function &F) {
predCache.clear();
assert(analyzing.empty());
FF = &F;
TD = getAnalysisIfAvailable<TargetData>();
SE = &getAnalysis<ScalarEvolution>();
LI = &getAnalysis<LoopInfo>();
DT = &getAnalysis<DominatorTree>();
return false;
}
void PointerTracking::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredTransitive<DominatorTree>();
AU.addRequiredTransitive<LoopInfo>();
AU.addRequiredTransitive<ScalarEvolution>();
AU.setPreservesAll();
}
bool PointerTracking::doInitialization(Module &M) {
const Type *PTy = Type::getInt8PtrTy(M.getContext());
// Find calloc(i64, i64) or calloc(i32, i32).
callocFunc = M.getFunction("calloc");
if (callocFunc) {
const FunctionType *Ty = callocFunc->getFunctionType();
std::vector<const Type*> args, args2;
args.push_back(Type::getInt64Ty(M.getContext()));
args.push_back(Type::getInt64Ty(M.getContext()));
args2.push_back(Type::getInt32Ty(M.getContext()));
args2.push_back(Type::getInt32Ty(M.getContext()));
const FunctionType *Calloc1Type =
FunctionType::get(PTy, args, false);
const FunctionType *Calloc2Type =
FunctionType::get(PTy, args2, false);
if (Ty != Calloc1Type && Ty != Calloc2Type)
callocFunc = 0; // Give up
}
// Find realloc(i8*, i64) or realloc(i8*, i32).
reallocFunc = M.getFunction("realloc");
if (reallocFunc) {
const FunctionType *Ty = reallocFunc->getFunctionType();
std::vector<const Type*> args, args2;
args.push_back(PTy);
args.push_back(Type::getInt64Ty(M.getContext()));
args2.push_back(PTy);
args2.push_back(Type::getInt32Ty(M.getContext()));
const FunctionType *Realloc1Type =
FunctionType::get(PTy, args, false);
const FunctionType *Realloc2Type =
FunctionType::get(PTy, args2, false);
if (Ty != Realloc1Type && Ty != Realloc2Type)
reallocFunc = 0; // Give up
}
return false;
}
// Calculates the number of elements allocated for pointer P,
// the type of the element is stored in Ty.
const SCEV *PointerTracking::computeAllocationCount(Value *P,
const Type *&Ty) const {
Value *V = P->stripPointerCasts();
if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
Value *arraySize = AI->getArraySize();
Ty = AI->getAllocatedType();
// arraySize elements of type Ty.
return SE->getSCEV(arraySize);
}
if (CallInst *CI = extractMallocCall(V)) {
Value *arraySize = getMallocArraySize(CI, TD);
const Type* AllocTy = getMallocAllocatedType(CI);
if (!AllocTy || !arraySize) return SE->getCouldNotCompute();
Ty = AllocTy;
// arraySize elements of type Ty.
return SE->getSCEV(arraySize);
}
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
if (GV->hasDefinitiveInitializer()) {
Constant *C = GV->getInitializer();
if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
Ty = ATy->getElementType();
return SE->getConstant(Type::getInt32Ty(P->getContext()),
ATy->getNumElements());
}
}
Ty = GV->getType();
return SE->getConstant(Type::getInt32Ty(P->getContext()), 1);
//TODO: implement more tracking for globals
}
if (CallInst *CI = dyn_cast<CallInst>(V)) {
CallSite CS(CI);
Function *F = dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
const Loop *L = LI->getLoopFor(CI->getParent());
if (F == callocFunc) {
Ty = Type::getInt8Ty(P->getContext());
// calloc allocates arg0*arg1 bytes.
return SE->getSCEVAtScope(SE->getMulExpr(SE->getSCEV(CS.getArgument(0)),
SE->getSCEV(CS.getArgument(1))),
L);
} else if (F == reallocFunc) {
Ty = Type::getInt8Ty(P->getContext());
// realloc allocates arg1 bytes.
return SE->getSCEVAtScope(CS.getArgument(1), L);
}
}
return SE->getCouldNotCompute();
}
Value *PointerTracking::computeAllocationCountValue(Value *P, const Type *&Ty) const
{
Value *V = P->stripPointerCasts();
if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
Ty = AI->getAllocatedType();
// arraySize elements of type Ty.
return AI->getArraySize();
}
if (CallInst *CI = extractMallocCall(V)) {
Ty = getMallocAllocatedType(CI);
if (!Ty)
return 0;
Value *arraySize = getMallocArraySize(CI, TD);
if (!arraySize) {
Ty = Type::getInt8Ty(P->getContext());
return CI->getArgOperand(0);
}
// arraySize elements of type Ty.
return arraySize;
}
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
if (GV->hasDefinitiveInitializer()) {
Constant *C = GV->getInitializer();
if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
Ty = ATy->getElementType();
return ConstantInt::get(Type::getInt32Ty(P->getContext()),
ATy->getNumElements());
}
}
Ty = cast<PointerType>(GV->getType())->getElementType();
return ConstantInt::get(Type::getInt32Ty(P->getContext()), 1);
//TODO: implement more tracking for globals
}
if (CallInst *CI = dyn_cast<CallInst>(V)) {
CallSite CS(CI);
Function *F = dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
if (F == reallocFunc) {
Ty = Type::getInt8Ty(P->getContext());
// realloc allocates arg1 bytes.
return CS.getArgument(1);
}
}
return 0;
}
// Calculates the number of elements of type Ty allocated for P.
const SCEV *PointerTracking::computeAllocationCountForType(Value *P,
const Type *Ty)
const {
const Type *elementTy;
const SCEV *Count = computeAllocationCount(P, elementTy);
if (isa<SCEVCouldNotCompute>(Count))
return Count;
if (elementTy == Ty)
return Count;
if (!TD) // need TargetData from this point forward
return SE->getCouldNotCompute();
uint64_t elementSize = TD->getTypeAllocSize(elementTy);
uint64_t wantSize = TD->getTypeAllocSize(Ty);
if (elementSize == wantSize)
return Count;
if (elementSize % wantSize) //fractional counts not possible
return SE->getCouldNotCompute();
return SE->getMulExpr(Count, SE->getConstant(Count->getType(),
elementSize/wantSize));
}
const SCEV *PointerTracking::getAllocationElementCount(Value *V) const {
// We only deal with pointers.
const PointerType *PTy = cast<PointerType>(V->getType());
return computeAllocationCountForType(V, PTy->getElementType());
}
const SCEV *PointerTracking::getAllocationSizeInBytes(Value *V) const {
return computeAllocationCountForType(V, Type::getInt8Ty(V->getContext()));
}
// Helper for isLoopGuardedBy that checks the swapped and inverted predicate too
enum SolverResult PointerTracking::isLoopGuardedBy(const Loop *L,
Predicate Pred,
const SCEV *A,
const SCEV *B) const {
if (SE->isLoopEntryGuardedByCond(L, Pred, A, B))
return AlwaysTrue;
Pred = ICmpInst::getSwappedPredicate(Pred);
if (SE->isLoopEntryGuardedByCond(L, Pred, B, A))
return AlwaysTrue;
Pred = ICmpInst::getInversePredicate(Pred);
if (SE->isLoopEntryGuardedByCond(L, Pred, B, A))
return AlwaysFalse;
Pred = ICmpInst::getSwappedPredicate(Pred);
if (SE->isLoopEntryGuardedByCond(L, Pred, A, B))
return AlwaysTrue;
return Unknown;
}
enum SolverResult PointerTracking::checkLimits(const SCEV *Offset,
const SCEV *Limit,
BasicBlock *BB)
{
//FIXME: merge implementation
return Unknown;
}
void PointerTracking::getPointerOffset(Value *Pointer, Value *&Base,
const SCEV *&Limit,
const SCEV *&Offset) const
{
Pointer = Pointer->stripPointerCasts();
Base = GetUnderlyingObject(Pointer, TD);
Limit = getAllocationSizeInBytes(Base);
if (isa<SCEVCouldNotCompute>(Limit)) {
Base = 0;
Offset = Limit;
return;
}
Offset = SE->getMinusSCEV(SE->getSCEV(Pointer), SE->getSCEV(Base));
if (isa<SCEVCouldNotCompute>(Offset)) {
Base = 0;
Limit = Offset;
}
}
void PointerTracking::print(raw_ostream &OS, const Module* M) const {
// Calling some PT methods may cause caches to be updated, however
// this should be safe for the same reason its safe for SCEV.
PointerTracking &PT = *const_cast<PointerTracking*>(this);
for (inst_iterator I=inst_begin(*FF), E=inst_end(*FF); I != E; ++I) {
if (!I->getType()->isPointerTy())
continue;
Value *Base;
const SCEV *Limit, *Offset;
getPointerOffset(&*I, Base, Limit, Offset);
if (!Base)
continue;
if (Base == &*I) {
const SCEV *S = getAllocationElementCount(Base);
OS << *Base << " ==> " << *S << " elements, ";
OS << *Limit << " bytes allocated\n";
continue;
}
OS << &*I << " -- base: " << *Base;
OS << " offset: " << *Offset;
enum SolverResult res = PT.checkLimits(Offset, Limit, I->getParent());
switch (res) {
case AlwaysTrue:
OS << " always safe\n";
break;
case AlwaysFalse:
OS << " always unsafe\n";
break;
case Unknown:
OS << " <<unknown>>\n";
break;
}
}
}

@ -0,0 +1,132 @@
//===- PointerTracking.h - Pointer Bounds Tracking --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements tracking of pointer bounds.
// It knows that the libc functions "calloc" and "realloc" allocate memory, thus
// you should avoid using this pass if they mean something else for your
// language.
//
// All methods assume that the pointer is not NULL, if it is then the returned
// allocation size is wrong, and the result from checkLimits is wrong too.
// It also assumes that pointers are valid, and that it is not analyzing a
// use-after-free scenario.
// Due to these limitations the "size" returned by these methods should be
// considered as either 0 or the returned size.
//
// Another analysis pass should be used to find use-after-free/NULL dereference
// bugs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_POINTERTRACKING_H
#define LLVM_ANALYSIS_POINTERTRACKING_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/PredIteratorCache.h"
namespace llvm {
class DominatorTree;
class ScalarEvolution;
class SCEV;
class Loop;
class LoopInfo;
class TargetData;
// Result from solver, assuming pointer is not NULL,
// and it is not a use-after-free situation.
enum SolverResult {
AlwaysFalse,// always false with above constraints
AlwaysTrue,// always true with above constraints
Unknown // it can sometimes be true, sometimes false, or it is undecided
};
class PointerTracking : public FunctionPass {
public:
typedef ICmpInst::Predicate Predicate;
static char ID;
PointerTracking();
virtual bool doInitialization(Module &M);
// If this pointer directly points to an allocation, return
// the number of elements of type Ty allocated.
// Otherwise return CouldNotCompute.
// Since allocations can fail by returning NULL, the real element count
// for every allocation is either 0 or the value returned by this function.
const SCEV *getAllocationElementCount(Value *P) const;
// Same as getAllocationSize() but returns size in bytes.
// We consider one byte as 8 bits.
const SCEV *getAllocationSizeInBytes(Value *V) const;
// Given a Pointer, determine a base pointer of known size, and an offset
// therefrom.
// When unable to determine, sets Base to NULL, and Limit/Offset to
// CouldNotCompute.
// BaseSize, and Offset are in bytes: Pointer == Base + Offset
void getPointerOffset(Value *Pointer, Value *&Base, const SCEV *& BaseSize,
const SCEV *&Offset) const;
// Compares the 2 scalar evolution expressions according to predicate,
// and if it can prove that the result is always true or always false
// return AlwaysTrue/AlwaysFalse. Otherwise it returns Unknown.
enum SolverResult compareSCEV(const SCEV *A, Predicate Pred, const SCEV *B,
const Loop *L);
// Determines whether the condition LHS <Pred> RHS is sufficient
// for the condition A <Pred> B to hold.
// Currently only ULT/ULE is supported.
// This errs on the side of returning false.
bool conditionSufficient(const SCEV *LHS, Predicate Pred1, const SCEV *RHS,
const SCEV *A, Predicate Pred2, const SCEV *B,
const Loop *L);
// Determines whether Offset is known to be always in [0, Limit) bounds.
// This errs on the side of returning Unknown.
enum SolverResult checkLimits(const SCEV *Offset, const SCEV *Limit,
BasicBlock *BB);
virtual bool runOnFunction(Function &F);
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
void print(raw_ostream &OS, const Module* = 0) const;
Value *computeAllocationCountValue(Value *P, const Type *&Ty) const;
private:
Function *FF;
TargetData *TD;
ScalarEvolution *SE;
LoopInfo *LI;
DominatorTree *DT;
Function *callocFunc;
Function *reallocFunc;
PredIteratorCache predCache;
SmallPtrSet<const SCEV*, 1> analyzing;
enum SolverResult isLoopGuardedBy(const Loop *L, Predicate Pred,
const SCEV *A, const SCEV *B) const;
static bool isMonotonic(const SCEV *S);
bool scevPositive(const SCEV *A, const Loop *L, bool strict=true) const;
bool conditionSufficient(Value *Cond, bool negated,
const SCEV *A, Predicate Pred, const SCEV *B);
Value *getConditionToReach(BasicBlock *A,
DomTreeNodeBase<BasicBlock> *B,
bool &negated);
Value *getConditionToReach(BasicBlock *A,
BasicBlock *B,
bool &negated);
const SCEV *computeAllocationCount(Value *P, const Type *&Ty) const;
const SCEV *computeAllocationCountForType(Value *P, const Type *Ty) const;
};
}
#endif

@ -59,13 +59,29 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/PrettyStackTrace.h"
#ifdef LLVM29
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/ThreadLocal.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/PassRegistry.h"
#else
#include "llvm/System/DataTypes.h"
#include "llvm/System/Host.h"
#include "llvm/System/Memory.h"
#include "llvm/System/Mutex.h"
#include "llvm/System/Signals.h"
#include "llvm/Support/Timer.h"
#include "llvm/System/Threading.h"
#include "llvm/System/ThreadLocal.h"
#endif
#include "llvm/Support/Timer.h"
extern "C" {
void LLVMInitializeX86AsmPrinter();
@ -78,7 +94,6 @@ void LLVMInitializePowerPCAsmPrinter();
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/System/ThreadLocal.h"
#include <cstdlib>
#include <csetjmp>
#include <new>
@ -133,6 +148,11 @@ struct cli_bcengine {
};
extern "C" uint8_t cli_debug_flag;
#ifdef LLVM29
namespace llvm {
void initializeRuntimeLimitsPass(PassRegistry&);
};
#endif
namespace {
#ifndef LLVM28
@ -149,6 +169,10 @@ namespace {
#define DEFINEPASS(passname) passname() : FunctionPass(&ID)
#endif
#ifdef LLVM29
#define NORETURN LLVM_ATTRIBUTE_NORETURN
#endif
static sys::ThreadLocal<const jmp_buf> ExceptionReturn;
static void UpgradeCall(CallInst *&C, Function *Intr)
@ -526,7 +550,12 @@ class RuntimeLimits : public FunctionPass {
public:
static char ID;
DEFINEPASS(RuntimeLimits) {}
DEFINEPASS(RuntimeLimits) {
#ifdef LLVM29
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeRuntimeLimitsPass(Registry);
#endif
}
virtual bool runOnFunction(Function &F) {
BBSetTy BackedgeTargets;
@ -1043,12 +1072,18 @@ public:
// Have an alloca -> some instruction uses its address otherwise
// mem2reg would have converted it to an SSA register.
// Enable stack protector for this function.
#ifndef LLVM29
// LLVM 2.9 has broken SSP, it does a 'mov 0x28, $rax', which tries
// to read from the address 0x28 and crashes
F->addFnAttr(Attribute::StackProtectReq);
#endif
}
// always add stackprotect attribute (bb #2239), so we know this
// function was verified. If there is no alloca it won't actually add
// stack protector in emitted code so this won't slow down the app.
#ifndef LLVM29
F->addFnAttr(Attribute::StackProtect);
#endif
}
Value *GEPOperand(Value *V) {
@ -1830,6 +1865,13 @@ static void addFunctionProtos(struct CommonFunctions *CF, ExecutionEngine *EE, M
}
}
#ifdef LLVM29
INITIALIZE_PASS_BEGIN(RuntimeLimits, "rl", "Runtime Limits", false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
INITIALIZE_PASS_DEPENDENCY(DominatorTree)
INITIALIZE_PASS_END(RuntimeLimits, "rl" ,"Runtime Limits", false, false)
#endif
static pthread_mutex_t watchdog_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t watchdog_cond = PTHREAD_COND_INITIALIZER;
@ -2179,7 +2221,9 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
PM.add(createCFGSimplificationPass());
PM.add(createGlobalOptimizerPass());
PM.add(createConstantMergePass());
PM.add(new RuntimeLimits());
RuntimeLimits *RL = new RuntimeLimits();
PM.add(RL);
TimerWrapper pmTimer2("Transform passes");
pmTimer2.startTimer();
PM.run(*M);
@ -2327,7 +2371,17 @@ void cli_bytecode_debug_printsrc(const struct cli_bc_ctx *ctx)
if (I == LinePrinter.files.end()) {
lines = new linesTy;
std::string ErrorMessage;
#ifdef LLVM29
OwningPtr<MemoryBuffer> File;
error_code ec = MemoryBuffer::getFile(path, File);
if (ec) {
ErrorMessage = ec.message();
lines->buffer = 0;
} else
lines->buffer = File.take();
#else
lines->buffer = MemoryBuffer::getFile(path, &ErrorMessage);
#endif
if (!lines->buffer) {
errs() << "Unable to open file '" << path << "'\n";
return ;
@ -2401,6 +2455,117 @@ void stop(const char *msg, llvm::Function* F, llvm::Instruction* I)
}
}
#ifdef LLVM29
static Value *findDbgGlobalDeclare(GlobalVariable *V) {
const Module *M = V->getParent();
NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv");
if (!NMD)
return 0;
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
if (!DIG.isGlobalVariable())
continue;
if (DIGlobalVariable(DIG).getGlobal() == V)
return DIG;
}
return 0;
}
/// Find the debug info descriptor corresponding to this function.
static Value *findDbgSubprogramDeclare(Function *V) {
const Module *M = V->getParent();
NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp");
if (!NMD)
return 0;
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
if (!DIG.isSubprogram())
continue;
if (DISubprogram(DIG).getFunction() == V)
return DIG;
}
return 0;
}
/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
/// It looks through pointer casts too.
static const DbgDeclareInst *findDbgDeclare(const Value *V) {
V = V->stripPointerCasts();
if (!isa<Instruction>(V) && !isa<Argument>(V))
return 0;
const Function *F = NULL;
if (const Instruction *I = dyn_cast<Instruction>(V))
F = I->getParent()->getParent();
else if (const Argument *A = dyn_cast<Argument>(V))
F = A->getParent();
for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end();
BI != BE; ++BI)
if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
if (DDI->getAddress() == V)
return DDI;
return 0;
}
static bool getLocationInfo(const Value *V, std::string &DisplayName,
std::string &Type, unsigned &LineNo,
std::string &File, std::string &Dir) {
DICompileUnit Unit;
DIType TypeD;
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(const_cast<Value*>(V))) {
Value *DIGV = findDbgGlobalDeclare(GV);
if (!DIGV) return false;
DIGlobalVariable Var(cast<MDNode>(DIGV));
StringRef D = Var.getDisplayName();
if (!D.empty())
DisplayName = D;
LineNo = Var.getLineNumber();
Unit = Var.getCompileUnit();
TypeD = Var.getType();
} else if (Function *F = dyn_cast<Function>(const_cast<Value*>(V))){
Value *DIF = findDbgSubprogramDeclare(F);
if (!DIF) return false;
DISubprogram Var(cast<MDNode>(DIF));
StringRef D = Var.getDisplayName();
if (!D.empty())
DisplayName = D;
LineNo = Var.getLineNumber();
Unit = Var.getCompileUnit();
TypeD = Var.getType();
} else {
const DbgDeclareInst *DDI = findDbgDeclare(V);
if (!DDI) return false;
DIVariable Var(cast<MDNode>(DDI->getVariable()));
StringRef D = Var.getName();
if (!D.empty())
DisplayName = D;
LineNo = Var.getLineNumber();
Unit = Var.getCompileUnit();
TypeD = Var.getType();
}
StringRef T = TypeD.getName();
if (!T.empty())
Type = T;
StringRef F = Unit.getFilename();
if (!F.empty())
File = F;
StringRef D = Unit.getDirectory();
if (!D.empty())
Dir = D;
return true;
}
#endif
void printValue(llvm::Value *V, bool a, bool b) {
std::string DisplayName;
std::string Type;

@ -15370,8 +15370,8 @@ if test "${with_system_llvm+set}" = set; then :
*)
llvmconfig="$withval"
llvmver=`$llvmconfig --version`
if test "$llvmver" != "2.8" -a "$llvmver" != "2.8svn" -a "$llvmver" != "2.8rc"; then
as_fn_error $? "LLVM 2.8 or 2.8svn required, but \"$llvmver\" found" "$LINENO" 5
if test "$llvmver" != "2.9"; then
as_fn_error $? "LLVM 2.9 required, but \"$llvmver\" found" "$LINENO" 5
fi
LLVMCONFIG_CXXFLAGS=`$llvmconfig --cxxflags`

@ -59,8 +59,8 @@ AC_ARG_WITH([system-llvm], AC_HELP_STRING([-with-system-llvm],
*)
llvmconfig="$withval"
llvmver=`$llvmconfig --version`
if test "$llvmver" != "2.8" -a "$llvmver" != "2.8svn" -a "$llvmver" != "2.8rc"; then
AC_MSG_ERROR([LLVM 2.8 or 2.8svn required, but "$llvmver" found])
if test "$llvmver" != "2.9"; then
AC_MSG_ERROR([LLVM 2.9 required, but "$llvmver" found])
fi
AC_SUBST(LLVMCONFIG_CXXFLAGS, [`$llvmconfig --cxxflags`])
AC_SUBST(LLVMCONFIG_LDFLAGS, [`$llvmconfig --ldflags`])

@ -22,9 +22,16 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"
#ifdef LLVM29
#include "llvm/Support/Host.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Memory.h"
#else
#include "llvm/System/Host.h"
#include "llvm/System/DataTypes.h"
#include "llvm/System/Memory.h"
#endif
#include "llvm/Config/config.h"
extern "C" {
@ -137,7 +144,9 @@ void cli_detect_env_jit(struct cli_environment *env)
CASE_OS(Linux, os_linux);
CASE_OS(Lv2, os_unknown);
CASE_OS(MinGW32, os_win32);
#ifndef LLVM29
CASE_OS(MinGW64, os_win64);
#endif
CASE_OS(NetBSD, os_bsd);
CASE_OS(OpenBSD, os_bsd);
CASE_OS(Psp, os_unknown);

@ -508,7 +508,7 @@
/* #undef USE_SYSLOG */
/* Version number of package */
#define VERSION "devel-clamav-0.97-110-g60ba0f8"
#define VERSION "devel-clamav-0.97-129-g0e3c6e3"
/* Version suffix for package */
#define VERSION_SUFFIX ""

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -332,7 +333,7 @@
<ClCompile Include="compat\net.c"/>
<ClCompile Include="compat\random.c"/>
<ClCompile Include="compat\snprintf.c"/>
<ClCompile Include="compat\utf8_util.c" />
<ClCompile Include="compat\utf8_util.c"/>
<ClCompile Include="compat\w32_errno.c"/>
<ClCompile Include="compat\w32_stat.c"/>
</ItemGroup>
@ -356,4 +357,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

@ -20,6 +20,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\libclamav\c++\PointerTracking.cpp"/>
<ClCompile Include="..\libclamav\c++\detect.cpp"/>
<ClCompile Include="..\libclamav\c++\bytecode2llvm.cpp"/>
<ClCompile Include="..\libclamav\c++\ClamBCRTChecks.cpp"/>

Loading…
Cancel
Save