Skip to content

Commit 6a9a686

Browse files
[dfsan] Tracking origins at phi nodes
This is a part of https://reviews.llvm.org/D95835. Reviewed-by: morehouse Differential Revision: https://reviews.llvm.org/D98268
1 parent 547624a commit 6a9a686

File tree

4 files changed

+186
-8
lines changed

4 files changed

+186
-8
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 -mllvm -dfsan-fast-16-labels=true %s -o %t && \
2+
// RUN: %run %t >%t.out 2>&1
3+
// RUN: FileCheck %s --check-prefix=CHECK < %t.out
4+
5+
#include <sanitizer/dfsan_interface.h>
6+
7+
__attribute__((noinline)) uint64_t foo(uint64_t x, uint64_t y) { return x + y; }
8+
9+
int main(int argc, char *argv[]) {
10+
uint64_t a = 10;
11+
uint64_t b = 20;
12+
dfsan_set_label(8, &a, sizeof(a));
13+
uint64_t c = foo(a, b);
14+
for (int i = 0; i < argc; ++i)
15+
c += foo(c, b);
16+
dfsan_print_origin_trace(&c, NULL);
17+
}
18+
19+
// CHECK: Taint value 0x8 {{.*}} origin tracking ()
20+
// CHECK: Origin value: {{.*}}, Taint value was stored to memory at
21+
// CHECK: #0 {{.*}} in main {{.*}}origin_branch.c:[[@LINE-6]]
22+
23+
// CHECK: Origin value: {{.*}}, Taint value was stored to memory at
24+
// CHECK: #0 {{.*}} in main {{.*}}origin_branch.c:[[@LINE-11]]
25+
26+
// CHECK: Origin value: {{.*}}, Taint value was created at
27+
// CHECK: #0 {{.*}} in main {{.*}}origin_branch.c:[[@LINE-15]]

llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,13 @@ struct DFSanFunction {
518518
DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
519519
DenseMap<AllocaInst *, AllocaInst *> AllocaOriginMap;
520520

521-
std::vector<std::pair<PHINode *, PHINode *>> PHIFixups;
521+
struct PHIFixupElement {
522+
PHINode *Phi;
523+
PHINode *ShadowPhi;
524+
PHINode *OriginPhi;
525+
};
526+
std::vector<PHIFixupElement> PHIFixups;
527+
522528
DenseSet<Instruction *> SkipInsts;
523529
std::vector<Value *> NonZeroChecks;
524530
bool AvoidNewBlocks;
@@ -1563,12 +1569,14 @@ bool DataFlowSanitizer::runImpl(Module &M) {
15631569
// until we have visited every block. Therefore, the code that handles phi
15641570
// nodes adds them to the PHIFixups list so that they can be properly
15651571
// handled here.
1566-
for (auto PHIFixup : DFSF.PHIFixups) {
1567-
PHINode *PN, *ShadowPN;
1568-
std::tie(PN, ShadowPN) = PHIFixup;
1569-
for (unsigned Val = 0, N = PN->getNumIncomingValues(); Val < N; ++Val) {
1570-
ShadowPN->setIncomingValue(Val,
1571-
DFSF.getShadow(PN->getIncomingValue(Val)));
1572+
for (DFSanFunction::PHIFixupElement &P : DFSF.PHIFixups) {
1573+
for (unsigned Val = 0, N = P.Phi->getNumIncomingValues(); Val != N;
1574+
++Val) {
1575+
P.ShadowPhi->setIncomingValue(
1576+
Val, DFSF.getShadow(P.Phi->getIncomingValue(Val)));
1577+
if (P.OriginPhi)
1578+
P.OriginPhi->setIncomingValue(
1579+
Val, DFSF.getOrigin(P.Phi->getIncomingValue(Val)));
15721580
}
15731581
}
15741582

@@ -3123,8 +3131,19 @@ void DFSanVisitor::visitPHINode(PHINode &PN) {
31233131
for (BasicBlock *BB : PN.blocks())
31243132
ShadowPN->addIncoming(UndefShadow, BB);
31253133

3126-
DFSF.PHIFixups.push_back(std::make_pair(&PN, ShadowPN));
31273134
DFSF.setShadow(&PN, ShadowPN);
3135+
3136+
PHINode *OriginPN = nullptr;
3137+
if (DFSF.DFS.shouldTrackOrigins()) {
3138+
OriginPN =
3139+
PHINode::Create(DFSF.DFS.OriginTy, PN.getNumIncomingValues(), "", &PN);
3140+
Value *UndefOrigin = UndefValue::get(DFSF.DFS.OriginTy);
3141+
for (BasicBlock *BB : PN.blocks())
3142+
OriginPN->addIncoming(UndefOrigin, BB);
3143+
DFSF.setOrigin(&PN, OriginPN);
3144+
}
3145+
3146+
DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
31283147
}
31293148

31303149
namespace {
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefix=CHECK
2+
;
3+
; %15 and %17 have the same key in shadow cache. They should not reuse the same
4+
; shadow because their blocks do not dominate each other. Origin tracking
5+
; splt blocks. This test ensures DT is updated correctly, and cached shadows
6+
; are not mis-used.
7+
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"
8+
target triple = "x86_64-unknown-linux-gnu"
9+
10+
; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]]
11+
; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]]
12+
; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]]
13+
14+
define void @cached_shadows(double %0) {
15+
; CHECK: @"dfs$cached_shadows"
16+
; CHECK: [[AO:%.*]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4
17+
; CHECK: [[AS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[#SBYTES]]
18+
; CHECK: [[L1:[0-9]+]]:
19+
; CHECK: {{.*}} = phi i[[#SBITS]]
20+
; CHECK: {{.*}} = phi i32
21+
; CHECK: {{.*}} = phi double [ 3.000000e+00
22+
; CHECK: [[S_L1:%.*]] = phi i[[#SBITS]] [ 0, %[[L0:[0-9]+]] ], [ [[S_L7:%.*]], %[[L7:[0-9]+]] ]
23+
; CHECK: [[O_L1:%.*]] = phi i32 [ 0, %[[L0]] ], [ [[O_L7:%.*]], %[[L7]] ]
24+
; CHECK: [[V_L1:%.*]] = phi double [ 4.000000e+00, %[[L0]] ], [ [[V_L7:%.*]], %[[L7]] ]
25+
; CHECK: br i1 {{%[0-9]+}}, label %[[L2:[0-9]+]], label %[[L4:[0-9]+]]
26+
; CHECK: [[L2]]:
27+
; CHECK: br i1 {{%[0-9]+}}, label %[[L3:[0-9]+]], label %[[L7]]
28+
; CHECK: [[L3]]:
29+
; CHECK: [[S_L3:%.*]] = or i[[#SBITS]]
30+
; CHECK: [[AS_NE_L3:%.*]] = icmp ne i[[#SBITS]] [[AS]], 0
31+
; CHECK: [[O_L3:%.*]] = select i1 [[AS_NE_L3]], i32 %2, i32 [[O_L1]]
32+
; CHECK: [[V_L3:%.*]] = fsub double [[V_L1]], %0
33+
; CHECK: br label %[[L7]]
34+
; CHECK: [[L4]]:
35+
; CHECK: br i1 %_dfscmp, label %[[L5:[0-9]+]], label %[[L6:[0-9]+]]
36+
; CHECK: [[L5]]:
37+
; CHECK: br label %[[L6]]
38+
; CHECK: [[L6]]:
39+
; CHECK: [[S_L6:%.*]] = or i[[#SBITS]]
40+
; CHECK: [[AS_NE_L6:%.*]] = icmp ne i[[#SBITS]] [[AS]], 0
41+
; CHECK: [[O_L6:%.*]] = select i1 [[AS_NE_L6]], i32 [[AO]], i32 [[O_L1]]
42+
; CHECK: [[V_L6:%.*]] = fadd double %24, %0
43+
; CHECK: br label %[[L7]]
44+
; CHECK: [[L7]]:
45+
; CHECK: [[S_L7]] = phi i[[#SBITS]] [ [[S_L3]], %[[L3]] ], [ [[S_L1]], %[[L2]] ], [ [[S_L6]], %[[L6]] ]
46+
; CHECK: [[O_L7]] = phi i32 [ [[O_L3]], %[[L3]] ], [ [[O_L1]], %[[L2]] ], [ [[O_L6]], %[[L6]] ]
47+
; CHECK: [[V_L7]] = phi double [ [[V_L3]], %[[L3]] ], [ [[V_L1]], %[[L2]] ], [ [[V_L6]], %[[L6]] ]
48+
; CHECK: br i1 {{%[0-9]+}}, label %[[L1]], label %[[L8:[0-9]+]]
49+
; CHECK: [[L8]]:
50+
51+
%2 = alloca double, align 8
52+
%3 = alloca double, align 8
53+
%4 = bitcast double* %2 to i8*
54+
store volatile double 1.000000e+00, double* %2, align 8
55+
%5 = bitcast double* %3 to i8*
56+
store volatile double 2.000000e+00, double* %3, align 8
57+
br label %6
58+
59+
6: ; preds = %18, %1
60+
%7 = phi double [ 3.000000e+00, %1 ], [ %19, %18 ]
61+
%8 = phi double [ 4.000000e+00, %1 ], [ %20, %18 ]
62+
%9 = load volatile double, double* %3, align 8
63+
%10 = fcmp une double %9, 0.000000e+00
64+
%11 = load volatile double, double* %3, align 8
65+
br i1 %10, label %12, label %16
66+
67+
12: ; preds = %6
68+
%13 = fcmp une double %11, 0.000000e+00
69+
br i1 %13, label %14, label %18
70+
71+
14: ; preds = %12
72+
%15 = fsub double %8, %0
73+
br label %18
74+
75+
16: ; preds = %6
76+
store volatile double %11, double* %2, align 8
77+
%17 = fadd double %8, %0
78+
br label %18
79+
80+
18: ; preds = %16, %14, %12
81+
%19 = phi double [ %8, %14 ], [ %7, %12 ], [ %8, %16 ]
82+
%20 = phi double [ %15, %14 ], [ %8, %12 ], [ %17, %16 ]
83+
%21 = fcmp olt double %19, 9.900000e+01
84+
br i1 %21, label %6, label %22
85+
86+
22: ; preds = %18
87+
ret void
88+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-fast-16-labels=true -S | FileCheck %s --check-prefix=CHECK
2+
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"
3+
target triple = "x86_64-unknown-linux-gnu"
4+
5+
; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]]
6+
; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]]
7+
; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]]
8+
9+
define i32 @phiop(i32 %a, i32 %b, i1 %c) {
10+
; CHECK: @"dfs$phiop"
11+
; CHECK: entry:
12+
; CHECK: [[BO:%.*]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
13+
; CHECK: [[AO:%.*]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4
14+
; CHECK: [[BS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([[TLS_ARR]]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[#SBYTES]]
15+
; CHECK: [[AS:%.*]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([[TLS_ARR]]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[#SBYTES]]
16+
; CHECK: br i1 %c, label %next, label %done
17+
; CHECK: next:
18+
; CHECK: br i1 %c, label %T, label %F
19+
; CHECK: T:
20+
; CHECK: [[BS_NE:%.*]] = icmp ne i[[#SBITS]] [[BS]], 0
21+
; CHECK: [[BAO_T:%.*]] = select i1 [[BS_NE]], i32 [[BO]], i32 [[AO]]
22+
; CHECK: br label %done
23+
; CHECK: F:
24+
; CHECK: [[AS_NE:%.*]] = icmp ne i[[#SBITS]] [[AS]], 0
25+
; CHECK: [[BAO_F:%.*]] = select i1 [[AS_NE]], i32 [[AO]], i32 [[BO]]
26+
; CHECK: br label %done
27+
; CHECK: done:
28+
; CHECK: [[PO:%.*]] = phi i32 [ [[BAO_T]], %T ], [ [[BAO_F]], %F ], [ [[AO]], %entry ]
29+
; CHECK: store i32 [[PO]], i32* @__dfsan_retval_origin_tls, align 4
30+
31+
entry:
32+
br i1 %c, label %next, label %done
33+
next:
34+
br i1 %c, label %T, label %F
35+
T:
36+
%sum = add i32 %a, %b
37+
br label %done
38+
F:
39+
%diff = sub i32 %b, %a
40+
br label %done
41+
done:
42+
%r = phi i32 [%sum, %T], [%diff, %F], [%a, %entry]
43+
ret i32 %r
44+
}

0 commit comments

Comments
 (0)