llvm.org GIT mirror llvm / 644422a
hwasan: Use bits [3..11) of the ring buffer entry address as the base stack tag. This saves roughly 32 bytes of instructions per function with stack objects and causes us to preserve enough information that we can recover the original tags of all stack variables. Now that stack tags are deterministic, we no longer need to pass -hwasan-generate-tags-with-calls during check-hwasan. This also means that the new stack tag generation mechanism is exercised by check-hwasan. Differential Revision: https://reviews.llvm.org/D63360 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363636 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 4 months ago
3 changed file(s) with 42 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
217217 Value *getUARTag(IRBuilder<> &IRB, Value *StackTag);
218218
219219 Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty);
220 Value *emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
220 void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
221221
222222 private:
223223 LLVMContext *C;
283283 Constant *ShadowGlobal;
284284
285285 Value *LocalDynamicShadow = nullptr;
286 Value *StackBaseTag = nullptr;
286287 GlobalValue *ThreadPtrGlobal = nullptr;
287288 };
288289
749750 // x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
750751 // masks.
751752 // The list does not include the value 255, which is used for UAR.
752 static unsigned FastMasks[] = {
753 0, 1, 2, 3, 4, 6, 7, 8, 12, 14, 15, 16, 24,
754 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112, 120,
755 124, 126, 127, 128, 192, 224, 240, 248, 252, 254};
753 //
754 // Because we are more likely to use earlier elements of this list than later
755 // ones, it is sorted in increasing order of probability of collision with a
756 // mask allocated (temporally) nearby. The program that generated this list
757 // can be found at:
758 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/sort_masks.py
759 static unsigned FastMasks[] = {0, 128, 64, 192, 32, 96, 224, 112, 240,
760 48, 16, 120, 248, 56, 24, 8, 124, 252,
761 60, 28, 12, 4, 126, 254, 62, 30, 14,
762 6, 2, 127, 63, 31, 15, 7, 3, 1};
756763 return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))];
757764 }
758765
763770 Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
764771 if (ClGenerateTagsWithCalls)
765772 return getNextTagWithCall(IRB);
773 if (StackBaseTag)
774 return StackBaseTag;
766775 // FIXME: use addressofreturnaddress (but implement it in aarch64 backend
767776 // first).
768777 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
880889 GV->setComdat(Comdat);
881890 }
882891
883 Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB,
884 bool WithFrameRecord) {
885 if (!Mapping.InTls)
886 return getDynamicShadowNonTls(IRB);
887
888 if (!WithFrameRecord && TargetTriple.isAndroid())
889 return getDynamicShadowIfunc(IRB);
892 void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {
893 if (!Mapping.InTls) {
894 LocalDynamicShadow = getDynamicShadowNonTls(IRB);
895 return;
896 }
897
898 if (!WithFrameRecord && TargetTriple.isAndroid()) {
899 LocalDynamicShadow = getDynamicShadowIfunc(IRB);
900 return;
901 }
890902
891903 Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy);
892904 assert(SlotPtr);
919931 TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong);
920932
921933 if (WithFrameRecord) {
934 StackBaseTag = IRB.CreateAShr(ThreadLong, 3);
935
922936 // Prepare ring buffer data.
923937 auto PC = IRB.CreatePtrToInt(F, IntptrTy);
924938 auto GetStackPointerFn =
927941 IRB.CreateCall(GetStackPointerFn,
928942 {Constant::getNullValue(IRB.getInt32Ty())}),
929943 IntptrTy);
930 // Mix SP and PC. TODO: also add the tag to the mix.
944 // Mix SP and PC.
931945 // Assumptions:
932946 // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero)
933947 // SP is 0xsssssssssssSSSS0 (4 lower bits are zero)
958972 // Get shadow base address by aligning RecordPtr up.
959973 // Note: this is not correct if the pointer is already aligned.
960974 // Runtime library will make sure this never happens.
961 Value *ShadowBase = IRB.CreateAdd(
975 LocalDynamicShadow = IRB.CreateAdd(
962976 IRB.CreateOr(
963977 ThreadLongMaybeUntagged,
964978 ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)),
965979 ConstantInt::get(IntptrTy, 1), "hwasan.shadow");
966 ShadowBase = IRB.CreateIntToPtr(ShadowBase, Int8PtrTy);
967 return ShadowBase;
980 LocalDynamicShadow = IRB.CreateIntToPtr(LocalDynamicShadow, Int8PtrTy);
968981 }
969982
970983 bool HWAddressSanitizer::instrumentLandingPads(
11141127
11151128 Instruction *InsertPt = &*F.getEntryBlock().begin();
11161129 IRBuilder<> EntryIRB(InsertPt);
1117 LocalDynamicShadow = emitPrologue(EntryIRB,
1118 /*WithFrameRecord*/ ClRecordStackHistory &&
1119 !AllocasToInstrument.empty());
1130 emitPrologue(EntryIRB,
1131 /*WithFrameRecord*/ ClRecordStackHistory &&
1132 !AllocasToInstrument.empty());
11201133
11211134 bool Changed = false;
11221135 if (!AllocasToInstrument.empty()) {
11451158 Changed |= instrumentMemAccess(Inst);
11461159
11471160 LocalDynamicShadow = nullptr;
1161 StackBaseTag = nullptr;
11481162
11491163 return Changed;
11501164 }
1212 %nodebug3 = alloca i8*
1313 %a = alloca i8*
1414 %b = alloca i8*
15 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 4)
15 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 32)
1616 call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14
17 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 4)
17 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 32)
1818 call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14
19 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 6)
19 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 96)
2020 call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14
21 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 6)
21 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 96)
2222 call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14
2323 call void @g(i8** %nodebug0, i8** %nodebug1, i8** %nodebug2, i8** %nodebug3, i8** %a, i8** %b)
2424 ret void, !dbg !15
5555 ; CHECK-TLS: %[[B:[^ ]*]] = getelementptr i8, i8* %[[A]], i32 48
5656 ; CHECK-TLS: %[[C:[^ ]*]] = bitcast i8* %[[B]] to i64*
5757 ; CHECK-TLS: %[[D:[^ ]*]] = load i64, i64* %[[C]]
58 ; CHECK-TLS: %[[E:[^ ]*]] = ashr i64 %[[D]], 3
5859
5960 ; CHECK-NOHISTORY-NOT: store i64
6061
6768 ; CHECK-HISTORY: %[[D5:[^ ]*]] = and i64 %[[D4]], %[[D3]]
6869 ; CHECK-HISTORY: store i64 %[[D5]], i64* %[[C]]
6970
70 ; CHECK-TLS: %[[E:[^ ]*]] = or i64 %[[D]], 4294967295
71 ; CHECK-TLS: = add i64 %[[E]], 1
71 ; CHECK-TLS: %[[F:[^ ]*]] = or i64 %[[D]], 4294967295
72 ; CHECK-TLS: = add i64 %[[F]], 1
73
74 ; CHECK-HISTORY: = xor i64 %[[E]], 0
7275
7376 ; CHECK-NOHISTORY-NOT: store i64
7477