aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@imgtec.com>2017-08-17 14:14:25 +0000
committerSimon Dardis <simon.dardis@imgtec.com>2017-08-17 14:14:25 +0000
commit987e30d8673d9d1a683ef811e9b7e32d2fadeb8a (patch)
treef39716f03fdc9a74b1a9467b882abba0261a9469
parentc3fa9e8b811cde54fe226eee2af6241eedad6fb9 (diff)
[dfsan] Add explicit zero extensions for shadow parameters in function wrappers.
In the case where dfsan provides a custom wrapper for a function, shadow parameters are added for each parameter of the function. These parameters are i16s. For targets which do not consider this a legal type, the lack of sign extension information would cause LLVM to generate anyexts around their usage with phi variables and calling convention logic. Address this by introducing zero exts for each shadow parameter. Reviewers: pcc, slthakur Differential Revision: https://reviews.llvm.org/D33349 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311087 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Instrumentation/DataFlowSanitizer.cpp10
-rw-r--r--test/Instrumentation/DataFlowSanitizer/Inputs/shadow-args-abilist.txt8
-rw-r--r--test/Instrumentation/DataFlowSanitizer/abilist.ll10
-rw-r--r--test/Instrumentation/DataFlowSanitizer/shadow-args-zext.ll54
4 files changed, 77 insertions, 5 deletions
diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index a33490f6e4a..ddc975cbed1 100644
--- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -1470,6 +1470,7 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
}
i = CS.arg_begin();
+ const unsigned ShadowArgStart = Args.size();
for (unsigned n = FT->getNumParams(); n != 0; ++i, --n)
Args.push_back(DFSF.getShadow(*i));
@@ -1505,6 +1506,15 @@ void DFSanVisitor::visitCallSite(CallSite CS) {
CustomCI->setCallingConv(CI->getCallingConv());
CustomCI->setAttributes(CI->getAttributes());
+ // Update the parameter attributes of the custom call instruction to
+ // zero extend the shadow parameters. This is required for targets
+ // which consider ShadowTy an illegal type.
+ for (unsigned n = 0; n < FT->getNumParams(); n++) {
+ const unsigned ArgNo = ShadowArgStart + n;
+ if (CustomCI->getArgOperand(ArgNo)->getType() == DFSF.DFS.ShadowTy)
+ CustomCI->addParamAttr(ArgNo, Attribute::ZExt);
+ }
+
if (!FT->getReturnType()->isVoidTy()) {
LoadInst *LabelLoad = IRB.CreateLoad(DFSF.LabelReturnAlloca);
DFSF.setShadow(CustomCI, LabelLoad);
diff --git a/test/Instrumentation/DataFlowSanitizer/Inputs/shadow-args-abilist.txt b/test/Instrumentation/DataFlowSanitizer/Inputs/shadow-args-abilist.txt
new file mode 100644
index 00000000000..723cbc9086d
--- /dev/null
+++ b/test/Instrumentation/DataFlowSanitizer/Inputs/shadow-args-abilist.txt
@@ -0,0 +1,8 @@
+fun:dfsan_get_label=uninstrumented
+fun:dfsan_get_label=custom
+
+fun:k2=uninstrumented
+fun:k2=custom
+
+fun:k4=uninstrumented
+fun:k4=custom
diff --git a/test/Instrumentation/DataFlowSanitizer/abilist.ll b/test/Instrumentation/DataFlowSanitizer/abilist.ll
index 8b30875a03f..e33237ffe19 100644
--- a/test/Instrumentation/DataFlowSanitizer/abilist.ll
+++ b/test/Instrumentation/DataFlowSanitizer/abilist.ll
@@ -47,13 +47,13 @@ define void @f(i32 %x) {
; CHECK: %[[LABELVA1:.*]] = alloca [2 x i16]
; CHECK: %[[LABELRETURN:.*]] = alloca i16
- ; CHECK: call void @__dfsw_custom1(i32 1, i32 2, i16 0, i16 0)
+ ; CHECK: call void @__dfsw_custom1(i32 1, i32 2, i16 zeroext 0, i16 zeroext 0)
call void @custom1(i32 1, i32 2)
- ; CHECK: call i32 @__dfsw_custom2(i32 1, i32 2, i16 0, i16 0, i16* %[[LABELRETURN]])
+ ; CHECK: call i32 @__dfsw_custom2(i32 1, i32 2, i16 zeroext 0, i16 zeroext 0, i16* %[[LABELRETURN]])
call i32 @custom2(i32 1, i32 2)
- ; CHECK: call void @__dfsw_customcb({{.*}} @"dfst0$customcb", i8* bitcast ({{.*}} @"dfs$cb" to i8*), i16 0)
+ ; CHECK: call void @__dfsw_customcb({{.*}} @"dfst0$customcb", i8* bitcast ({{.*}} @"dfs$cb" to i8*), i16 zeroext 0)
call void @customcb(i32 (i32)* @cb)
; CHECK: %[[LABELVA1_0:.*]] = getelementptr inbounds [2 x i16], [2 x i16]* %[[LABELVA1]], i32 0, i32 0
@@ -61,12 +61,12 @@ define void @f(i32 %x) {
; CHECK: %[[LABELVA1_1:.*]] = getelementptr inbounds [2 x i16], [2 x i16]* %[[LABELVA1]], i32 0, i32 1
; CHECK: store i16 %{{.*}}, i16* %[[LABELVA1_1]]
; CHECK: %[[LABELVA1_0A:.*]] = getelementptr inbounds [2 x i16], [2 x i16]* %[[LABELVA1]], i32 0, i32 0
- ; CHECK: call void (i32, i16, i16*, ...) @__dfsw_custom3(i32 1, i16 0, i16* %[[LABELVA1_0A]], i32 2, i32 %{{.*}})
+ ; CHECK: call void (i32, i16, i16*, ...) @__dfsw_custom3(i32 1, i16 zeroext 0, i16* %[[LABELVA1_0A]], i32 2, i32 %{{.*}})
call void (i32, ...) @custom3(i32 1, i32 2, i32 %x)
; CHECK: %[[LABELVA2_0:.*]] = getelementptr inbounds [2 x i16], [2 x i16]* %[[LABELVA2]], i32 0, i32 0
; CHECK: %[[LABELVA2_0A:.*]] = getelementptr inbounds [2 x i16], [2 x i16]* %[[LABELVA2]], i32 0, i32 0
- ; CHECK: call i32 (i32, i16, i16*, i16*, ...) @__dfsw_custom4(i32 1, i16 0, i16* %[[LABELVA2_0A]], i16* %[[LABELRETURN]], i32 2, i32 3)
+ ; CHECK: call i32 (i32, i16, i16*, i16*, ...) @__dfsw_custom4(i32 1, i16 zeroext 0, i16* %[[LABELVA2_0A]], i16* %[[LABELRETURN]], i32 2, i32 3)
call i32 (i32, ...) @custom4(i32 1, i32 2, i32 3)
ret void
diff --git a/test/Instrumentation/DataFlowSanitizer/shadow-args-zext.ll b/test/Instrumentation/DataFlowSanitizer/shadow-args-zext.ll
new file mode 100644
index 00000000000..0ffbf1970e7
--- /dev/null
+++ b/test/Instrumentation/DataFlowSanitizer/shadow-args-zext.ll
@@ -0,0 +1,54 @@
+; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -dfsan -S --dfsan-abilist=%S/Inputs/shadow-args-abilist.txt | FileCheck %s
+
+; REQUIRES: x86-registered-target
+
+; Test that the custom abi marks shadow parameters as zero extended.
+
+define i32 @m() {
+entry:
+ %call = call zeroext i16 @dfsan_get_label(i64 signext 56)
+ %conv = zext i16 %call to i32
+ ret i32 %conv
+}
+
+; CHECK-LABEL: @"dfs$m"
+; CHECK: %{{.*}} = call zeroext i16 @__dfsw_dfsan_get_label(i64 signext 56, i16 zeroext 0, i16* %{{.*}})
+
+define i32 @k() {
+entry:
+ %call = call zeroext i16 @k2(i64 signext 56, i64 signext 67)
+ %conv = zext i16 %call to i32
+ ret i32 %conv
+}
+
+; CHECK-LABEL: @"dfs$k"
+; CHECK: %{{.*}} = call zeroext i16 @__dfsw_k2(i64 signext 56, i64 signext 67, i16 zeroext {{.*}}, i16 zeroext {{.*}}, i16* %{{.*}})
+
+define i32 @k3() {
+entry:
+ %call = call zeroext i16 @k4(i64 signext 56, i64 signext 67, i64 signext 78, i64 signext 89)
+ %conv = zext i16 %call to i32
+ ret i32 %conv
+}
+
+; CHECK-LABEL: @"dfs$k3"
+; CHECK: %{{.*}} = call zeroext i16 @__dfsw_k4(i64 signext 56, i64 signext 67, i64 signext 78, i64 signext 89, i16 zeroext {{.*}}, i16 zeroext {{.*}}, i16 zeroext {{.*}}, i16 zeroext {{.*}}, i16* %{{.*}})
+
+declare zeroext i16 @dfsan_get_label(i64 signext)
+
+; CHECK-LABEL: @"dfsw$dfsan_get_label"
+; CHECK: %{{.*}} = call i16 @__dfsw_dfsan_get_label(i64 %0, i16 zeroext %1, i16* %{{.*}})
+
+declare zeroext i16 @k2(i64 signext, i64 signext)
+; CHECK-LABEL: @"dfsw$k2"
+; CHECK: %{{.*}} = call i16 @__dfsw_k2(i64 %{{.*}}, i64 %{{.*}}, i16 zeroext %{{.*}}, i16 zeroext %{{.*}}, i16* %{{.*}})
+
+declare zeroext i16 @k4(i64 signext, i64 signext, i64 signext, i64 signext)
+
+; CHECK-LABEL: @"dfsw$k4"
+; CHECK: %{{.*}} = call i16 @__dfsw_k4(i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i16 zeroext %{{.*}}, i16 zeroext %{{.*}}, i16 zeroext %{{.*}}, i16 zeroext %{{.*}}, i16* %{{.*}})
+
+
+; CHECK: declare zeroext i16 @__dfsw_dfsan_get_label(i64 signext, i16, i16*)
+; CHECK: declare zeroext i16 @__dfsw_k2(i64 signext, i64 signext, i16, i16, i16*)
+; CHECK: declare zeroext i16 @__dfsw_k4(i64 signext, i64 signext, i64 signext, i64 signext, i16, i16, i16, i16, i16*)