summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/Sanitizers.def3
-rw-r--r--clang/include/clang/Basic/Sanitizers.h3
-rw-r--r--clang/lib/AST/Decl.cpp3
-rw-r--r--clang/lib/Basic/Sanitizers.cpp4
-rw-r--r--clang/lib/CodeGen/BackendUtil.cpp17
-rw-r--r--clang/lib/CodeGen/CGDeclCXX.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--clang/lib/CodeGen/SanitizerMetadata.cpp9
-rw-r--r--clang/lib/Driver/SanitizerArgs.cpp5
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp4
-rw-r--r--clang/test/CodeGen/address-safety-attr-kasan.cpp38
-rw-r--r--clang/test/Driver/asan.c17
-rw-r--r--clang/test/Driver/fsanitize.c12
-rw-r--r--clang/test/Lexer/has_feature_address_sanitizer.cpp1
-rw-r--r--llvm/include/llvm/Transforms/Instrumentation.h4
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp103
17 files changed, 171 insertions, 62 deletions
diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def
index 9e341ae55da..1b528c8d6f6 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -41,6 +41,9 @@
// AddressSanitizer
SANITIZER("address", Address)
+// Kernel AddressSanitizer (KASan)
+SANITIZER("kernel-address", KernelAddress)
+
// MemorySanitizer
SANITIZER("memory", Memory)
diff --git a/clang/include/clang/Basic/Sanitizers.h b/clang/include/clang/Basic/Sanitizers.h
index 3b1797e9f53..78c1ddb56f9 100644
--- a/clang/include/clang/Basic/Sanitizers.h
+++ b/clang/include/clang/Basic/Sanitizers.h
@@ -52,6 +52,9 @@ struct SanitizerSet {
/// \brief Check if a certain (single) sanitizer is enabled.
bool has(SanitizerMask K) const;
+ /// \brief Check if one or more sanitizers are enabled.
+ bool hasOneOf(SanitizerMask K) const;
+
/// \brief Enable or disable a certain (single) sanitizer.
void set(SanitizerMask K, bool Value);
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 8eff4c4427b..d9a3389c58f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3681,7 +3681,8 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
ASTContext &Context = getASTContext();
- if (!Context.getLangOpts().Sanitize.has(SanitizerKind::Address) ||
+ if (!Context.getLangOpts().Sanitize.hasOneOf(
+ SanitizerKind::Address | SanitizerKind::KernelAddress) ||
!Context.getLangOpts().SanitizeAddressFieldPadding)
return false;
const auto &Blacklist = Context.getSanitizerBlacklist();
diff --git a/clang/lib/Basic/Sanitizers.cpp b/clang/lib/Basic/Sanitizers.cpp
index 8c4884b8ec3..d3676b6b465 100644
--- a/clang/lib/Basic/Sanitizers.cpp
+++ b/clang/lib/Basic/Sanitizers.cpp
@@ -25,6 +25,10 @@ bool SanitizerSet::has(SanitizerMask K) const {
return Mask & K;
}
+bool SanitizerSet::hasOneOf(SanitizerMask K) const {
+ return Mask & K;
+}
+
void SanitizerSet::set(SanitizerMask K, bool Value) {
assert(llvm::countPopulation(K) == 1);
Mask = Value ? (Mask | K) : (Mask & ~K);
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 30e9ebffa28..f5edea7810a 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -201,8 +201,14 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
- PM.add(createAddressSanitizerFunctionPass());
- PM.add(createAddressSanitizerModulePass());
+ PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/false));
+ PM.add(createAddressSanitizerModulePass(/*CompileKernel*/false));
+}
+
+static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/true));
+ PM.add(createAddressSanitizerModulePass(/*CompileKernel*/true));
}
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
@@ -328,6 +334,13 @@ void EmitAssemblyHelper::CreatePasses() {
addAddressSanitizerPasses);
}
+ if (LangOpts.Sanitize.has(SanitizerKind::KernelAddress)) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addKernelAddressSanitizerPasses);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addKernelAddressSanitizerPasses);
+ }
+
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addMemorySanitizerPass);
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 50a499607f8..bae8ab4ea0d 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -267,7 +267,8 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction(
Fn->setDoesNotThrow();
if (!isInSanitizerBlacklist(Fn, Loc)) {
- if (getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
if (getLangOpts().Sanitize.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index f370ac27676..bece41e9ecb 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -615,7 +615,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
}
// Apply sanitizer attributes to the function.
- if (SanOpts.has(SanitizerKind::Address))
+ if (SanOpts.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress))
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
if (SanOpts.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c0cbe98484f..2dd5414795e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1218,8 +1218,9 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::Function *Fn,
bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
SourceLocation Loc, QualType Ty,
StringRef Category) const {
- // For now globals can be blacklisted only in ASan.
- if (!LangOpts.Sanitize.has(SanitizerKind::Address))
+ // For now globals can be blacklisted only in ASan and KASan.
+ if (!LangOpts.Sanitize.hasOneOf(
+ SanitizerKind::Address | SanitizerKind::KernelAddress))
return false;
const auto &SanitizerBL = getContext().getSanitizerBlacklist();
if (SanitizerBL.isBlacklistedGlobal(GV->getName(), Category))
diff --git a/clang/lib/CodeGen/SanitizerMetadata.cpp b/clang/lib/CodeGen/SanitizerMetadata.cpp
index 7c38b2807e9..2a338bac4b4 100644
--- a/clang/lib/CodeGen/SanitizerMetadata.cpp
+++ b/clang/lib/CodeGen/SanitizerMetadata.cpp
@@ -25,7 +25,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
SourceLocation Loc, StringRef Name,
QualType Ty, bool IsDynInit,
bool IsBlacklisted) {
- if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
return;
IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init");
IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty);
@@ -56,7 +57,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
const VarDecl &D, bool IsDynInit) {
- if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
return;
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -67,7 +69,8 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
// For now, just make sure the global is not modified by the ASan
// instrumentation.
- if (CGM.getLangOpts().Sanitize.has(SanitizerKind::Address))
+ if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
}
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 9918fcbd5e1..4d27a393182 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -305,7 +305,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
std::make_pair(Address, Thread), std::make_pair(Address, Memory),
std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
- std::make_pair(Leak, Memory)};
+ std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
+ std::make_pair(KernelAddress, Leak),
+ std::make_pair(KernelAddress, Thread),
+ std::make_pair(KernelAddress, Memory)};
for (auto G : IncompatibleGroups) {
SanitizerMask Group = G.first;
if (Kinds & Group) {
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index c63cafb6d79..ccfb30240b0 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1049,7 +1049,9 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
Feature = Feature.substr(2, Feature.size() - 4);
return llvm::StringSwitch<bool>(Feature)
- .Case("address_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Address))
+ .Case("address_sanitizer",
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress))
.Case("attribute_analyzer_noreturn", true)
.Case("attribute_availability", true)
.Case("attribute_availability_with_message", true)
diff --git a/clang/test/CodeGen/address-safety-attr-kasan.cpp b/clang/test/CodeGen/address-safety-attr-kasan.cpp
new file mode 100644
index 00000000000..c84ba88291d
--- /dev/null
+++ b/clang/test/CodeGen/address-safety-attr-kasan.cpp
@@ -0,0 +1,38 @@
+// Make sure the sanitize_address attribute is emitted when using both ASan and KASan.
+// Also document that __attribute__((no_sanitize_address)) doesn't disable KASan instrumentation.
+
+/// RUN: %clang_cc1 -triple i386-unknown-linux -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NOASAN %s
+/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=address -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-ASAN %s
+/// RUN: %clang_cc1 -triple i386-unknown-linux -fsanitize=kernel-address -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-KASAN %s
+
+int HasSanitizeAddress() {
+ return 1;
+}
+// CHECK-NOASAN: {{Function Attrs: nounwind$}}
+// CHECK-ASAN: Function Attrs: nounwind sanitize_address
+// CHECK-KASAN: Function Attrs: nounwind sanitize_address
+
+__attribute__((no_sanitize("address")))
+int NoSanitizeQuoteAddress() {
+ return 0;
+}
+// CHECK-NOASAN: {{Function Attrs: nounwind$}}
+// CHECK-ASAN: {{Function Attrs: nounwind$}}
+// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}}
+
+__attribute__((no_sanitize_address))
+int NoSanitizeAddress() {
+ return 0;
+}
+// CHECK-NOASAN: {{Function Attrs: nounwind$}}
+// CHECK-ASAN: {{Function Attrs: nounwind$}}
+// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}}
+
+__attribute__((no_sanitize("kernel-address")))
+int NoSanitizeKernelAddress() {
+ return 0;
+}
+
+// CHECK-NOASAN: {{Function Attrs: nounwind$}}
+// CHECK-ASAN: {{Function Attrs: nounwind sanitize_address$}}
+// CHECK-KASAN: {{Function Attrs: nounwind$}}
diff --git a/clang/test/Driver/asan.c b/clang/test/Driver/asan.c
index f199e904e75..4db103d2646 100644
--- a/clang/test/Driver/asan.c
+++ b/clang/test/Driver/asan.c
@@ -1,8 +1,13 @@
-// RUN: %clang -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O1 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O2 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
-// RUN: %clang -O3 -target i386-unknown-unknown -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s
-// Verify that -fsanitize=address invokes asan instrumentation.
+// RUN: %clang -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN
+// RUN: %clang -O1 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN
+// RUN: %clang -O2 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN
+// RUN: %clang -O3 -target i386-unknown-linux -fsanitize=address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-ASAN
+// RUN: %clang -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN
+// RUN: %clang -O1 -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN
+// RUN: %clang -O2 -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN
+// RUN: %clang -O3 -target i386-unknown-linux -fsanitize=kernel-address %s -S -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-KASAN
+// Verify that -fsanitize={address,kernel-address} invoke ASan and KASan instrumentation.
int foo(int *a) { return *a; }
-// CHECK: __asan_init
+// CHECK-ASAN: __asan_init
+// CHECK-KASAN: __asan_load4_noabort
diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c
index 5c30dc12f6c..66e49250bae 100644
--- a/clang/test/Driver/fsanitize.c
+++ b/clang/test/Driver/fsanitize.c
@@ -59,6 +59,18 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=leak,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANL-SANM
// CHECK-SANL-SANM: '-fsanitize=leak' not allowed with '-fsanitize=memory'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANT
+// CHECK-SANKA-SANT: '-fsanitize=kernel-address' not allowed with '-fsanitize=thread'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,memory -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANM
+// CHECK-SANKA-SANM: '-fsanitize=kernel-address' not allowed with '-fsanitize=memory'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANA
+// CHECK-SANKA-SANA: '-fsanitize=kernel-address' not allowed with '-fsanitize=address'
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=kernel-address,leak -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANKA-SANL
+// CHECK-SANKA-SANL: '-fsanitize=kernel-address' not allowed with '-fsanitize=leak'
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize-memory-track-origins -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-TRACK-ORIGINS
// CHECK-ONLY-TRACK-ORIGINS: warning: argument unused during compilation: '-fsanitize-memory-track-origins'
diff --git a/clang/test/Lexer/has_feature_address_sanitizer.cpp b/clang/test/Lexer/has_feature_address_sanitizer.cpp
index 5c981161f9f..406a2ab179a 100644
--- a/clang/test/Lexer/has_feature_address_sanitizer.cpp
+++ b/clang/test/Lexer/has_feature_address_sanitizer.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -E -fsanitize=address %s -o - | FileCheck --check-prefix=CHECK-ASAN %s
+// RUN: %clang_cc1 -E -fsanitize=kernel-address %s -o - | FileCheck --check-prefix=CHECK-ASAN %s
// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-ASAN %s
#if __has_feature(address_sanitizer)
diff --git a/llvm/include/llvm/Transforms/Instrumentation.h b/llvm/include/llvm/Transforms/Instrumentation.h
index fbad76c0177..250e3893cb1 100644
--- a/llvm/include/llvm/Transforms/Instrumentation.h
+++ b/llvm/include/llvm/Transforms/Instrumentation.h
@@ -84,8 +84,8 @@ ModulePass *createInstrProfilingPass(
const InstrProfOptions &Options = InstrProfOptions());
// Insert AddressSanitizer (address sanity checking) instrumentation
-FunctionPass *createAddressSanitizerFunctionPass();
-ModulePass *createAddressSanitizerModulePass();
+FunctionPass *createAddressSanitizerFunctionPass(bool CompileKernel = false);
+ModulePass *createAddressSanitizerModulePass(bool CompileKernel = false);
// Insert MemorySanitizer instrumentation (detection of uninitialized reads)
FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0);
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 2e088ccb29b..2dd2fe6211c 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -67,6 +67,7 @@ static const uint64_t kDefaultShadowOffset32 = 1ULL << 29;
static const uint64_t kIOSShadowOffset32 = 1ULL << 30;
static const uint64_t kDefaultShadowOffset64 = 1ULL << 44;
static const uint64_t kSmallX86_64ShadowOffset = 0x7FFF8000; // < 2G.
+static const uint64_t kLinuxKasan_ShadowOffset64 = 0xdffffc0000000000;
static const uint64_t kPPC64_ShadowOffset64 = 1ULL << 41;
static const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa0000;
static const uint64_t kMIPS64_ShadowOffset64 = 1ULL << 37;
@@ -115,6 +116,9 @@ static const size_t kNumberOfAccessSizes = 5;
static const unsigned kAllocaRzSize = 32;
// Command-line flags.
+static cl::opt<bool> ClEnableKasan(
+ "asan-kernel", cl::desc("Enable KernelAddressSanitizer instrumentation"),
+ cl::Hidden, cl::init(false));
// This flag may need to be replaced with -f[no-]asan-reads.
static cl::opt<bool> ClInstrumentReads("asan-instrument-reads",
@@ -315,7 +319,8 @@ struct ShadowMapping {
bool OrShadowOffset;
};
-static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize) {
+static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize,
+ bool IsKasan) {
bool IsAndroid = TargetTriple.getEnvironment() == llvm::Triple::Android;
bool IsIOS = TargetTriple.isiOS();
bool IsFreeBSD = TargetTriple.isOSFreeBSD();
@@ -350,9 +355,12 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize) {
Mapping.Offset = kPPC64_ShadowOffset64;
else if (IsFreeBSD)
Mapping.Offset = kFreeBSD_ShadowOffset64;
- else if (IsLinux && IsX86_64)
- Mapping.Offset = kSmallX86_64ShadowOffset;
- else if (IsMIPS64)
+ else if (IsLinux && IsX86_64) {
+ if (IsKasan)
+ Mapping.Offset = kLinuxKasan_ShadowOffset64;
+ else
+ Mapping.Offset = kSmallX86_64ShadowOffset;
+ } else if (IsMIPS64)
Mapping.Offset = kMIPS64_ShadowOffset64;
else if (IsAArch64)
Mapping.Offset = kAArch64_ShadowOffset64;
@@ -381,7 +389,8 @@ static size_t RedzoneSizeForScale(int MappingScale) {
/// AddressSanitizer: instrument the code in module to find memory bugs.
struct AddressSanitizer : public FunctionPass {
- AddressSanitizer() : FunctionPass(ID) {
+ explicit AddressSanitizer(bool CompileKernel = false)
+ : FunctionPass(ID), CompileKernel(CompileKernel || ClEnableKasan) {
initializeAddressSanitizerPass(*PassRegistry::getPassRegistry());
}
const char *getPassName() const override {
@@ -444,11 +453,12 @@ struct AddressSanitizer : public FunctionPass {
LLVMContext *C;
Triple TargetTriple;
int LongSize;
+ bool CompileKernel;
Type *IntptrTy;
ShadowMapping Mapping;
DominatorTree *DT;
- Function *AsanCtorFunction;
- Function *AsanInitFunction;
+ Function *AsanCtorFunction = nullptr;
+ Function *AsanInitFunction = nullptr;
Function *AsanHandleNoReturnFunc;
Function *AsanPtrCmpFunction, *AsanPtrSubFunction;
// This array is indexed by AccessIsWrite, Experiment and log2(AccessSize).
@@ -467,7 +477,8 @@ struct AddressSanitizer : public FunctionPass {
class AddressSanitizerModule : public ModulePass {
public:
- AddressSanitizerModule() : ModulePass(ID) {}
+ explicit AddressSanitizerModule(bool CompileKernel = false)
+ : ModulePass(ID), CompileKernel(CompileKernel || ClEnableKasan) {}
bool runOnModule(Module &M) override;
static char ID; // Pass identification, replacement for typeid
const char *getPassName() const override { return "AddressSanitizerModule"; }
@@ -484,6 +495,7 @@ class AddressSanitizerModule : public ModulePass {
}
GlobalsMetadata GlobalsMD;
+ bool CompileKernel;
Type *IntptrTy;
LLVMContext *C;
Triple TargetTriple;
@@ -689,8 +701,8 @@ INITIALIZE_PASS_END(
AddressSanitizer, "asan",
"AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false,
false)
-FunctionPass *llvm::createAddressSanitizerFunctionPass() {
- return new AddressSanitizer();
+FunctionPass *llvm::createAddressSanitizerFunctionPass(bool CompileKernel) {
+ return new AddressSanitizer(CompileKernel);
}
char AddressSanitizerModule::ID = 0;
@@ -699,8 +711,8 @@ INITIALIZE_PASS(
"AddressSanitizer: detects use-after-free and out-of-bounds bugs."
"ModulePass",
false, false)
-ModulePass *llvm::createAddressSanitizerModulePass() {
- return new AddressSanitizerModule();
+ModulePass *llvm::createAddressSanitizerModulePass(bool CompileKernel) {
+ return new AddressSanitizerModule(CompileKernel);
}
static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
@@ -1344,16 +1356,18 @@ bool AddressSanitizerModule::runOnModule(Module &M) {
int LongSize = M.getDataLayout().getPointerSizeInBits();
IntptrTy = Type::getIntNTy(*C, LongSize);
TargetTriple = Triple(M.getTargetTriple());
- Mapping = getShadowMapping(TargetTriple, LongSize);
+ Mapping = getShadowMapping(TargetTriple, LongSize, CompileKernel);
initializeCallbacks(M);
bool Changed = false;
- Function *CtorFunc = M.getFunction(kAsanModuleCtorName);
- assert(CtorFunc);
- IRBuilder<> IRB(CtorFunc->getEntryBlock().getTerminator());
-
- if (ClGlobals) Changed |= InstrumentGlobals(IRB, M);
+ // TODO(glider): temporarily disabled globals instrumentation for KASan.
+ if (ClGlobals && !CompileKernel) {
+ Function *CtorFunc = M.getFunction(kAsanModuleCtorName);
+ assert(CtorFunc);
+ IRBuilder<> IRB(CtorFunc->getEntryBlock().getTerminator());
+ Changed |= InstrumentGlobals(IRB, M);
+ }
return Changed;
}
@@ -1366,38 +1380,44 @@ void AddressSanitizer::initializeCallbacks(Module &M) {
for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
const std::string TypeStr = AccessIsWrite ? "store" : "load";
const std::string ExpStr = Exp ? "exp_" : "";
+ const std::string SuffixStr = CompileKernel ? "N" : "_n";
+ const std::string EndingStr = CompileKernel ? "_noabort" : "";
const Type *ExpType = Exp ? Type::getInt32Ty(*C) : nullptr;
+ // TODO(glider): for KASan builds add _noabort to error reporting
+ // functions and make them actually noabort (remove the UnreachableInst).
AsanErrorCallbackSized[AccessIsWrite][Exp] =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- kAsanReportErrorTemplate + ExpStr + TypeStr + "_n",
+ kAsanReportErrorTemplate + ExpStr + TypeStr + SuffixStr,
IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr));
AsanMemoryAccessCallbackSized[AccessIsWrite][Exp] =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- ClMemoryAccessCallbackPrefix + ExpStr + TypeStr + "N",
+ ClMemoryAccessCallbackPrefix + ExpStr + TypeStr + "N" + EndingStr,
IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr));
for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
AccessSizeIndex++) {
const std::string Suffix = TypeStr + itostr(1 << AccessSizeIndex);
AsanErrorCallback[AccessIsWrite][Exp][AccessSizeIndex] =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- kAsanReportErrorTemplate + ExpStr + Suffix, IRB.getVoidTy(),
- IntptrTy, ExpType, nullptr));
+ kAsanReportErrorTemplate + ExpStr + Suffix,
+ IRB.getVoidTy(), IntptrTy, ExpType, nullptr));
AsanMemoryAccessCallback[AccessIsWrite][Exp][AccessSizeIndex] =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- ClMemoryAccessCallbackPrefix + ExpStr + Suffix, IRB.getVoidTy(),
- IntptrTy, ExpType, nullptr));
+ ClMemoryAccessCallbackPrefix + ExpStr + Suffix + EndingStr,
+ IRB.getVoidTy(), IntptrTy, ExpType, nullptr));
}
}
}
+ const std::string MemIntrinCallbackPrefix =
+ CompileKernel ? std::string("") : ClMemoryAccessCallbackPrefix;
AsanMemmove = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
+ MemIntrinCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy, nullptr));
AsanMemcpy = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- ClMemoryAccessCallbackPrefix + "memcpy", IRB.getInt8PtrTy(),
+ MemIntrinCallbackPrefix + "memcpy", IRB.getInt8PtrTy(),
IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy, nullptr));
AsanMemset = checkSanitizerInterfaceFunction(M.getOrInsertFunction(
- ClMemoryAccessCallbackPrefix + "memset", IRB.getInt8PtrTy(),
+ MemIntrinCallbackPrefix + "memset", IRB.getInt8PtrTy(),
IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy, nullptr));
AsanHandleNoReturnFunc = checkSanitizerInterfaceFunction(
@@ -1424,14 +1444,14 @@ bool AddressSanitizer::doInitialization(Module &M) {
IntptrTy = Type::getIntNTy(*C, LongSize);
TargetTriple = Triple(M.getTargetTriple());
- std::tie(AsanCtorFunction, AsanInitFunction) =
- createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName, kAsanInitName,
- /*InitArgTypes=*/{},
- /*InitArgs=*/{});
-
- Mapping = getShadowMapping(TargetTriple, LongSize);
-
- appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority);
+ if (!CompileKernel) {
+ std::tie(AsanCtorFunction, AsanInitFunction) =
+ createSanitizerCtorAndInitFunctions(M, kAsanModuleCtorName, kAsanInitName,
+ /*InitArgTypes=*/{},
+ /*InitArgs=*/{});
+ appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority);
+ }
+ Mapping = getShadowMapping(TargetTriple, LongSize, CompileKernel);
return true;
}
@@ -1513,11 +1533,10 @@ bool AddressSanitizer::runOnFunction(Function &F) {
}
}
- bool UseCalls = false;
- if (ClInstrumentationWithCallsThreshold >= 0 &&
- ToInstrument.size() > (unsigned)ClInstrumentationWithCallsThreshold)
- UseCalls = true;
-
+ bool UseCalls =
+ CompileKernel ||
+ (ClInstrumentationWithCallsThreshold >= 0 &&
+ ToInstrument.size() > (unsigned)ClInstrumentationWithCallsThreshold);
const TargetLibraryInfo *TLI =
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
const DataLayout &DL = F.getParent()->getDataLayout();
@@ -1732,8 +1751,8 @@ void FunctionStackPoisoner::poisonStack() {
ComputeASanStackFrameLayout(SVD, 1UL << Mapping.Scale, MinHeaderSize, &L);
DEBUG(dbgs() << L.DescriptionString << " --- " << L.FrameSize << "\n");
uint64_t LocalStackSize = L.FrameSize;
- bool DoStackMalloc =
- ClUseAfterReturn && LocalStackSize <= kMaxStackMallocSize;
+ bool DoStackMalloc = ClUseAfterReturn && !ASan.CompileKernel &&
+ LocalStackSize <= kMaxStackMallocSize;
// Don't do dynamic alloca in presence of inline asm: too often it makes
// assumptions on which registers are available. Don't do stack malloc in the
// presence of inline asm on 32-bit platforms for the same reason.
OpenPOWER on IntegriCloud