llvm.org GIT mirror llvm / a56c8a9
[ASan] Make ASan instrument variable-masked loads and stores Summary: Previously we only supported constant-masked loads and stores. Reviewers: kcc, RKSimon, pgousseau, gbedwell, vitalybuka Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D28370 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291238 91177308-0d34-0410-b5e6-96231b3b80d8 Filipe Cabecinhas 3 years ago
2 changed file(s) with 130 addition(s) and 44 deletion(s). Raw diff Collapse all Expand all
513513 void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
514514 Value *Addr, uint32_t TypeSize, bool IsWrite,
515515 Value *SizeArgument, bool UseCalls, uint32_t Exp);
516 void instrumentUnusualSizeOrAlignment(Instruction *I, Value *Addr,
516 void instrumentUnusualSizeOrAlignment(Instruction *I,
517 Instruction *InsertBefore, Value *Addr,
517518 uint32_t TypeSize, bool IsWrite,
518519 Value *SizeArgument, bool UseCalls,
519520 uint32_t Exp);
10551056 return nullptr;
10561057 *IsWrite = false;
10571058 }
1058 // Only instrument if the mask is constant for now.
1059 if (isa(CI->getOperand(2 + OpOffset))) {
1060 auto BasePtr = CI->getOperand(0 + OpOffset);
1061 auto Ty = cast(BasePtr->getType())->getElementType();
1062 *TypeSize = DL.getTypeStoreSizeInBits(Ty);
1063 if (auto AlignmentConstant =
1064 dyn_cast(CI->getOperand(1 + OpOffset)))
1065 *Alignment = (unsigned)AlignmentConstant->getZExtValue();
1066 else
1067 *Alignment = 1; // No alignment guarantees. We probably got Undef
1068 if (MaybeMask)
1069 *MaybeMask = CI->getOperand(2 + OpOffset);
1070 PtrOperand = BasePtr;
1071 }
1059
1060 auto BasePtr = CI->getOperand(0 + OpOffset);
1061 auto Ty = cast(BasePtr->getType())->getElementType();
1062 *TypeSize = DL.getTypeStoreSizeInBits(Ty);
1063 if (auto AlignmentConstant =
1064 dyn_cast(CI->getOperand(1 + OpOffset)))
1065 *Alignment = (unsigned)AlignmentConstant->getZExtValue();
1066 else
1067 *Alignment = 1; // No alignment guarantees. We probably got Undef
1068 if (MaybeMask)
1069 *MaybeMask = CI->getOperand(2 + OpOffset);
1070 PtrOperand = BasePtr;
10721071 }
10731072 }
10741073
11291128 }
11301129
11311130 static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
1132 Value *Addr, unsigned Alignment,
1133 unsigned Granularity, uint32_t TypeSize,
1134 bool IsWrite, Value *SizeArgument,
1135 bool UseCalls, uint32_t Exp) {
1131 Instruction *InsertBefore, Value *Addr,
1132 unsigned Alignment, unsigned Granularity,
1133 uint32_t TypeSize, bool IsWrite,
1134 Value *SizeArgument, bool UseCalls,
1135 uint32_t Exp) {
11361136 // Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check
11371137 // if the data is properly aligned.
11381138 if ((TypeSize == 8 || TypeSize == 16 || TypeSize == 32 || TypeSize == 64 ||
11391139 TypeSize == 128) &&
11401140 (Alignment >= Granularity || Alignment == 0 || Alignment >= TypeSize / 8))
1141 return Pass->instrumentAddress(I, I, Addr, TypeSize, IsWrite, nullptr,
1142 UseCalls, Exp);
1143 Pass->instrumentUnusualSizeOrAlignment(I, Addr, TypeSize, IsWrite, nullptr,
1144 UseCalls, Exp);
1141 return Pass->instrumentAddress(I, InsertBefore, Addr, TypeSize, IsWrite,
1142 nullptr, UseCalls, Exp);
1143 Pass->instrumentUnusualSizeOrAlignment(I, InsertBefore, Addr, TypeSize,
1144 IsWrite, nullptr, UseCalls, Exp);
11451145 }
11461146
11471147 static void instrumentMaskedLoadOrStore(AddressSanitizer *Pass,
11481148 const DataLayout &DL, Type *IntptrTy,
1149 ConstantVector *Mask, Instruction *I,
1149 Value *Mask, Instruction *I,
11501150 Value *Addr, unsigned Alignment,
11511151 unsigned Granularity, uint32_t TypeSize,
11521152 bool IsWrite, Value *SizeArgument,
11561156 unsigned Num = VTy->getVectorNumElements();
11571157 auto Zero = ConstantInt::get(IntptrTy, 0);
11581158 for (unsigned Idx = 0; Idx < Num; ++Idx) {
1159 // dyn_cast as we might get UndefValue
1160 auto Masked = dyn_cast(Mask->getOperand(Idx));
1161 if (Masked && Masked->isAllOnesValue()) {
1159 Value *InstrumentedAddress = nullptr;
1160 Instruction *InsertBefore = I;
1161 if (auto *Vector = dyn_cast(Mask)) {
1162 // dyn_cast as we might get UndefValue
1163 if (auto *Masked = dyn_cast(Vector->getOperand(Idx))) {
1164 if (Masked->isNullValue())
1165 // Mask is constant false, so no instrumentation needed.
1166 continue;
1167 // If we have a true or undef value, fall through to doInstrumentAddress
1168 // with InsertBefore == I
1169 }
1170 } else {
11621171 IRBuilder<> IRB(I);
1163 auto InstrumentedAddress =
1164 IRB.CreateGEP(Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
1165 doInstrumentAddress(Pass, I, InstrumentedAddress, Alignment, Granularity,
1166 ElemTypeSize, IsWrite, SizeArgument, UseCalls, Exp);
1167 }
1172 Value *MaskElem = IRB.CreateExtractElement(Mask, Idx);
1173 TerminatorInst *ThenTerm = SplitBlockAndInsertIfThen(MaskElem, I, false);
1174 InsertBefore = ThenTerm;
1175 }
1176
1177 IRBuilder<> IRB(InsertBefore);
1178 InstrumentedAddress =
1179 IRB.CreateGEP(Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
1180 doInstrumentAddress(Pass, I, InsertBefore, InstrumentedAddress, Alignment,
1181 Granularity, ElemTypeSize, IsWrite, SizeArgument,
1182 UseCalls, Exp);
11681183 }
11691184 }
11701185
12191234
12201235 unsigned Granularity = 1 << Mapping.Scale;
12211236 if (MaybeMask) {
1222 auto Mask = cast(MaybeMask);
1223 instrumentMaskedLoadOrStore(this, DL, IntptrTy, Mask, I, Addr, Alignment,
1224 Granularity, TypeSize, IsWrite, nullptr,
1225 UseCalls, Exp);
1237 instrumentMaskedLoadOrStore(this, DL, IntptrTy, MaybeMask, I, Addr,
1238 Alignment, Granularity, TypeSize, IsWrite,
1239 nullptr, UseCalls, Exp);
12261240 } else {
1227 doInstrumentAddress(this, I, Addr, Alignment, Granularity, TypeSize,
1241 doInstrumentAddress(this, I, I, Addr, Alignment, Granularity, TypeSize,
12281242 IsWrite, nullptr, UseCalls, Exp);
12291243 }
12301244 }
13411355 // and the last bytes. We call __asan_report_*_n(addr, real_size) to be able
13421356 // to report the actual access size.
13431357 void AddressSanitizer::instrumentUnusualSizeOrAlignment(
1344 Instruction *I, Value *Addr, uint32_t TypeSize, bool IsWrite,
1345 Value *SizeArgument, bool UseCalls, uint32_t Exp) {
1346 IRBuilder<> IRB(I);
1358 Instruction *I, Instruction *InsertBefore, Value *Addr, uint32_t TypeSize,
1359 bool IsWrite, Value *SizeArgument, bool UseCalls, uint32_t Exp) {
1360 IRBuilder<> IRB(InsertBefore);
13471361 Value *Size = ConstantInt::get(IntptrTy, TypeSize / 8);
13481362 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
13491363 if (UseCalls) {
13571371 Value *LastByte = IRB.CreateIntToPtr(
13581372 IRB.CreateAdd(AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)),
13591373 Addr->getType());
1360 instrumentAddress(I, I, Addr, 8, IsWrite, Size, false, Exp);
1361 instrumentAddress(I, I, LastByte, 8, IsWrite, Size, false, Exp);
1374 instrumentAddress(I, InsertBefore, Addr, 8, IsWrite, Size, false, Exp);
1375 instrumentAddress(I, InsertBefore, LastByte, 8, IsWrite, Size, false, Exp);
13621376 }
13631377 }
13641378
7272 define void @store.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) sanitize_address {
7373 ; ALL-LABEL: @store.v4f32.variable
7474 %p = load <4 x float>*, <4 x float>** @v4f32, align 8
75 ; ALL-NOT: call void @__asan_store
75 ; STORE: [[MASK0:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 0
76 ; STORE: br i1 [[MASK0]], label %[[THEN0:[0-9A-Za-z]+]], label %[[AFTER0:[0-9A-Za-z]+]]
77 ; STORE:
78 ; STORE: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
79 ; STORE: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
80 ; STORE: call void @__asan_store4(i64 [[PGEP0]])
81 ; STORE: br label %[[AFTER0]]
82 ; STORE:
83
84 ; STORE: [[MASK1:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 1
85 ; STORE: br i1 [[MASK1]], label %[[THEN1:[0-9A-Za-z]+]], label %[[AFTER1:[0-9A-Za-z]+]]
86 ; STORE:
87 ; STORE: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
88 ; STORE: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
89 ; STORE: call void @__asan_store4(i64 [[PGEP1]])
90 ; STORE: br label %[[AFTER1]]
91 ; STORE:
92
93 ; STORE: [[MASK2:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 2
94 ; STORE: br i1 [[MASK2]], label %[[THEN2:[0-9A-Za-z]+]], label %[[AFTER2:[0-9A-Za-z]+]]
95 ; STORE:
96 ; STORE: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
97 ; STORE: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
98 ; STORE: call void @__asan_store4(i64 [[PGEP2]])
99 ; STORE: br label %[[AFTER2]]
100 ; STORE:
101
102 ; STORE: [[MASK3:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 3
103 ; STORE: br i1 [[MASK3]], label %[[THEN3:[0-9A-Za-z]+]], label %[[AFTER3:[0-9A-Za-z]+]]
104 ; STORE:
105 ; STORE: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
106 ; STORE: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
107 ; STORE: call void @__asan_store4(i64 [[PGEP3]])
108 ; STORE: br label %[[AFTER3]]
109 ; STORE:
110
111 ; STORE: tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> %mask)
76112 tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> %mask)
77113 ret void
78114 }
164200 define <4 x float> @load.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) sanitize_address {
165201 ; ALL-LABEL: @load.v4f32.variable
166202 %p = load <4 x float>*, <4 x float>** @v4f32, align 8
167 ; ALL-NOT: call void @__asan_load
203 ; LOAD: [[MASK0:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 0
204 ; LOAD: br i1 [[MASK0]], label %[[THEN0:[0-9A-Za-z]+]], label %[[AFTER0:[0-9A-Za-z]+]]
205 ; LOAD:
206 ; LOAD: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
207 ; LOAD: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
208 ; LOAD: call void @__asan_load4(i64 [[PGEP0]])
209 ; LOAD: br label %[[AFTER0]]
210 ; LOAD:
211
212 ; LOAD: [[MASK1:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 1
213 ; LOAD: br i1 [[MASK1]], label %[[THEN1:[0-9A-Za-z]+]], label %[[AFTER1:[0-9A-Za-z]+]]
214 ; LOAD:
215 ; LOAD: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
216 ; LOAD: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
217 ; LOAD: call void @__asan_load4(i64 [[PGEP1]])
218 ; LOAD: br label %[[AFTER1]]
219 ; LOAD:
220
221 ; LOAD: [[MASK2:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 2
222 ; LOAD: br i1 [[MASK2]], label %[[THEN2:[0-9A-Za-z]+]], label %[[AFTER2:[0-9A-Za-z]+]]
223 ; LOAD:
224 ; LOAD: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
225 ; LOAD: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
226 ; LOAD: call void @__asan_load4(i64 [[PGEP2]])
227 ; LOAD: br label %[[AFTER2]]
228 ; LOAD:
229
230 ; LOAD: [[MASK3:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 3
231 ; LOAD: br i1 [[MASK3]], label %[[THEN3:[0-9A-Za-z]+]], label %[[AFTER3:[0-9A-Za-z]+]]
232 ; LOAD:
233 ; LOAD: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
234 ; LOAD: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
235 ; LOAD: call void @__asan_load4(i64 [[PGEP3]])
236 ; LOAD: br label %[[AFTER3]]
237 ; LOAD:
238
239 ; LOAD: tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
168240 %res = tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
169241 ret <4 x float> %res
170242 }