diff --git a/compiler-rt/test/hwasan/lit.cfg b/compiler-rt/test/hwasan/lit.cfg --- a/compiler-rt/test/hwasan/lit.cfg +++ b/compiler-rt/test/hwasan/lit.cfg @@ -11,7 +11,7 @@ # Setup default compiler flags used with -fsanitize=memory option. clang_cflags = [config.target_cflags] + config.debug_info_flags clang_cxxflags = config.cxx_mode_flags + clang_cflags -clang_hwasan_cflags = ["-fsanitize=hwaddress", "-mllvm", "-hwasan-generate-tags-with-calls"] + clang_cflags +clang_hwasan_cflags = ["-fsanitize=hwaddress"] + clang_cflags clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags def build_invocation(compile_flags): diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -218,7 +218,7 @@ Value *getUARTag(IRBuilder<> &IRB, Value *StackTag); Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty); - Value *emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord); + void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord); private: LLVMContext *C; @@ -284,6 +284,7 @@ Constant *ShadowGlobal; Value *LocalDynamicShadow = nullptr; + Value *StackBaseTag = nullptr; GlobalValue *ThreadPtrGlobal = nullptr; }; @@ -764,6 +765,8 @@ Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) { if (ClGenerateTagsWithCalls) return getNextTagWithCall(IRB); + if (StackBaseTag) + return StackBaseTag; // FIXME: use addressofreturnaddress (but implement it in aarch64 backend // first). Module *M = IRB.GetInsertBlock()->getParent()->getParent(); @@ -881,13 +884,16 @@ GV->setComdat(Comdat); } -Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, - bool WithFrameRecord) { - if (!Mapping.InTls) - return getDynamicShadowNonTls(IRB); +void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) { + if (!Mapping.InTls) { + LocalDynamicShadow = getDynamicShadowNonTls(IRB); + return; + } - if (!WithFrameRecord && TargetTriple.isAndroid()) - return getDynamicShadowIfunc(IRB); + if (!WithFrameRecord && TargetTriple.isAndroid()) { + LocalDynamicShadow = getDynamicShadowIfunc(IRB); + return; + } Value *SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy); assert(SlotPtr); @@ -920,6 +926,8 @@ TargetTriple.isAArch64() ? ThreadLong : untagPointer(IRB, ThreadLong); if (WithFrameRecord) { + StackBaseTag = ThreadLong; + // Prepare ring buffer data. auto PC = IRB.CreatePtrToInt(F, IntptrTy); auto GetStackPointerFn = @@ -928,7 +936,7 @@ IRB.CreateCall(GetStackPointerFn, {Constant::getNullValue(IRB.getInt32Ty())}), IntptrTy); - // Mix SP and PC. TODO: also add the tag to the mix. + // Mix SP and PC. // Assumptions: // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero) // SP is 0xsssssssssssSSSS0 (4 lower bits are zero) @@ -959,13 +967,12 @@ // Get shadow base address by aligning RecordPtr up. // Note: this is not correct if the pointer is already aligned. // Runtime library will make sure this never happens. - Value *ShadowBase = IRB.CreateAdd( + LocalDynamicShadow = IRB.CreateAdd( IRB.CreateOr( ThreadLongMaybeUntagged, ConstantInt::get(IntptrTy, (1ULL << kShadowBaseAlignment) - 1)), ConstantInt::get(IntptrTy, 1), "hwasan.shadow"); - ShadowBase = IRB.CreateIntToPtr(ShadowBase, Int8PtrTy); - return ShadowBase; + LocalDynamicShadow = IRB.CreateIntToPtr(LocalDynamicShadow, Int8PtrTy); } bool HWAddressSanitizer::instrumentLandingPads( @@ -994,16 +1001,22 @@ // (unless we use ASan-style mega-alloca). Instead we keep the base tag in a // temp, shift-OR it into each alloca address and xor with the retag mask. // This generates one extra instruction per alloca use. - for (unsigned N = 0; N < Allocas.size(); ++N) { - auto *AI = Allocas[N]; + uint8_t TagOffset = 0; + for (AllocaInst *AI : Allocas) { + // The base tag will be a multiple of 8, so we should avoid using tags with + // lower bits clear so that we don't end up with a final tag of 0. + ++TagOffset; + if ((TagOffset & 7) == 0) + ++TagOffset; + IRBuilder<> IRB(AI->getNextNode()); // Replace uses of the alloca with tagged address. - Value *Tag = getAllocaTag(IRB, StackTag, AI, N); + Value *Tag = getAllocaTag(IRB, StackTag, AI, TagOffset); Value *AILong = IRB.CreatePointerCast(AI, IntptrTy); Value *Replacement = tagPointer(IRB, AI->getType(), AILong, Tag); std::string Name = - AI->hasName() ? AI->getName().str() : "alloca." + itostr(N); + AI->hasName() ? AI->getName().str() : "alloca." + itostr(TagOffset); Replacement->setName(Name + ".hwasan"); for (auto UI = AI->use_begin(), UE = AI->use_end(); UI != UE;) { @@ -1014,8 +1027,8 @@ for (auto *DDI : AllocaDeclareMap.lookup(AI)) { DIExpression *OldExpr = DDI->getExpression(); - DIExpression *NewExpr = - DIExpression::append(OldExpr, {dwarf::DW_OP_LLVM_tag_offset, N}); + DIExpression *NewExpr = DIExpression::append( + OldExpr, {dwarf::DW_OP_LLVM_tag_offset, TagOffset}); DDI->setArgOperand(2, MetadataAsValue::get(*C, NewExpr)); } @@ -1115,9 +1128,9 @@ Instruction *InsertPt = &*F.getEntryBlock().begin(); IRBuilder<> EntryIRB(InsertPt); - LocalDynamicShadow = emitPrologue(EntryIRB, - /*WithFrameRecord*/ ClRecordStackHistory && - !AllocasToInstrument.empty()); + emitPrologue(EntryIRB, + /*WithFrameRecord*/ ClRecordStackHistory && + !AllocasToInstrument.empty()); bool Changed = false; if (!AllocasToInstrument.empty()) { @@ -1146,6 +1159,7 @@ Changed |= instrumentMemAccess(Inst); LocalDynamicShadow = nullptr; + StackBaseTag = nullptr; return Changed; } diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/alloca.ll @@ -17,7 +17,7 @@ ; CHECK: %[[BASE_TAG:[^ ]*]] = xor i64 %[[A]], %[[B]] ; CHECK: %[[X:[^ ]*]] = alloca i32, align 16 -; CHECK: %[[X_TAG:[^ ]*]] = xor i64 %[[BASE_TAG]], 0 +; CHECK: %[[X_TAG:[^ ]*]] = xor i64 %[[BASE_TAG]], 1 ; CHECK: %[[X1:[^ ]*]] = ptrtoint i32* %[[X]] to i64 ; CHECK: %[[C:[^ ]*]] = shl i64 %[[X_TAG]], 56 ; CHECK: %[[D:[^ ]*]] = or i64 %[[X1]], %[[C]] diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll b/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll @@ -9,13 +9,13 @@ entry: %a = alloca i8* %b = alloca i8* - ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 0) - call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14 - ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 0) + ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 1) call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14 ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 1) + call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14 + ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 2) call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14 - ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 1) + ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 2) call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14 call void @g(i8** %a, i8** %b) ret void, !dbg !15 diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/kernel-alloca.ll b/llvm/test/Instrumentation/HWAddressSanitizer/kernel-alloca.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/kernel-alloca.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/kernel-alloca.ll @@ -15,7 +15,7 @@ ; CHECK: %[[BASE_TAG:[^ ]*]] = xor i64 %[[A]], %[[B]] ; CHECK: %[[X:[^ ]*]] = alloca i32, align 16 -; CHECK: %[[X_TAG:[^ ]*]] = xor i64 %[[BASE_TAG]], 0 +; CHECK: %[[X_TAG:[^ ]*]] = xor i64 %[[BASE_TAG]], 1 ; CHECK: %[[X1:[^ ]*]] = ptrtoint i32* %[[X]] to i64 ; CHECK: %[[C:[^ ]*]] = shl i64 %[[X_TAG]], 56 ; CHECK: %[[D:[^ ]*]] = or i64 %[[C]], 72057594037927935 diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll b/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll @@ -71,6 +71,8 @@ ; CHECK-TLS: %[[E:[^ ]*]] = or i64 %[[D]], 4294967295 ; CHECK-TLS: = add i64 %[[E]], 1 +; CHECK-HISTORY: = xor i64 %[[D]], 1 + ; CHECK-NOHISTORY-NOT: store i64