llvm.org GIT mirror llvm / 19cd7e9
ASan: wrap mapping scale and offset in a struct and make it a member of ASan passes. Add test for non-default mapping scale and offset. No functionality change git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172610 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 6 years ago
2 changed file(s) with 121 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
5252 static const uint64_t kDefaultShadowScale = 3;
5353 static const uint64_t kDefaultShadowOffset32 = 1ULL << 29;
5454 static const uint64_t kDefaultShadowOffset64 = 1ULL << 44;
55 static const uint64_t kDefaultShadowOffsetAndroid = 0;
55 static const uint64_t kDefaultShadowOffsetPie = 0;
5656
5757 static const size_t kMaxStackMallocSize = 1 << 16; // 64K
5858 static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3;
185185 SmallSet DynInitGlobals;
186186 };
187187
188 static int MappingScale() {
189 return ClMappingScale ? ClMappingScale : kDefaultShadowScale;
190 }
191
192 static size_t RedzoneSize() {
188 /// This struct defines the shadow mapping using the rule:
189 /// shadow = (mem >> Scale) + Offset.
190 struct ShadowMapping {
191 int Scale;
192 uint64_t Offset;
193 };
194
195 static ShadowMapping getShadowMapping(const Module &M, int LongSize) {
196 llvm::Triple targetTriple(M.getTargetTriple());
197 bool isAndroid = targetTriple.getEnvironment() == llvm::Triple::Android;
198
199 ShadowMapping Mapping;
200
201 Mapping.Offset = isAndroid ? kDefaultShadowOffsetPie :
202 (LongSize == 32 ? kDefaultShadowOffset32 : kDefaultShadowOffset64);
203 if (ClMappingOffsetLog >= 0) {
204 // Zero offset log is the special case.
205 Mapping.Offset = (ClMappingOffsetLog == 0) ? 0 : 1ULL << ClMappingOffsetLog;
206 }
207
208 Mapping.Scale = kDefaultShadowScale;
209 if (ClMappingScale) {
210 Mapping.Scale = ClMappingScale;
211 }
212
213 return Mapping;
214 }
215
216 static size_t RedzoneSizeForScale(int MappingScale) {
193217 // Redzone used for stack and globals is at least 32 bytes.
194218 // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively.
195 return std::max(32U, 1U << MappingScale());
219 return std::max(32U, 1U << MappingScale);
196220 }
197221
198222 /// AddressSanitizer: instrument the code in module to find memory bugs.
226250 void createInitializerPoisonCalls(Module &M,
227251 Value *FirstAddr, Value *LastAddr);
228252 bool maybeInsertAsanInitAtFunctionEntry(Function &F);
253 void emitShadowMapping(Module &M, IRBuilder<> &IRB) const;
229254 virtual bool doInitialization(Module &M);
230255 static char ID; // Pass identification, replacement for typeid
231256
241266 bool CheckLifetime;
242267 LLVMContext *C;
243268 DataLayout *TD;
244 uint64_t MappingOffset;
245269 int LongSize;
246270 Type *IntptrTy;
271 ShadowMapping Mapping;
247272 Function *AsanCtorFunction;
248273 Function *AsanInitFunction;
249274 Function *AsanHandleNoReturnFunc;
277302 bool ShouldInstrumentGlobal(GlobalVariable *G);
278303 void createInitializerPoisonCalls(Module &M, Value *FirstAddr,
279304 Value *LastAddr);
305 size_t RedzoneSize() const {
306 return RedzoneSizeForScale(Mapping.Scale);
307 }
280308
281309 bool CheckInitOrder;
282310 SmallString<64> BlacklistFile;
285313 Type *IntptrTy;
286314 LLVMContext *C;
287315 DataLayout *TD;
316 ShadowMapping Mapping;
288317 Function *AsanPoisonGlobals;
289318 Function *AsanUnpoisonGlobals;
290319 Function *AsanRegisterGlobals;
307336 LLVMContext *C;
308337 Type *IntptrTy;
309338 Type *IntptrPtrTy;
339 ShadowMapping Mapping;
310340
311341 SmallVector AllocaVec;
312342 SmallVector RetVec;
331361 FunctionStackPoisoner(Function &F, AddressSanitizer &ASan)
332362 : F(F), ASan(ASan), DIB(*F.getParent()), C(ASan.C),
333363 IntptrTy(ASan.IntptrTy), IntptrPtrTy(PointerType::get(IntptrTy, 0)),
334 TotalStackSize(0), StackAlignment(1 << MappingScale()) {}
364 Mapping(ASan.Mapping),
365 TotalStackSize(0), StackAlignment(1 << Mapping.Scale) {}
335366
336367 bool runOnFunction() {
337368 if (!ClStack) return false;
410441 AI.getAllocatedType()->isSized());
411442 }
412443
444 size_t RedzoneSize() const {
445 return RedzoneSizeForScale(Mapping.Scale);
446 }
413447 uint64_t getAllocaSizeInBytes(AllocaInst *AI) {
414448 Type *Ty = AI->getAllocatedType();
415449 uint64_t SizeInBytes = ASan.TD->getTypeAllocSize(Ty);
472506
473507 Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
474508 // Shadow >> scale
475 Shadow = IRB.CreateLShr(Shadow, MappingScale());
476 if (MappingOffset == 0)
509 Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
510 if (Mapping.Offset == 0)
477511 return Shadow;
478512 // (Shadow >> scale) | offset
479513 return IRB.CreateOr(Shadow, ConstantInt::get(IntptrTy,
480 MappingOffset));
514 Mapping.Offset));
481515 }
482516
483517 void AddressSanitizer::instrumentMemIntrinsicParam(
613647 Value *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong,
614648 Value *ShadowValue,
615649 uint32_t TypeSize) {
616 size_t Granularity = 1 << MappingScale();
650 size_t Granularity = 1 << Mapping.Scale;
617651 // Addr & (Granularity - 1)
618652 Value *LastAccessedByte = IRB.CreateAnd(
619653 AddrLong, ConstantInt::get(IntptrTy, Granularity - 1));
634668 Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
635669
636670 Type *ShadowTy = IntegerType::get(
637 *C, std::max(8U, TypeSize >> MappingScale()));
671 *C, std::max(8U, TypeSize >> Mapping.Scale));
638672 Type *ShadowPtrTy = PointerType::get(ShadowTy, 0);
639673 Value *ShadowPtr = memToShadow(AddrLong, IRB);
640674 Value *CmpVal = Constant::getNullValue(ShadowTy);
643677
644678 Value *Cmp = IRB.CreateICmpNE(ShadowValue, CmpVal);
645679 size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
646 size_t Granularity = 1 << MappingScale();
680 size_t Granularity = 1 << Mapping.Scale;
647681 TerminatorInst *CrashTerm = 0;
648682
649683 if (ClAlwaysSlowPath || (TypeSize < 8 * Granularity)) {
781815 BL.reset(new BlackList(BlacklistFile));
782816 if (BL->isIn(M)) return false;
783817 C = &(M.getContext());
784 IntptrTy = Type::getIntNTy(*C, TD->getPointerSizeInBits());
818 int LongSize = TD->getPointerSizeInBits();
819 IntptrTy = Type::getIntNTy(*C, LongSize);
820 Mapping = getShadowMapping(M, LongSize);
785821 initializeCallbacks(M);
786822 DynamicallyInitializedGlobals.Init(M);
787823
929965 /*hasSideEffects=*/true);
930966 }
931967
968 void AddressSanitizer::emitShadowMapping(Module &M, IRBuilder<> &IRB) const {
969 // Tell the values of mapping offset and scale to the run-time if they are
970 // specified by command-line flags.
971 if (ClMappingOffsetLog >= 0) {
972 GlobalValue *asan_mapping_offset =
973 new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage,
974 ConstantInt::get(IntptrTy, Mapping.Offset),
975 kAsanMappingOffsetName);
976 // Read the global, otherwise it may be optimized away.
977 IRB.CreateLoad(asan_mapping_offset, true);
978 }
979
980 if (ClMappingScale) {
981 GlobalValue *asan_mapping_scale =
982 new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage,
983 ConstantInt::get(IntptrTy, Mapping.Scale),
984 kAsanMappingScaleName);
985 // Read the global, otherwise it may be optimized away.
986 IRB.CreateLoad(asan_mapping_scale, true);
987 }
988 }
989
932990 // virtual
933991 bool AddressSanitizer::doInitialization(Module &M) {
934992 // Initialize the private fields. No one has accessed them before.
9541012 AsanInitFunction->setLinkage(Function::ExternalLinkage);
9551013 IRB.CreateCall(AsanInitFunction);
9561014
957 llvm::Triple targetTriple(M.getTargetTriple());
958 bool isAndroid = targetTriple.getEnvironment() == llvm::Triple::Android;
959
960 MappingOffset = isAndroid ? kDefaultShadowOffsetAndroid :
961 (LongSize == 32 ? kDefaultShadowOffset32 : kDefaultShadowOffset64);
962 if (ClMappingOffsetLog >= 0) {
963 if (ClMappingOffsetLog == 0) {
964 // special case
965 MappingOffset = 0;
966 } else {
967 MappingOffset = 1ULL << ClMappingOffsetLog;
968 }
969 }
970
971
972 if (ClMappingOffsetLog >= 0) {
973 // Tell the run-time the current values of mapping offset and scale.
974 GlobalValue *asan_mapping_offset =
975 new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage,
976 ConstantInt::get(IntptrTy, MappingOffset),
977 kAsanMappingOffsetName);
978 // Read the global, otherwise it may be optimized away.
979 IRB.CreateLoad(asan_mapping_offset, true);
980 }
981 if (ClMappingScale) {
982 GlobalValue *asan_mapping_scale =
983 new GlobalVariable(M, IntptrTy, true, GlobalValue::LinkOnceODRLinkage,
984 ConstantInt::get(IntptrTy, MappingScale()),
985 kAsanMappingScaleName);
986 // Read the global, otherwise it may be optimized away.
987 IRB.CreateLoad(asan_mapping_scale, true);
988 }
1015 Mapping = getShadowMapping(M, LongSize);
1016 emitShadowMapping(M, IRB);
9891017
9901018 appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndCtorPriority);
991
9921019 return true;
9931020 }
9941021
11461173 void FunctionStackPoisoner::poisonRedZones(
11471174 const ArrayRef &AllocaVec, IRBuilder<> IRB, Value *ShadowBase,
11481175 bool DoPoison) {
1149 size_t ShadowRZSize = RedzoneSize() >> MappingScale();
1176 size_t ShadowRZSize = RedzoneSize() >> Mapping.Scale;
11501177 assert(ShadowRZSize >= 1 && ShadowRZSize <= 4);
11511178 Type *RZTy = Type::getIntNTy(*C, ShadowRZSize * 8);
11521179 Type *RZPtrTy = PointerType::get(RZTy, 0);
11771204 // Poison the partial redzone at right
11781205 Ptr = IRB.CreateAdd(
11791206 ShadowBase, ConstantInt::get(IntptrTy,
1180 (Pos >> MappingScale()) - ShadowRZSize));
1207 (Pos >> Mapping.Scale) - ShadowRZSize));
11811208 size_t AddressableBytes = RedzoneSize() - (AlignedSize - SizeInBytes);
11821209 uint32_t Poison = 0;
11831210 if (DoPoison) {
11841211 PoisonShadowPartialRightRedzone((uint8_t*)&Poison, AddressableBytes,
11851212 RedzoneSize(),
1186 1ULL << MappingScale(),
1213 1ULL << Mapping.Scale,
11871214 kAsanStackPartialRedzoneMagic);
11881215 }
11891216 Value *PartialPoison = ConstantInt::get(RZTy, Poison);
11921219
11931220 // Poison the full redzone at right.
11941221 Ptr = IRB.CreateAdd(ShadowBase,
1195 ConstantInt::get(IntptrTy, Pos >> MappingScale()));
1222 ConstantInt::get(IntptrTy, Pos >> Mapping.Scale));
11961223 bool LastAlloca = (i == AllocaVec.size() - 1);
11971224 Value *Poison = LastAlloca ? PoisonRight : PoisonMid;
11981225 IRB.CreateStore(Poison, IRB.CreateIntToPtr(Ptr, RZPtrTy));
0 ; Test non-default shadow mapping scale and offset.
1 ;
2 ; RUN: opt < %s -asan -asan-mapping-scale=2 -asan-mapping-offset-log=0 -S | FileCheck %s
3
4 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"
5 target triple = "x86_64-unknown-linux-gnu"
6
7 ; Test that ASan tells scale and offset to runtime.
8 ; CHECK: @__asan_mapping_offset = linkonce_odr constant i64 0
9 ; CHECK: @__asan_mapping_scale = linkonce_odr constant i64 2
10
11 define i32 @test_load(i32* %a) address_safety {
12 ; CHECK: @test_load
13 ; CHECK-NOT: load
14 ; CHECK: %[[LOAD_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
15 ; CHECK: lshr i64 %[[LOAD_ADDR]], 2
16
17 ; No need in shift for zero offset.
18 ; CHECK-NOT: or i64
19
20 ; CHECK: %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
21 ; CHECK: %[[LOAD_SHADOW:[^ ]*]] = load i8* %[[LOAD_SHADOW_PTR]]
22 ; CHECK: icmp ne i8
23 ; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
24
25 ; No need in slow path for i32 and mapping scale equal to 2.
26 ; CHECK-NOT: and i64 %[[LOAD_ADDR]]
27 ;
28 ; The crash block reports the error.
29 ; CHECK: call void @__asan_report_load4(i64 %[[LOAD_ADDR]])
30 ; CHECK: unreachable
31 ;
32 ; The actual load.
33 ; CHECK: %tmp1 = load i32* %a
34 ; CHECK: ret i32 %tmp1
35
36 entry:
37 %tmp1 = load i32* %a
38 ret i32 %tmp1
39 }
40