DataFlowSanitizer; LLVM changes.

DataFlowSanitizer is a generalised dynamic data flow analysis.

Unlike other Sanitizer tools, this tool is not designed to detect a
specific class of bugs on its own.  Instead, it provides a generic
dynamic data flow analysis framework to be used by clients to help
detect application-specific issues within their own code.

Differential Revision: http://llvm-reviews.chandlerc.com/D965

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187923 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Collingbourne 2013-08-07 22:47:18 +00:00
parent 9c2c660e12
commit 6fa33f5dd9
10 changed files with 1276 additions and 0 deletions

View File

@ -122,6 +122,7 @@ void initializeAddressSanitizerPass(PassRegistry&);
void initializeAddressSanitizerModulePass(PassRegistry&);
void initializeMemorySanitizerPass(PassRegistry&);
void initializeThreadSanitizerPass(PassRegistry&);
void initializeDataFlowSanitizerPass(PassRegistry&);
void initializeEarlyCSEPass(PassRegistry&);
void initializeExpandISelPseudosPass(PassRegistry&);
void initializeFindUsedTypesPass(PassRegistry&);

View File

@ -16,6 +16,20 @@
#include "llvm/ADT/StringRef.h"
#ifdef __GNUC__
inline void *getDFSanArgTLSPtrForJIT() {
extern __thread __attribute__((tls_model("initial-exec")))
void *__dfsan_arg_tls;
return (void *)&__dfsan_arg_tls;
}
inline void *getDFSanRetValTLSPtrForJIT() {
extern __thread __attribute__((tls_model("initial-exec")))
void *__dfsan_retval_tls;
return (void *)&__dfsan_retval_tls;
}
#endif
namespace llvm {
class ModulePass;
@ -74,6 +88,17 @@ FunctionPass *createMemorySanitizerPass(bool TrackOrigins = false,
// Insert ThreadSanitizer (race detection) instrumentation
FunctionPass *createThreadSanitizerPass(StringRef BlacklistFile = StringRef());
// Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation
ModulePass *createDataFlowSanitizerPass(void *(*getArgTLS)() = 0,
void *(*getRetValTLS)() = 0);
#ifdef __GNUC__
inline ModulePass *createDataFlowSanitizerPassForJIT() {
return createDataFlowSanitizerPass(getDFSanArgTLSPtrForJIT,
getDFSanRetValTLSPtrForJIT);
}
#endif
// BoundsChecking - This pass instruments the code to perform run-time bounds
// checking on loads, stores, and other memory intrinsics.
FunctionPass *createBoundsCheckingPass();

View File

@ -1,6 +1,7 @@
add_llvm_library(LLVMInstrumentation
AddressSanitizer.cpp
BoundsChecking.cpp
DataFlowSanitizer.cpp
DebugIR.cpp
EdgeProfiling.cpp
GCOVProfiling.cpp

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) {
initializePathProfilerPass(Registry);
initializeMemorySanitizerPass(Registry);
initializeThreadSanitizerPass(Registry);
initializeDataFlowSanitizerPass(Registry);
}
/// LLVMInitializeInstrumentation - C binding for

View File

@ -0,0 +1,62 @@
; RUN: opt < %s -dfsan -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
define i8 @add(i8 %a, i8 %b) {
; CHECK: @add
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: add i8
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
%c = add i8 %a, %b
ret i8 %c
}
define i8 @sub(i8 %a, i8 %b) {
; CHECK: @sub
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: sub i8
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
%c = sub i8 %a, %b
ret i8 %c
}
define i8 @mul(i8 %a, i8 %b) {
; CHECK: @mul
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: mul i8
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
%c = mul i8 %a, %b
ret i8 %c
}
define i8 @sdiv(i8 %a, i8 %b) {
; CHECK: @sdiv
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: sdiv i8
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
%c = sdiv i8 %a, %b
ret i8 %c
}
define i8 @udiv(i8 %a, i8 %b) {
; CHECK: @udiv
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}__dfsan_union
; CHECK: udiv i8
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
%c = udiv i8 %a, %b
ret i8 %c
}

View File

@ -0,0 +1,23 @@
; RUN: opt < %s -dfsan -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [64 x i16]
; CHECK: @__dfsan_retval_tls = external thread_local(initialexec) global i16
declare i32 @f(i32)
declare float @llvm.sqrt.f32(float)
; CHECK: @call
define i32 @call() {
; CHECK: store{{.*}}__dfsan_arg_tls
; CHECK: call{{.*}}@f
; CHECK: load{{.*}}__dfsan_retval_tls
%r = call i32 @f(i32 0)
; CHECK-NOT: store{{.*}}__dfsan_arg_tls
%i = call float @llvm.sqrt.f32(float -1.0)
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i32
ret i32 %r
}

View File

@ -0,0 +1 @@
config.suffixes = ['.ll', '.c', '.cpp']

View File

@ -0,0 +1,81 @@
; RUN: opt < %s -dfsan -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
define i8 @load8(i8* %p) {
; CHECK: @load8
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: load
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i8
%a = load i8* %p
ret i8 %a
}
define i16 @load16(i16* %p) {
; CHECK: @load16
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: load
; CHECK: load
; CHECK: icmp ne
; CHECK: call{{.*}}__dfsan_union
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i16
%a = load i16* %p
ret i16 %a
}
define i32 @load32(i32* %p) {
; CHECK: @load32
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: bitcast
; CHECK: load
; CHECK: trunc
; CHECK: shl
; CHECK: lshr
; CHECK: or
; CHECK: icmp eq
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i32
; CHECK: call{{.*}}__dfsan_union_load
%a = load i32* %p
ret i32 %a
}
define i64 @load64(i64* %p) {
; CHECK: @load64
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: bitcast
; CHECK: load
; CHECK: trunc
; CHECK: shl
; CHECK: lshr
; CHECK: or
; CHECK: icmp eq
; CHECK: store{{.*}}__dfsan_retval_tls
; CHECK: ret i64
; CHECK: call{{.*}}__dfsan_union_load
; CHECK: getelementptr
; CHECK: load
; CHECK: icmp eq
%a = load i64* %p
ret i64 %a
}

View File

@ -0,0 +1,75 @@
; RUN: opt < %s -dfsan -S | FileCheck %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
define void @store8(i8 %v, i8* %p) {
; CHECK: @store8
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: getelementptr
; CHECK: store
; CHECK: store
store i8 %v, i8* %p
ret void
}
define void @store16(i16 %v, i16* %p) {
; CHECK: @store16
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: getelementptr
; CHECK: store
; CHECK: getelementptr
; CHECK: store
; CHECK: store
store i16 %v, i16* %p
ret void
}
define void @store32(i32 %v, i32* %p) {
; CHECK: @store32
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: getelementptr
; CHECK: store
; CHECK: getelementptr
; CHECK: store
; CHECK: getelementptr
; CHECK: store
; CHECK: getelementptr
; CHECK: store
; CHECK: store
store i32 %v, i32* %p
ret void
}
define void @store64(i64 %v, i64* %p) {
; CHECK: @store64
; CHECK: load{{.*}}__dfsan_arg_tls
; CHECK: ptrtoint
; CHECK: and
; CHECK: mul
; CHECK: inttoptr
; CHECK: insertelement
; CHECK: insertelement
; CHECK: insertelement
; CHECK: insertelement
; CHECK: insertelement
; CHECK: insertelement
; CHECK: insertelement
; CHECK: insertelement
; CHECK: bitcast
; CHECK: getelementptr
; CHECK: store
; CHECK: store
store i64 %v, i64* %p
ret void
}