diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1187,9 +1187,7 @@ MPM.addPass(RequireAnalysisPass()); MPM.addPass(ModuleAddressSanitizerPass( CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator, - DestructorKind)); - MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( - {CompileKernel, Recover, UseAfterScope, UseAfterReturn}))); + DestructorKind, UseAfterScope, UseAfterReturn)); } }; ASanPass(SanitizerKind::Address, false); diff --git a/clang/test/CodeGen/asan-stack-safety-analysis.c b/clang/test/CodeGen/asan-stack-safety-analysis.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/asan-stack-safety-analysis.c @@ -0,0 +1,16 @@ +// REQUIRES: x86_64-pc-linux-gnu + +// RUN: %clang -fno-legacy-pass-manager -fsanitize=address -fsanitize-address-outline-instrumentation -target x86_64-pc-linux-gnu -S -emit-llvm -mllvm -asan-use-stack-safety=true -O2 %s -o - | FileCheck %s --check-prefix=SAFETY +// RUN: %clang -fno-legacy-pass-manager -fsanitize=address -fsanitize-address-outline-instrumentation -target x86_64-pc-linux-gnu -S -emit-llvm -mllvm -asan-use-stack-safety=false -O2 %s -o - | FileCheck %s --check-prefix=NOSAFETY + +// RUN: %clang -flegacy-pass-manager -fsanitize=address -target x86_64-pc-linux-gnu -S -emit-llvm -mllvm -asan-use-stack-safety=true -O2 %s -o - | FileCheck %s --check-prefix=SAFETY +// RUN: %clang -flegacy-pass-manager -fsanitize=address -target x86_64-pc-linux-gnu -S -emit-llvm -mllvm -asan-use-stack-safety=false -O2 %s -o - | FileCheck %s --check-prefix=NOSAFETY + +int main(int argc, char **argv) { + char buf[10]; + volatile char *x = buf; + *x = 0; + return buf[0]; + // NOSAFETY: call void @__asan_load1 + // SAFETY-NOT: call void @__asan_load1 +} 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 @@ -89,40 +89,6 @@ static AnalysisKey Key; }; -struct AddressSanitizerOptions { - AddressSanitizerOptions() - : AddressSanitizerOptions(false, false, false, - AsanDetectStackUseAfterReturnMode::Runtime){}; - AddressSanitizerOptions(bool CompileKernel, bool Recover, bool UseAfterScope, - AsanDetectStackUseAfterReturnMode UseAfterReturn) - : CompileKernel(CompileKernel), Recover(Recover), - UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn){}; - bool CompileKernel; - bool Recover; - bool UseAfterScope; - AsanDetectStackUseAfterReturnMode UseAfterReturn; -}; - -/// Public interface to the address sanitizer pass for instrumenting code to -/// check for various memory errors at runtime. -/// -/// The sanitizer itself is a function pass that works by inserting various -/// calls to the ASan runtime library functions. The runtime library essentially -/// replaces malloc() and free() with custom implementations that allow regions -/// surrounding requested memory to be checked for invalid accesses. -class AddressSanitizerPass : public PassInfoMixin { -public: - explicit AddressSanitizerPass(AddressSanitizerOptions Options) - : Options(Options){}; - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); - void printPipeline(raw_ostream &OS, - function_ref MapClassName2PassName); - static bool isRequired() { return true; } - -private: - AddressSanitizerOptions Options; -}; - /// Public interface to the address sanitizer module pass for instrumenting code /// to check for various memory errors. /// @@ -134,7 +100,10 @@ explicit ModuleAddressSanitizerPass( bool CompileKernel = false, bool Recover = false, bool UseGlobalGC = true, bool UseOdrIndicator = false, - AsanDtorKind DestructorKind = AsanDtorKind::Global); + AsanDtorKind DestructorKind = AsanDtorKind::Global, + bool UseAfterScope = false, + AsanDetectStackUseAfterReturnMode UseAfterReturn = + AsanDetectStackUseAfterReturnMode::Runtime); PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); void printPipeline(raw_ostream &OS, function_ref MapClassName2PassName); @@ -146,6 +115,8 @@ bool UseGlobalGC; bool UseOdrIndicator; AsanDtorKind DestructorKind; + bool UseAfterScope; + AsanDetectStackUseAfterReturnMode UseAfterReturn; }; // Insert AddressSanitizer (address sanity checking) instrumentation diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -584,24 +584,6 @@ return parseSinglePassOption(Params, "kernel", "ModuleAddressSanitizer"); } -Expected parseASanPassOptions(StringRef Params) { - AddressSanitizerOptions Result; - while (!Params.empty()) { - StringRef ParamName; - std::tie(ParamName, Params) = Params.split(';'); - - if (ParamName == "kernel") { - Result.CompileKernel = true; - } else { - return make_error( - formatv("invalid AddressSanitizer pass parameter '{0}' ", ParamName) - .str(), - inconvertibleErrorCode()); - } - } - return Result; -} - Expected parseHWASanPassOptions(StringRef Params) { HWAddressSanitizerOptions Result; while (!Params.empty()) { diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -393,13 +393,6 @@ "no-profile-peeling;profile-peeling;" "no-runtime;runtime;" "no-upperbound;upperbound") -FUNCTION_PASS_WITH_PARAMS("asan", - "AddressSanitizerPass", - [](AddressSanitizerOptions Opts) { - return AddressSanitizerPass(Opts); - }, - parseASanPassOptions, - "kernel") FUNCTION_PASS_WITH_PARAMS("msan", "MemorySanitizerPass", [](MemorySanitizerOptions Opts) { 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 @@ -1254,35 +1254,6 @@ return GlobalsMetadata(M); } -PreservedAnalyses AddressSanitizerPass::run(Function &F, - AnalysisManager &AM) { - auto &MAMProxy = AM.getResult(F); - Module &M = *F.getParent(); - if (auto *R = MAMProxy.getCachedResult(M)) { - const TargetLibraryInfo *TLI = &AM.getResult(F); - AddressSanitizer Sanitizer(M, R, Options.CompileKernel, Options.Recover, - Options.UseAfterScope, Options.UseAfterReturn); - if (Sanitizer.instrumentFunction(F, TLI)) - return PreservedAnalyses::none(); - return PreservedAnalyses::all(); - } - - report_fatal_error( - "The ASanGlobalsMetadataAnalysis is required to run before " - "AddressSanitizer can run"); - return PreservedAnalyses::all(); -} - -void AddressSanitizerPass::printPipeline( - raw_ostream &OS, function_ref MapClassName2PassName) { - static_cast *>(this)->printPipeline( - OS, MapClassName2PassName); - OS << "<"; - if (Options.CompileKernel) - OS << "kernel"; - OS << ">"; -} - void ModuleAddressSanitizerPass::printPipeline( raw_ostream &OS, function_ref MapClassName2PassName) { static_cast *>(this)->printPipeline( @@ -1295,9 +1266,11 @@ ModuleAddressSanitizerPass::ModuleAddressSanitizerPass( bool CompileKernel, bool Recover, bool UseGlobalGC, bool UseOdrIndicator, - AsanDtorKind DestructorKind) + AsanDtorKind DestructorKind, bool UseAfterScope, + AsanDetectStackUseAfterReturnMode UseAfterReturn) : CompileKernel(CompileKernel), Recover(Recover), UseGlobalGC(UseGlobalGC), - UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind) {} + UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind), + UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn) {} PreservedAnalyses ModuleAddressSanitizerPass::run(Module &M, AnalysisManager &AM) { @@ -1305,7 +1278,14 @@ ModuleAddressSanitizer Sanitizer(M, &GlobalsMD, CompileKernel, Recover, UseGlobalGC, UseOdrIndicator, DestructorKind); - if (Sanitizer.instrumentModule(M)) + bool Modified = Sanitizer.instrumentModule(M); + const TargetLibraryInfo *TLI = &AM.getResult(M); + for (Function &F : M) { + AddressSanitizer Sanitizer(M, &GlobalsMD, CompileKernel, Recover, + UseAfterScope, UseAfterReturn); + Modified |= Sanitizer.instrumentFunction(F, TLI); + } + if (Modified) return PreservedAnalyses::none(); return PreservedAnalyses::all(); } diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll.rej b/llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll.rej new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/msan_eager.ll.rej @@ -0,0 +1,22 @@ +--- msan_eager.ll ++++ msan_eager.ll +@@ -69,8 +69,8 @@ + + define void @NormalArgAfterNoUndef(i32 noundef %a, i32 %b) nounwind uwtable sanitize_memory { + ; CHECK-LABEL: @NormalArgAfterNoUndef( +-; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* bitcast ([100 x i64]* @__msan_param_tls to i32*), align 8 +-; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__msan_param_origin_tls, i32 0, i32 0), align 4 ++; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i32*), align 8 ++; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* inttoptr (i64 add (i64 ptrtoint ([200 x i32]* @__msan_param_origin_tls to i64), i64 8) to i32*), align 4 + ; CHECK-NEXT: call void @llvm.donothing() + ; CHECK-NEXT: [[P:%.*]] = inttoptr i64 0 to i32* + ; CHECK-NEXT: [[TMP3:%.*]] = ptrtoint i32* [[P]] to i64 +@@ -135,7 +135,7 @@ + ; CHECK-LABEL: @CallNormalArgAfterNoUndef( + ; CHECK-NEXT: call void @llvm.donothing() + ; CHECK-NEXT: [[R:%.*]] = call i32 @NormalRet() #[[ATTR0]] +-; CHECK-NEXT: store i32 0, i32* bitcast ([100 x i64]* @__msan_param_tls to i32*), align 8 ++; CHECK-NEXT: store i32 0, i32* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i32*), align 8 + ; CHECK-NEXT: call void @NormalArgAfterNoUndef(i32 [[R]], i32 [[R]]) #[[ATTR0]] + ; CHECK-NEXT: ret void + ;