diff --git a/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S b/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S --- a/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S +++ b/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S @@ -54,11 +54,57 @@ // * x0: The address of read/write instruction that caused HWASan check fail. // * x1: The tag size. +// This function has two entry points. The first, __hwasan_tag_mismatch, is used +// by clients that were compiled without short tag checks (i.e. binaries built +// by older compilers and binaries targeting older runtimes). In this case the +// outlined tag check will be missing the code handling short tags (which won't +// be used in the binary's own stack variables but may be used on the heap +// or stack variables in other binaries), so the check needs to be done here. +// +// The second, __hwasan_tag_mismatch_v2, is used by binaries targeting newer +// runtimes. This entry point bypasses the short tag check since it will have +// already been done as part of the outlined tag check. Since tag mismatches are +// uncommon, there isn't a significant performance benefit to being able to +// bypass the check; the main benefits are that we can sometimes avoid +// clobbering the x17 register in error reports, and that the program will have +// a runtime dependency on the __hwasan_tag_mismatch_v2 symbol therefore it will +// fail to start up given an older (i.e. incompatible) runtime. .section .text .file "hwasan_tag_mismatch_aarch64.S" .global __hwasan_tag_mismatch .type __hwasan_tag_mismatch, %function __hwasan_tag_mismatch: + // Compute the granule position one past the end of the access. + mov x16, #1 + and x17, x1, #0xf + lsl x16, x16, x17 + and x17, x0, #0xf + add x17, x16, x17 + + // Load the shadow byte again and check whether it is a short tag within the + // range of the granule position computed above. + ubfx x16, x0, #4, #52 + ldrb w16, [x9, x16] + cmp w16, #0xf + b.hi __hwasan_tag_mismatch_v2 + cmp w16, w17 + b.lo __hwasan_tag_mismatch_v2 + + // Load the real tag from the last byte of the granule and compare against + // the pointer tag. + orr x16, x0, #0xf + ldrb w16, [x16] + cmp x16, x0, lsr #56 + b.ne __hwasan_tag_mismatch_v2 + + // Restore x0, x1 and sp to their values from before the __hwasan_tag_mismatch + // call and resume execution. + ldp x0, x1, [sp], #256 + ret + +.global __hwasan_tag_mismatch_v2 +.type __hwasan_tag_mismatch_v2, %function +__hwasan_tag_mismatch_v2: CFI_STARTPROC // Set the CFA to be the return address for caller of __hwasan_check_*. Note diff --git a/compiler-rt/test/hwasan/TestCases/stack-oob.c b/compiler-rt/test/hwasan/TestCases/stack-oob.c --- a/compiler-rt/test/hwasan/TestCases/stack-oob.c +++ b/compiler-rt/test/hwasan/TestCases/stack-oob.c @@ -1,4 +1,6 @@ +// RUN: %clang_hwasan_oldrt -DSIZE=15 -O0 %s -o %t && %run %t // RUN: %clang_hwasan -DSIZE=15 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clang_hwasan_oldrt -DSIZE=16 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clang_hwasan -DSIZE=16 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clang_hwasan -DSIZE=64 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clang_hwasan -DSIZE=0x1000 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s @@ -18,7 +20,7 @@ int main() { return f(); // CHECK: READ of size 1 at - // CHECK: #0 {{.*}} in f{{.*}}stack-oob.c:15 + // CHECK: #0 {{.*}} in f{{.*}}stack-oob.c:17 // CHECK: is located in stack of threa diff --git a/compiler-rt/test/hwasan/lit.cfg.py b/compiler-rt/test/hwasan/lit.cfg.py --- a/compiler-rt/test/hwasan/lit.cfg.py +++ b/compiler-rt/test/hwasan/lit.cfg.py @@ -18,9 +18,11 @@ # equivalent target feature implemented on x86_64. clang_hwasan_common_cflags += ["-mcmodel=large"] clang_hwasan_cflags = clang_hwasan_common_cflags + ["-mllvm", "-hwasan-globals", + "-mllvm", "-hwasan-use-short-granules", "-mllvm", "-hwasan-instrument-landing-pads=0", "-mllvm", "-hwasan-instrument-personality-functions"] -clang_hwasan_oldrt_cflags = clang_hwasan_common_cflags + ["-mllvm", "-hwasan-instrument-landing-pads=1", +clang_hwasan_oldrt_cflags = clang_hwasan_common_cflags + ["-mllvm", "-hwasan-use-short-granules=0", + "-mllvm", "-hwasan-instrument-landing-pads=1", "-mllvm", "-hwasan-instrument-personality-functions=0"] clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags @@ -31,6 +33,7 @@ config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) ) config.substitutions.append( ("%clang_hwasan ", build_invocation(clang_hwasan_cflags)) ) +config.substitutions.append( ("%clang_hwasan_oldrt ", build_invocation(clang_hwasan_oldrt_cflags)) ) config.substitutions.append( ("%clangxx_hwasan ", build_invocation(clang_hwasan_cxxflags)) ) config.substitutions.append( ("%clangxx_hwasan_oldrt ", build_invocation(clang_hwasan_oldrt_cxxflags)) ) config.substitutions.append( ("%compiler_rt_libdir", config.compiler_rt_libdir) ) diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -263,15 +263,22 @@ std::unique_ptr STI( TM.getTarget().createMCSubtargetInfo(TT.str(), "", "")); - MCSymbol *HwasanTagMismatchSym = + MCSymbol *HwasanTagMismatchV1Sym = OutContext.getOrCreateSymbol("__hwasan_tag_mismatch"); + MCSymbol *HwasanTagMismatchV2Sym = + OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2"); - const MCSymbolRefExpr *HwasanTagMismatchRef = - MCSymbolRefExpr::create(HwasanTagMismatchSym, OutContext); + const MCSymbolRefExpr *HwasanTagMismatchV1Ref = + MCSymbolRefExpr::create(HwasanTagMismatchV1Sym, OutContext); + const MCSymbolRefExpr *HwasanTagMismatchV2Ref = + MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext); for (auto &P : HwasanMemaccessSymbols) { unsigned Reg = P.first.first; - uint32_t AccessInfo = P.first.second; + uint32_t AccessInfo = P.first.second & 0x3f; + uint32_t Version = P.first.second >> 6; + const MCSymbolRefExpr *HwasanTagMismatchRef = + Version >= 1 ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref; MCSymbol *Sym = P.second; OutStreamer->SwitchSection(OutContext.getELFSection( @@ -304,82 +311,86 @@ .addReg(Reg) .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSR, 56)), *STI); - MCSymbol *HandlePartialSym = OutContext.createTempSymbol(); + MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol(); OutStreamer->EmitInstruction( MCInstBuilder(AArch64::Bcc) .addImm(AArch64CC::NE) - .addExpr(MCSymbolRefExpr::create(HandlePartialSym, OutContext)), + .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym, + OutContext)), *STI); MCSymbol *ReturnSym = OutContext.createTempSymbol(); OutStreamer->EmitLabel(ReturnSym); OutStreamer->EmitInstruction( MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI); + OutStreamer->EmitLabel(HandleMismatchOrPartialSym); - OutStreamer->EmitLabel(HandlePartialSym); - OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWri) - .addReg(AArch64::WZR) - .addReg(AArch64::W16) - .addImm(15) - .addImm(0), - *STI); - MCSymbol *HandleMismatchSym = OutContext.createTempSymbol(); - OutStreamer->EmitInstruction( - MCInstBuilder(AArch64::Bcc) - .addImm(AArch64CC::HI) - .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), - *STI); - - OutStreamer->EmitInstruction( - MCInstBuilder(AArch64::ANDXri) - .addReg(AArch64::X17) - .addReg(Reg) - .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)), - *STI); - unsigned Size = 1 << (AccessInfo & 0xf); - if (Size != 1) - OutStreamer->EmitInstruction(MCInstBuilder(AArch64::ADDXri) - .addReg(AArch64::X17) - .addReg(AArch64::X17) - .addImm(Size - 1) + if (Version >= 1) { + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWri) + .addReg(AArch64::WZR) + .addReg(AArch64::W16) + .addImm(15) .addImm(0), *STI); - OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWrs) - .addReg(AArch64::WZR) - .addReg(AArch64::W16) - .addReg(AArch64::W17) - .addImm(0), - *STI); - OutStreamer->EmitInstruction( - MCInstBuilder(AArch64::Bcc) - .addImm(AArch64CC::LS) - .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), - *STI); - - OutStreamer->EmitInstruction( - MCInstBuilder(AArch64::ORRXri) - .addReg(AArch64::X16) - .addReg(Reg) - .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)), - *STI); - OutStreamer->EmitInstruction(MCInstBuilder(AArch64::LDRBBui) - .addReg(AArch64::W16) - .addReg(AArch64::X16) - .addImm(0), - *STI); - OutStreamer->EmitInstruction( - MCInstBuilder(AArch64::SUBSXrs) - .addReg(AArch64::XZR) - .addReg(AArch64::X16) - .addReg(Reg) - .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSR, 56)), - *STI); - OutStreamer->EmitInstruction( - MCInstBuilder(AArch64::Bcc) - .addImm(AArch64CC::EQ) - .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)), - *STI); + MCSymbol *HandleMismatchSym = OutContext.createTempSymbol(); + OutStreamer->EmitInstruction( + MCInstBuilder(AArch64::Bcc) + .addImm(AArch64CC::HI) + .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), + *STI); + + OutStreamer->EmitInstruction( + MCInstBuilder(AArch64::ANDXri) + .addReg(AArch64::X17) + .addReg(Reg) + .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)), + *STI); + unsigned Size = 1 << (AccessInfo & 0xf); + if (Size != 1) + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::ADDXri) + .addReg(AArch64::X17) + .addReg(AArch64::X17) + .addImm(Size - 1) + .addImm(0), + *STI); + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::SUBSWrs) + .addReg(AArch64::WZR) + .addReg(AArch64::W16) + .addReg(AArch64::W17) + .addImm(0), + *STI); + OutStreamer->EmitInstruction( + MCInstBuilder(AArch64::Bcc) + .addImm(AArch64CC::LS) + .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), + *STI); + + OutStreamer->EmitInstruction( + MCInstBuilder(AArch64::ORRXri) + .addReg(AArch64::X16) + .addReg(Reg) + .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)), + *STI); + OutStreamer->EmitInstruction(MCInstBuilder(AArch64::LDRBBui) + .addReg(AArch64::W16) + .addReg(AArch64::X16) + .addImm(0), + *STI); + OutStreamer->EmitInstruction( + MCInstBuilder(AArch64::SUBSXrs) + .addReg(AArch64::XZR) + .addReg(AArch64::X16) + .addReg(Reg) + .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSR, 56)), + *STI); + OutStreamer->EmitInstruction( + MCInstBuilder(AArch64::Bcc) + .addImm(AArch64CC::EQ) + .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)), + *STI); + + OutStreamer->EmitLabel(HandleMismatchSym); + } - OutStreamer->EmitLabel(HandleMismatchSym); OutStreamer->EmitInstruction(MCInstBuilder(AArch64::STPXpre) .addReg(AArch64::SP) .addReg(AArch64::X0) @@ -414,7 +425,7 @@ MCInstBuilder(AArch64::ADRP) .addReg(AArch64::X16) .addExpr(AArch64MCExpr::create( - HwasanTagMismatchRef, + Version >= 1 ? HwasanTagMismatchV2Ref : HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE, OutContext)), *STI); OutStreamer->EmitInstruction( @@ -422,7 +433,7 @@ .addReg(AArch64::X16) .addReg(AArch64::X16) .addExpr(AArch64MCExpr::create( - HwasanTagMismatchRef, + Version >= 1 ? HwasanTagMismatchV2Ref : HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12, OutContext)), *STI); OutStreamer->EmitInstruction( 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 @@ -166,6 +166,11 @@ cl::desc("instrument landing pads"), cl::Hidden, cl::init(false), cl::ZeroOrMore); +static cl::opt ClUseShortGranules( + "hwasan-use-short-granules", + cl::desc("use short granules in allocas and outlined checks"), cl::Hidden, + cl::init(false), cl::ZeroOrMore); + static cl::opt ClInstrumentPersonalityFunctions( "hwasan-instrument-personality-functions", cl::desc("instrument personality functions"), cl::Hidden, cl::init(false), @@ -269,6 +274,7 @@ bool CompileKernel; bool Recover; + bool UseShortGranules; bool InstrumentLandingPads; Function *HwasanCtorFunction; @@ -372,11 +378,14 @@ HwasanCtorFunction = nullptr; // Older versions of Android do not have the required runtime support for - // global or personality function instrumentation. On other platforms we - // currently require using the latest version of the runtime. + // short granules, global or personality function instrumentation. On other + // platforms we currently require using the latest version of the runtime. bool NewRuntime = !TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30); + UseShortGranules = + ClUseShortGranules.getNumOccurrences() ? ClUseShortGranules : NewRuntime; + // If we don't have personality function support, fall back to landing pads. InstrumentLandingPads = ClInstrumentLandingPads.getNumOccurrences() ? ClInstrumentLandingPads @@ -610,7 +619,8 @@ Ptr = IRB.CreateBitCast(Ptr, Int8PtrTy); IRB.CreateCall( Intrinsic::getDeclaration(M, Intrinsic::hwasan_check_memaccess), - {shadowBase(), Ptr, ConstantInt::get(Int32Ty, AccessInfo)}); + {shadowBase(), Ptr, + ConstantInt::get(Int32Ty, AccessInfo + UseShortGranules * 0x40)}); return; } @@ -630,36 +640,40 @@ TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored); } - Instruction *CheckTerm = - SplitBlockAndInsertIfThen(TagMismatch, InsertBefore, false, - MDBuilder(*C).createBranchWeights(1, 100000)); - + Instruction *CheckTerm = SplitBlockAndInsertIfThen( + TagMismatch, InsertBefore, !UseShortGranules && !Recover, + MDBuilder(*C).createBranchWeights(1, 100000)); IRB.SetInsertPoint(CheckTerm); - Value *OutOfShortGranuleTagRange = - IRB.CreateICmpUGT(MemTag, ConstantInt::get(Int8Ty, 15)); - Instruction *CheckFailTerm = - SplitBlockAndInsertIfThen(OutOfShortGranuleTagRange, CheckTerm, !Recover, - MDBuilder(*C).createBranchWeights(1, 100000)); - IRB.SetInsertPoint(CheckTerm); - Value *PtrLowBits = IRB.CreateTrunc(IRB.CreateAnd(PtrLong, 15), Int8Ty); - PtrLowBits = IRB.CreateAdd( - PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1)); - Value *PtrLowBitsOOB = IRB.CreateICmpUGE(PtrLowBits, MemTag); - SplitBlockAndInsertIfThen(PtrLowBitsOOB, CheckTerm, false, - MDBuilder(*C).createBranchWeights(1, 100000), - nullptr, nullptr, CheckFailTerm->getParent()); + Instruction *CheckFailTerm; + if (UseShortGranules) { + Value *OutOfShortGranuleTagRange = + IRB.CreateICmpUGT(MemTag, ConstantInt::get(Int8Ty, 15)); + CheckFailTerm = SplitBlockAndInsertIfThen( + OutOfShortGranuleTagRange, CheckTerm, !Recover, + MDBuilder(*C).createBranchWeights(1, 100000)); + + IRB.SetInsertPoint(CheckTerm); + Value *PtrLowBits = IRB.CreateTrunc(IRB.CreateAnd(PtrLong, 15), Int8Ty); + PtrLowBits = IRB.CreateAdd( + PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1)); + Value *PtrLowBitsOOB = IRB.CreateICmpUGE(PtrLowBits, MemTag); + SplitBlockAndInsertIfThen(PtrLowBitsOOB, CheckTerm, false, + MDBuilder(*C).createBranchWeights(1, 100000), + nullptr, nullptr, CheckFailTerm->getParent()); + + IRB.SetInsertPoint(CheckTerm); + Value *InlineTagAddr = IRB.CreateOr(AddrLong, 15); + InlineTagAddr = IRB.CreateIntToPtr(InlineTagAddr, Int8PtrTy); + Value *InlineTag = IRB.CreateLoad(Int8Ty, InlineTagAddr); + Value *InlineTagMismatch = IRB.CreateICmpNE(PtrTag, InlineTag); + SplitBlockAndInsertIfThen(InlineTagMismatch, CheckTerm, false, + MDBuilder(*C).createBranchWeights(1, 100000), + nullptr, nullptr, CheckFailTerm->getParent()); + + IRB.SetInsertPoint(CheckFailTerm); + } - IRB.SetInsertPoint(CheckTerm); - Value *InlineTagAddr = IRB.CreateOr(AddrLong, 15); - InlineTagAddr = IRB.CreateIntToPtr(InlineTagAddr, Int8PtrTy); - Value *InlineTag = IRB.CreateLoad(Int8Ty, InlineTagAddr); - Value *InlineTagMismatch = IRB.CreateICmpNE(PtrTag, InlineTag); - SplitBlockAndInsertIfThen(InlineTagMismatch, CheckTerm, false, - MDBuilder(*C).createBranchWeights(1, 100000), - nullptr, nullptr, CheckFailTerm->getParent()); - - IRB.SetInsertPoint(CheckFailTerm); InlineAsm *Asm; switch (TargetTriple.getArch()) { case Triple::x86_64: @@ -683,7 +697,7 @@ report_fatal_error("unsupported architecture"); } IRB.CreateCall(Asm, PtrLong); - if (Recover) + if (UseShortGranules && Recover) cast(CheckFailTerm)->setSuccessor(0, CheckTerm->getParent()); } @@ -763,6 +777,8 @@ bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag, size_t Size) { size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment()); + if (!UseShortGranules) + Size = AlignedSize; Value *JustTag = IRB.CreateTrunc(Tag, IRB.getInt8Ty()); if (ClInstrumentWithCalls) { diff --git a/llvm/test/CodeGen/AArch64/hwasan-check-memaccess.ll b/llvm/test/CodeGen/AArch64/hwasan-check-memaccess.ll --- a/llvm/test/CodeGen/AArch64/hwasan-check-memaccess.ll +++ b/llvm/test/CodeGen/AArch64/hwasan-check-memaccess.ll @@ -8,11 +8,11 @@ ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: .cfi_offset w30, -16 ; CHECK-NEXT: mov x9, x0 - ; CHECK-NEXT: bl __hwasan_check_x1_123 + ; CHECK-NEXT: bl __hwasan_check_x1_1 ; CHECK-NEXT: mov x0, x1 ; CHECK-NEXT: ldr x30, [sp], #16 ; CHECK-NEXT: ret - call void @llvm.hwasan.check.memaccess(i8* %x0, i8* %x1, i32 123) + call void @llvm.hwasan.check.memaccess(i8* %x0, i8* %x1, i32 1) ret i8* %x1 } @@ -22,20 +22,20 @@ ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: .cfi_offset w30, -16 ; CHECK-NEXT: mov x9, x1 - ; CHECK-NEXT: bl __hwasan_check_x0_456 + ; CHECK-NEXT: bl __hwasan_check_x0_66 ; CHECK-NEXT: ldr x30, [sp], #16 ; CHECK-NEXT: ret - call void @llvm.hwasan.check.memaccess(i8* %x1, i8* %x0, i32 456) + call void @llvm.hwasan.check.memaccess(i8* %x1, i8* %x0, i32 66) ret i8* %x0 } declare void @llvm.hwasan.check.memaccess(i8*, i8*, i32) -; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x0_456,comdat -; CHECK-NEXT: .type __hwasan_check_x0_456,@function -; CHECK-NEXT: .weak __hwasan_check_x0_456 -; CHECK-NEXT: .hidden __hwasan_check_x0_456 -; CHECK-NEXT: __hwasan_check_x0_456: +; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x0_66,comdat +; CHECK-NEXT: .type __hwasan_check_x0_66,@function +; CHECK-NEXT: .weak __hwasan_check_x0_66 +; CHECK-NEXT: .hidden __hwasan_check_x0_66 +; CHECK-NEXT: __hwasan_check_x0_66: ; CHECK-NEXT: ubfx x16, x0, #4, #52 ; CHECK-NEXT: ldrb w16, [x9, x16] ; CHECK-NEXT: cmp x16, x0, lsr #56 @@ -46,7 +46,7 @@ ; CHECK-NEXT: cmp w16, #15 ; CHECK-NEXT: b.hi .Ltmp2 ; CHECK-NEXT: and x17, x0, #0xf -; CHECK-NEXT: add x17, x17, #255 +; CHECK-NEXT: add x17, x17, #3 ; CHECK-NEXT: cmp w16, w17 ; CHECK-NEXT: b.ls .Ltmp2 ; CHECK-NEXT: orr x16, x0, #0xf @@ -56,17 +56,17 @@ ; CHECK-NEXT: .Ltmp2: ; CHECK-NEXT: stp x0, x1, [sp, #-256]! ; CHECK-NEXT: stp x29, x30, [sp, #232] -; CHECK-NEXT: mov x1, #456 -; CHECK-NEXT: adrp x16, :got:__hwasan_tag_mismatch -; CHECK-NEXT: ldr x16, [x16, :got_lo12:__hwasan_tag_mismatch] +; CHECK-NEXT: mov x1, #2 +; CHECK-NEXT: adrp x16, :got:__hwasan_tag_mismatch_v2 +; CHECK-NEXT: ldr x16, [x16, :got_lo12:__hwasan_tag_mismatch_v2] ; CHECK-NEXT: br x16 -; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x1_123,comdat -; CHECK-NEXT: .type __hwasan_check_x1_123,@function -; CHECK-NEXT: .weak __hwasan_check_x1_123 -; CHECK-NEXT: .hidden __hwasan_check_x1_123 -; CHECK-NEXT: __hwasan_check_x1_123: +; CHECK: .section .text.hot,"axG",@progbits,__hwasan_check_x1_1,comdat +; CHECK-NEXT: .type __hwasan_check_x1_1,@function +; CHECK-NEXT: .weak __hwasan_check_x1_1 +; CHECK-NEXT: .hidden __hwasan_check_x1_1 +; CHECK-NEXT: __hwasan_check_x1_1: ; CHECK-NEXT: ubfx x16, x1, #4, #52 ; CHECK-NEXT: ldrb w16, [x9, x16] ; CHECK-NEXT: cmp x16, x1, lsr #56 @@ -74,21 +74,10 @@ ; CHECK-NEXT: .Ltmp4: ; CHECK-NEXT: ret ; CHECK-NEXT: .Ltmp3: -; CHECK-NEXT: cmp w16, #15 -; CHECK-NEXT: b.hi .Ltmp5 -; CHECK-NEXT: and x17, x1, #0xf -; CHECK-NEXT: add x17, x17, #2047 -; CHECK-NEXT: cmp w16, w17 -; CHECK-NEXT: b.ls .Ltmp5 -; CHECK-NEXT: orr x16, x1, #0xf -; CHECK-NEXT: ldrb w16, [x16] -; CHECK-NEXT: cmp x16, x1, lsr #56 -; CHECK-NEXT: b.eq .Ltmp4 -; CHECK-NEXT: .Ltmp5: ; CHECK-NEXT: stp x0, x1, [sp, #-256]! ; CHECK-NEXT: stp x29, x30, [sp, #232] ; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: mov x1, #123 +; CHECK-NEXT: mov x1, #1 ; CHECK-NEXT: adrp x16, :got:__hwasan_tag_mismatch ; CHECK-NEXT: ldr x16, [x16, :got_lo12:__hwasan_tag_mismatch] ; CHECK-NEXT: br x16 diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/alloca-compat.ll b/llvm/test/Instrumentation/HWAddressSanitizer/alloca-compat.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/alloca-compat.ll @@ -0,0 +1,17 @@ +; Test that alloca instrumentation with old API levels does not use short granules. +; +; RUN: opt < %s -hwasan -S | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-android" + +declare void @use32(i32*) + +define void @test_alloca() sanitize_hwaddress { +; CHECK-LABEL: @test_alloca( +; CHECK: %[[X_TAG:[^ ]*]] = trunc i64 {{.*}} to i8 +; CHECK: call void @llvm.memset.p0i8.i64(i8* align 1 {{.*}}, i8 %[[X_TAG]], i64 1, i1 false) + %x = alloca i32, align 4 + call void @use32(i32* nonnull %x) + ret void +} 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 @@ -5,7 +5,7 @@ ; RUN: opt < %s -hwasan -hwasan-with-ifunc=1 -hwasan-uar-retag-to-zero=0 -S | FileCheck %s --check-prefixes=CHECK,DYNAMIC-SHADOW,UAR-TAGS target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" -target triple = "aarch64--linux-android" +target triple = "aarch64--linux-android10000" declare void @use32(i32*) diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/basic-compat.ll b/llvm/test/Instrumentation/HWAddressSanitizer/basic-compat.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/basic-compat.ll @@ -0,0 +1,13 @@ +; Test that the old outlined check is used with old API levels. + +; RUN: opt < %s -hwasan -S | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-android" + +define i8 @test_load8(i8* %a) sanitize_hwaddress { +; CHECK-LABEL: @test_load8( +; CHECK: call void @llvm.hwasan.check.memaccess(i8* {{.*}}, i8* {{.*}}, i32 0) + %b = load i8, i8* %a, align 4 + ret i8 %b +} diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/basic.ll b/llvm/test/Instrumentation/HWAddressSanitizer/basic.ll --- a/llvm/test/Instrumentation/HWAddressSanitizer/basic.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/basic.ll @@ -14,7 +14,7 @@ ; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @hwasan.module_ctor, i8* bitcast (void ()* @hwasan.module_ctor to i8*) }] target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" -target triple = "aarch64--linux-android" +target triple = "aarch64--linux-android10000" define i8 @test_load8(i8* %a) sanitize_hwaddress { ; CHECK-LABEL: @test_load8( @@ -56,8 +56,8 @@ ; RECOVER: [[CONT]]: -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %a, i32 0) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %a, i32 0) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %a, i32 64) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %a, i32 64) ; CHECK: %[[G:[^ ]*]] = load i8, i8* %a, align 4 ; CHECK: ret i8 %[[G]] @@ -108,8 +108,8 @@ ; RECOVER: [[CONT]]: ; ABORT: %[[A:[^ ]*]] = bitcast i16* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 1) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 1) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 65) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 65) ; CHECK: %[[G:[^ ]*]] = load i16, i16* %a, align 4 ; CHECK: ret i16 %[[G]] @@ -136,8 +136,8 @@ ; RECOVER: br label ; ABORT: %[[A:[^ ]*]] = bitcast i32* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 2) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 2) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 66) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 66) ; CHECK: %[[G:[^ ]*]] = load i32, i32* %a, align 4 ; CHECK: ret i32 %[[G]] @@ -164,8 +164,8 @@ ; RECOVER: br label ; ABORT: %[[A:[^ ]*]] = bitcast i64* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 3) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 3) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 67) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 67) ; CHECK: %[[G:[^ ]*]] = load i64, i64* %a, align 8 ; CHECK: ret i64 %[[G]] @@ -192,8 +192,8 @@ ; RECOVER: br label ; ABORT: %[[A:[^ ]*]] = bitcast i128* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 4) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 4) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 68) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 68) ; CHECK: %[[G:[^ ]*]] = load i128, i128* %a, align 16 ; CHECK: ret i128 %[[G]] @@ -232,8 +232,8 @@ ; RECOVER: call void asm sideeffect "brk #2352", "{x0}"(i64 %[[A]]) ; RECOVER: br label -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %a, i32 16) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %a, i32 16) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %a, i32 80) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %a, i32 80) ; CHECK: store i8 %b, i8* %a, align 4 ; CHECK: ret void @@ -260,8 +260,8 @@ ; RECOVER: br label ; ABORT: %[[A:[^ ]*]] = bitcast i16* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 17) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 17) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 81) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 81) ; CHECK: store i16 %b, i16* %a, align 4 ; CHECK: ret void @@ -288,8 +288,8 @@ ; RECOVER: br label ; ABORT: %[[A:[^ ]*]] = bitcast i32* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 18) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 18) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 82) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 82) ; CHECK: store i32 %b, i32* %a, align 4 ; CHECK: ret void @@ -316,8 +316,8 @@ ; RECOVER: br label ; ABORT: %[[A:[^ ]*]] = bitcast i64* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 19) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 19) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 83) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 83) ; CHECK: store i64 %b, i64* %a, align 8 ; CHECK: ret void @@ -344,8 +344,8 @@ ; RECOVER: br label ; ABORT: %[[A:[^ ]*]] = bitcast i128* %a to i8* -; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 20) -; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 20) +; ABORT-DYNAMIC-SHADOW: call void @llvm.hwasan.check.memaccess(i8* %.hwasan.shadow, i8* %[[A]], i32 84) +; ABORT-ZERO-BASED-SHADOW: call void @llvm.hwasan.check.memaccess(i8* null, i8* %[[A]], i32 84) ; CHECK: store i128 %b, i128* %a, align 16 ; CHECK: ret void