diff --git a/clang/test/CodeGen/asan-use-callbacks.cpp b/clang/test/CodeGen/asan-use-callbacks.cpp --- a/clang/test/CodeGen/asan-use-callbacks.cpp +++ b/clang/test/CodeGen/asan-use-callbacks.cpp @@ -1,12 +1,18 @@ -// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -fsanitize=address \ -// RUN: -o - %s \ +// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - \ +// RUN: -fsanitize=address %s \ // RUN: | FileCheck %s --check-prefixes=CHECK-NO-OUTLINE // RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - \ // RUN: -fsanitize=address %s -fsanitize-address-outline-instrumentation \ // RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE +// RUN: %clang -target x86_64-linux-gnu -S -emit-llvm -o - \ +// RUN: -fsanitize=address %s -fsanitize-address-outline-instrumentation \ +// RUN: -mllvm -asan-optimize-callbacks \ +// RUN: | FileCheck %s --check-prefixes=CHECK-OPTIMIZED + // CHECK-NO-OUTLINE-NOT: call{{.*}}@__asan_load4 // CHECK-OUTLINE: call{{.*}}@__asan_load4 +// CHECK-OPTIMIZED: call{{.*}}@llvm.asan.check.memaccess(i8*{{.*}}, i64{{.*}}, i32{{.*}}) int deref(int *p) { return *p; diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h --- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h +++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h @@ -147,6 +147,10 @@ bool UseOdrIndicator = true, AsanDtorKind DestructorKind = AsanDtorKind::Global); +// Get AddressSanitizer parameters. +void getAddressSanitizerParams(Module &M, uint64_t *ShadowBase, + int *MappingScale, bool *OrShadowOffset); + } // namespace llvm #endif diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h --- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h +++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h @@ -87,6 +87,8 @@ return true; } +void getASanShadowMapping(int *Scale, uint64_t *Offset, bool *OrShadowOffset); + } // namespace llvm #endif diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -348,6 +348,10 @@ static cl::opt ClOpt("asan-opt", cl::desc("Optimize instrumentation"), cl::Hidden, cl::init(true)); +static cl::opt ClOptimizeCallbacks("asan-optimize-callbacks", + cl::desc("Optimize callbacks"), + cl::Hidden, cl::init(false)); + static cl::opt ClOptSameTemp( "asan-opt-same-temp", cl::desc("Instrument the same temp just once"), cl::Hidden, cl::init(true)); @@ -559,6 +563,17 @@ return Mapping; } +void getAddressSanitizerParams(Module &M, uint64_t *ShadowBase, + int *MappingScale, bool *OrShadowOffset) { + Triple TargetTriple = Triple(M.getTargetTriple()); + auto Mapping = + getShadowMapping(TargetTriple, M.getDataLayout().getPointerSizeInBits(), + ClEnableKasan.getNumOccurrences() > 0); + *ShadowBase = Mapping.Offset; + *MappingScale = Mapping.Scale; + *OrShadowOffset = Mapping.OrShadowOffset; +} + static uint64_t getRedzoneSizeForScale(int MappingScale) { // Redzone used for stack and globals is at least 32 bytes. // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively. @@ -623,6 +638,7 @@ C = &(M.getContext()); LongSize = M.getDataLayout().getPointerSizeInBits(); IntptrTy = Type::getIntNTy(*C, LongSize); + Int8PtrTy = Type::getInt8PtrTy(*C); TargetTriple = Triple(M.getTargetTriple()); Mapping = getShadowMapping(TargetTriple, LongSize, this->CompileKernel); @@ -673,6 +689,7 @@ Value *SizeArgument, uint32_t Exp); void instrumentMemIntrinsic(MemIntrinsic *MI); Value *memToShadow(Value *Shadow, IRBuilder<> &IRB); + void encodeMemToShadowInfo(int64_t *AccessInfo); bool suppressInstrumentationSiteForDebug(int &Instrumented); bool instrumentFunction(Function &F, const TargetLibraryInfo *TLI); bool maybeInsertAsanInitAtFunctionEntry(Function &F); @@ -713,6 +730,7 @@ bool UseAfterScope; AsanDetectStackUseAfterReturnMode UseAfterReturn; Type *IntptrTy; + Type *Int8PtrTy; ShadowMapping Mapping; FunctionCallee AsanHandleNoReturnFunc; FunctionCallee AsanPtrCmpFunction, AsanPtrSubFunction; @@ -1742,12 +1760,21 @@ size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); if (UseCalls) { - if (Exp == 0) - IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], - AddrLong); - else - IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex], - {AddrLong, ConstantInt::get(IRB.getInt32Ty(), Exp)}); + if (ClOptimizeCallbacks) { + Value *Ptr8 = IRB.CreatePointerCast(Addr, Int8PtrTy); + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); + IRB.CreateCall( + Intrinsic::getDeclaration(M, Intrinsic::asan_check_memaccess), + {Ptr8, ConstantInt::get(IRB.getInt8Ty(), IsWrite), + ConstantInt::get(IRB.getInt8Ty(), AccessSizeIndex)}); + } else { + if (Exp == 0) + IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], + AddrLong); + else + IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex], + {AddrLong, ConstantInt::get(IRB.getInt32Ty(), Exp)}); + } return; }