[llvm] 14ce567 - [DFSan] Add `zeroext` attribute for callbacks with 8bit shadow variable arguments
Weining Lu via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 28 19:52:02 PST 2022
Author: Weining Lu
Date: 2022-12-29T11:37:47+08:00
New Revision: 14ce567fa267cce9466354bed1549a83286866b1
URL: https://github.com/llvm/llvm-project/commit/14ce567fa267cce9466354bed1549a83286866b1
DIFF: https://github.com/llvm/llvm-project/commit/14ce567fa267cce9466354bed1549a83286866b1.diff
LOG: [DFSan] Add `zeroext` attribute for callbacks with 8bit shadow variable arguments
Add `zeroext` attribute for below callbacks' first parameter
(8bit shadow variable arguments) to conform to many platforms'
ABI calling convention and some compiler behavior.
- __dfsan_load_callback
- __dfsan_store_callback
- __dfsan_cmp_callback
- __dfsan_conditional_callback
- __dfsan_conditional_callback_origin
- __dfsan_reaches_function_callback
- __dfsan_reaches_function_callback_origin
The type of these callbacks' first parameter is u8 (see the
definition of `dfsan_label`). First, many platforms' ABI
requires unsigned integer data types (except unsigned int)
are zero-extended when stored in general-purpose register.
Second, the problem is that compiler optimization may assume
the arguments are zero-extended and, if not, misbehave, e.g.
it uses an `i8` argument to index into a jump table. If the
argument has non-zero high bits, the output executable may
crash at run-time. So we need to add the `zeroext` attribute
when declaring and calling them.
Reviewed By: browneee, MaskRay
Differential Revision: https://reviews.llvm.org/D140689
Added:
Modified:
llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
llvm/test/Instrumentation/DataFlowSanitizer/array.ll
llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
llvm/test/Instrumentation/DataFlowSanitizer/callback.ll
llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll
llvm/test/Instrumentation/DataFlowSanitizer/struct.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index d5896246a3675..f4964df1f3266 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -1033,13 +1033,15 @@ void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &I,
}
IRBuilder<> IRB(&I);
Value *CondShadow = getShadow(Condition);
+ CallInst *CI;
if (DFS.shouldTrackOrigins()) {
Value *CondOrigin = getOrigin(Condition);
- IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn,
- {CondShadow, CondOrigin});
+ CI = IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn,
+ {CondShadow, CondOrigin});
} else {
- IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
+ CI = IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
}
+ CI->addParamAttr(0, Attribute::ZExt);
}
void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB,
@@ -1078,6 +1080,7 @@ void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB,
args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackFn, args);
}
+ CB->addParamAttr(0, Attribute::ZExt);
CB->setDebugLoc(dbgloc);
}
@@ -1413,25 +1416,53 @@ void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
// Initializes event callback functions and declare them in the module
void DataFlowSanitizer::initializeCallbackFunctions(Module &M) {
- DFSanLoadCallbackFn = Mod->getOrInsertFunction("__dfsan_load_callback",
- DFSanLoadStoreCallbackFnTy);
- DFSanStoreCallbackFn = Mod->getOrInsertFunction("__dfsan_store_callback",
- DFSanLoadStoreCallbackFnTy);
+ {
+ AttributeList AL;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ DFSanLoadCallbackFn = Mod->getOrInsertFunction(
+ "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
+ }
+ {
+ AttributeList AL;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ DFSanStoreCallbackFn = Mod->getOrInsertFunction(
+ "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
+ }
DFSanMemTransferCallbackFn = Mod->getOrInsertFunction(
"__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
- DFSanCmpCallbackFn =
- Mod->getOrInsertFunction("__dfsan_cmp_callback", DFSanCmpCallbackFnTy);
-
- DFSanConditionalCallbackFn = Mod->getOrInsertFunction(
- "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy);
- DFSanConditionalCallbackOriginFn =
- Mod->getOrInsertFunction("__dfsan_conditional_callback_origin",
- DFSanConditionalCallbackOriginFnTy);
- DFSanReachesFunctionCallbackFn = Mod->getOrInsertFunction(
- "__dfsan_reaches_function_callback", DFSanReachesFunctionCallbackFnTy);
- DFSanReachesFunctionCallbackOriginFn =
- Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin",
- DFSanReachesFunctionCallbackOriginFnTy);
+ {
+ AttributeList AL;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback",
+ DFSanCmpCallbackFnTy, AL);
+ }
+ {
+ AttributeList AL;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ DFSanConditionalCallbackFn = Mod->getOrInsertFunction(
+ "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
+ }
+ {
+ AttributeList AL;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ DFSanConditionalCallbackOriginFn =
+ Mod->getOrInsertFunction("__dfsan_conditional_callback_origin",
+ DFSanConditionalCallbackOriginFnTy, AL);
+ }
+ {
+ AttributeList AL;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ DFSanReachesFunctionCallbackFn =
+ Mod->getOrInsertFunction("__dfsan_reaches_function_callback",
+ DFSanReachesFunctionCallbackFnTy, AL);
+ }
+ {
+ AttributeList AL;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ DFSanReachesFunctionCallbackOriginFn =
+ Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin",
+ DFSanReachesFunctionCallbackOriginFnTy, AL);
+ }
}
void DataFlowSanitizer::injectMetadataGlobals(Module &M) {
@@ -2403,7 +2434,9 @@ void DFSanVisitor::visitLoadInst(LoadInst &LI) {
if (ClEventCallbacks) {
IRBuilder<> IRB(Pos);
Value *Addr8 = IRB.CreateBitCast(LI.getPointerOperand(), DFSF.DFS.Int8Ptr);
- IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8});
+ CallInst *CI =
+ IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8});
+ CI->addParamAttr(0, Attribute::ZExt);
}
IRBuilder<> IRB(AfterLi);
@@ -2663,7 +2696,9 @@ void DFSanVisitor::visitStoreInst(StoreInst &SI) {
if (ClEventCallbacks) {
IRBuilder<> IRB(&SI);
Value *Addr8 = IRB.CreateBitCast(SI.getPointerOperand(), DFSF.DFS.Int8Ptr);
- IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8});
+ CallInst *CI =
+ IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8});
+ CI->addParamAttr(0, Attribute::ZExt);
}
}
@@ -2725,7 +2760,9 @@ void DFSanVisitor::visitCmpInst(CmpInst &CI) {
if (ClEventCallbacks) {
IRBuilder<> IRB(&CI);
Value *CombinedShadow = DFSF.getShadow(&CI);
- IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
+ CallInst *CallI =
+ IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
+ CallI->addParamAttr(0, Attribute::ZExt);
}
}
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/array.ll b/llvm/test/Instrumentation/DataFlowSanitizer/array.ll
index e25387157b504..c8c93efb9b980 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/array.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/array.ll
@@ -81,7 +81,7 @@ define [1 x i1] @load_array1(ptr %p) {
; EVENT_CALLBACKS: @load_array1.dfsan
; EVENT_CALLBACKS: [[L:%.*]] = or i[[#SBITS]]
- ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[L]], ptr {{.*}})
+ ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[L]], ptr {{.*}})
; FAST: @load_array1.dfsan
; FAST: [[P:%.*]] = load i[[#SBITS]], ptr @__dfsan_arg_tls, align [[ALIGN:2]]
@@ -107,7 +107,7 @@ define [2 x i1] @load_array2(ptr %p) {
; EVENT_CALLBACKS: @load_array2.dfsan
; EVENT_CALLBACKS: [[O1:%.*]] = or i[[#SBITS]]
; EVENT_CALLBACKS: [[O2:%.*]] = or i[[#SBITS]] [[O1]]
- ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[O2]], ptr {{.*}})
+ ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[O2]], ptr {{.*}})
; FAST: @load_array2.dfsan
; FAST: [[P:%.*]] = load i[[#SBITS]], ptr @__dfsan_arg_tls, align [[ALIGN:2]]
@@ -134,7 +134,7 @@ define [4 x i1] @load_array4(ptr %p) {
; EVENT_CALLBACKS: [[O1:%.*]] = or i[[#mul(4, SBITS)]] [[O0]]
; EVENT_CALLBACKS: [[O2:%.*]] = trunc i[[#mul(4, SBITS)]] [[O1]] to i[[#SBITS]]
; EVENT_CALLBACKS: [[O3:%.*]] = or i[[#SBITS]] [[O2]]
- ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[O3]], ptr {{.*}})
+ ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[O3]], ptr {{.*}})
; FAST: @load_array4.dfsan
; FAST: [[T:%.*]] = trunc i[[#mul(4, SBITS)]] {{.*}} to i[[#SBITS]]
@@ -196,7 +196,7 @@ define void @store_zero_array(ptr %p) {
define void @store_array2([2 x i1] %a, ptr %p) {
; EVENT_CALLBACKS: @store_array2.dfsan
; EVENT_CALLBACKS: [[E12:%.*]] = or i[[#SBITS]]
- ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] [[E12]], ptr %p)
+ ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] zeroext [[E12]], ptr %p)
; FAST: @store_array2.dfsan
; FAST: [[S:%.*]] = load [2 x i[[#SBITS]]], ptr @__dfsan_arg_tls, align [[ALIGN:2]]
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
index 1890053ae72a0..567a512093bce 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/basic.ll
@@ -30,10 +30,10 @@ define void @store(ptr %p) {
ret void
}
-; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]], ptr)
-; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]], ptr)
+; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]] zeroext, ptr)
+; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]] zeroext, ptr)
; CHECK: declare void @__dfsan_mem_transfer_callback(ptr, i64)
-; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]])
+; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]] zeroext)
; CHECK: ; Function Attrs: nounwind memory(read)
; CHECK-NEXT: declare zeroext i[[#SBITS]] @__dfsan_union_load(ptr, i64)
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll b/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll
index 19b7f2ee61c96..4bd8e7b1ccb6c 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/callback.ll
@@ -6,7 +6,7 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]]
define i8 @load8(ptr %p) {
- ; CHECK: call void @__dfsan_load_callback(i[[#SBITS]] %[[LABEL:.*]], ptr %p)
+ ; CHECK: call void @__dfsan_load_callback(i[[#SBITS]] zeroext %[[LABEL:.*]], ptr %p)
; CHECK: %a = load i8, ptr %p
; CHECK: store i[[#SBITS]] %[[LABEL]], ptr @__dfsan_retval_tls
@@ -16,7 +16,7 @@ define i8 @load8(ptr %p) {
define void @store8(ptr %p, i8 %a) {
; CHECK: store i[[#SBITS]] %[[LABEL:.*]], ptr %{{.*}}
- ; CHECK: call void @__dfsan_store_callback(i[[#SBITS]] %[[LABEL]], ptr %p)
+ ; CHECK: call void @__dfsan_store_callback(i[[#SBITS]] zeroext %[[LABEL]], ptr %p)
; CHECK: store i8 %a, ptr %p
store i8 %a, ptr %p
@@ -24,10 +24,19 @@ define void @store8(ptr %p, i8 %a) {
}
define i1 @cmp(i8 %a, i8 %b) {
- ; CHECK: call void @__dfsan_cmp_callback(i[[#SBITS]] %[[CMPLABEL:.*]])
+ ; CHECK: call void @__dfsan_cmp_callback(i[[#SBITS]] zeroext %[[CMPLABEL:.*]])
; CHECK: %c = icmp ne i8 %a, %b
; CHECK: store i[[#SBITS]] %[[CMPLABEL]], ptr @__dfsan_retval_tls
%c = icmp ne i8 %a, %b
ret i1 %c
-}
\ No newline at end of file
+}
+
+; CHECK: declare void @__dfsan_load_callback(i[[#SBITS]] zeroext, ptr)
+; CHECK: declare void @__dfsan_store_callback(i[[#SBITS]] zeroext, ptr)
+; CHECK: declare void @__dfsan_mem_transfer_callback(ptr, i64)
+; CHECK: declare void @__dfsan_cmp_callback(i[[#SBITS]] zeroext)
+; CHECK: declare void @__dfsan_conditional_callback(i[[#SBITS]] zeroext)
+; CHECK: declare void @__dfsan_conditional_callback_origin(i[[#SBITS]] zeroext, i32)
+; CHECK: declare void @__dfsan_reaches_function_callback(i[[#SBITS]] zeroext, ptr, i32, ptr)
+; CHECK: declare void @__dfsan_reaches_function_callback_origin(i[[#SBITS]] zeroext, i32, ptr, i32, ptr)
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll b/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll
index 654696833a671..9e47795e1ba62 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/reaches_function.ll
@@ -26,4 +26,4 @@ define void @call() {
ret void
}
-; CHECK-LABEL: @__dfsan_reaches_function_callback(i8, ptr, i32, ptr)
+; CHECK-LABEL: @__dfsan_reaches_function_callback(i8 zeroext, ptr, i32, ptr)
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll b/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll
index cdb8c30f1ab08..08e2fc678f392 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/struct.ll
@@ -133,7 +133,7 @@ define {i1, i1} @load_struct(ptr %p) {
; EVENT_CALLBACKS: [[OL0:%.*]] = or i[[#SBITS]]
; EVENT_CALLBACKS: [[OL1:%.*]] = or i[[#SBITS]] [[OL0]],
; EVENT_CALLBACKS: [[S0:%.*]] = insertvalue { i[[#SBITS]], i[[#SBITS]] } undef, i[[#SBITS]] [[OL1]], 0
- ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] [[OL1]]
+ ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i[[#SBITS]] zeroext [[OL1]]
%s = load {i1, i1}, ptr %p
ret {i1, i1} %s
@@ -152,7 +152,7 @@ define void @store_struct(ptr %p, {i1, i1} %s) {
; EVENT_CALLBACKS: @store_struct.dfsan
; EVENT_CALLBACKS: [[OL:%.*]] = or i[[#SBITS]]
- ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] [[OL]]
+ ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i[[#SBITS]] zeroext [[OL]]
; COMBINE_STORE_PTR: @store_struct.dfsan
; COMBINE_STORE_PTR: [[PL:%.*]] = load i[[#SBITS]], ptr @__dfsan_arg_tls, align [[ALIGN:2]]
More information about the llvm-commits
mailing list