From 2c07cb571f9a6d046084a96046676c946725a8fe Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Tue, 14 May 2019 21:17:21 +0000 Subject: [PATCH] [NewPM] Port HWASan and Kernel HWASan Port hardware assisted address sanitizer to new PM following the same guidelines as msan and tsan. Changes: - Separate HWAddressSanitizer into a pass class and a sanitizer class. - Create new PM wrapper pass for the sanitizer class. - Use the getOrINsert pattern for some module level initialization declarations. - Also enable kernel-kwasan in new PM - Update llvm tests and add clang test. Differential Revision: https://reviews.llvm.org/D61709 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360707 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/BackendUtil.cpp | 34 ++++++++++++++++++++++++++++++++-- test/CodeGen/hwasan-new-pm.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/hwasan-new-pm.c diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index f6018e7d62..32eb776a6d 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -57,6 +57,7 @@ #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" #include "llvm/Transforms/Instrumentation/BoundsChecking.h" #include "llvm/Transforms/Instrumentation/GCOVProfiler.h" +#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" @@ -265,12 +266,13 @@ static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder, static_cast(Builder); const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress); - PM.add(createHWAddressSanitizerPass(/*CompileKernel*/ false, Recover)); + PM.add( + createHWAddressSanitizerLegacyPassPass(/*CompileKernel*/ false, Recover)); } static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createHWAddressSanitizerPass( + PM.add(createHWAddressSanitizerLegacyPassPass( /*CompileKernel*/ true, /*Recover*/ true)); } @@ -962,6 +964,17 @@ static void addSanitizersAtO0(ModulePassManager &MPM, if (LangOpts.Sanitize.has(SanitizerKind::Thread)) { MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } + + if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) { + bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress); + MPM.addPass(createModuleToFunctionPassAdaptor( + HWAddressSanitizerPass(/*CompileKernel=*/false, Recover))); + } + + if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { + MPM.addPass(createModuleToFunctionPassAdaptor( + HWAddressSanitizerPass(/*CompileKernel=*/true, /*Recover=*/true))); + } } /// A clean version of `EmitAssembly` that uses the new pass manager. @@ -1145,6 +1158,23 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( UseOdrIndicator)); }); } + if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) { + bool Recover = + CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress); + PB.registerOptimizerLastEPCallback( + [Recover](FunctionPassManager &FPM, + PassBuilder::OptimizationLevel Level) { + FPM.addPass(HWAddressSanitizerPass( + /*CompileKernel=*/false, Recover)); + }); + } + if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { + PB.registerOptimizerLastEPCallback( + [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { + FPM.addPass(HWAddressSanitizerPass( + /*CompileKernel=*/true, /*Recover=*/true)); + }); + } if (Optional Options = getGCOVOptions(CodeGenOpts)) PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) { MPM.addPass(GCOVProfilerPass(*Options)); diff --git a/test/CodeGen/hwasan-new-pm.c b/test/CodeGen/hwasan-new-pm.c new file mode 100644 index 0000000000..266e750031 --- /dev/null +++ b/test/CodeGen/hwasan-new-pm.c @@ -0,0 +1,34 @@ +// Test that HWASan and KHWASan runs with the new pass manager. +// We run them under different optimizations and LTOs to ensure the IR is still +// being instrumented properly. + +// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=hwaddress %s | FileCheck %s --check-prefixes=CHECK,HWASAN,HWASAN-NOOPT +// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,HWASAN,HWASAN-NOOPT +// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=hwaddress -flto=thin %s | FileCheck %s --check-prefixes=CHECK,HWASAN,HWASAN-NOOPT +// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=hwaddress %s | FileCheck %s --check-prefixes=CHECK,HWASAN +// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,HWASAN +// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=hwaddress -flto=thin %s | FileCheck %s + +// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress %s | FileCheck %s --check-prefixes=CHECK,KHWASAN,KHWASAN-NOOPT +// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,KHWASAN,KHWASAN-NOOPT +// RUN: %clang_cc1 -S -emit-llvm -o - -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto=thin %s | FileCheck %s --check-prefixes=CHECK,KHWASAN,KHWASAN-NOOPT +// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress %s | FileCheck %s --check-prefixes=CHECK,KHWASAN +// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto %s | FileCheck %s --check-prefixes=CHECK,KHWASAN +// RUN: %clang_cc1 -S -emit-llvm -o - -O1 -fexperimental-new-pass-manager -fsanitize=kernel-hwaddress -flto=thin %s | FileCheck %s + +int foo(int *a) { return *a; } + +// All the cases above mark the function with sanitize_hwaddress. +// CHECK-DAG: sanitize_hwaddress + +// Both sanitizers produce %hwasan.shadow without both thinlto and optimizations. +// HWASAN-DAG: %hwasan.shadow +// KHWASAN-DAG: %hwasan.shadow + +// Both sanitizers produce __hwasan_tls without both thinlto and optimizations. +// HWASAN-DAG: __hwasan_tls +// KHWASAN-DAG: __hwasan_tls + +// For unoptimized cases, both sanitizers produce different load functions. +// HWASAN-NOOPT-DAG: __hwasan_loadN +// KHWASAN-NOOPT-DAG: __hwasan_loadN_noabort -- 2.40.0