hfinkel updated this revision to Diff 111109.
hfinkel added a comment.
Rebased.
https://reviews.llvm.org/D32199
Files:
include/clang/Basic/Sanitizers.def
include/clang/Driver/SanitizerArgs.h
lib/CodeGen/BackendUtil.cpp
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGDeclCXX.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenTBAA.cpp
lib/CodeGen/SanitizerMetadata.cpp
lib/CodeGen/SanitizerMetadata.h
lib/Driver/SanitizerArgs.cpp
lib/Driver/ToolChains/CommonArgs.cpp
lib/Driver/ToolChains/Linux.cpp
lib/Lex/PPMacroExpansion.cpp
test/CodeGen/sanitize-type-attr.cpp
test/Driver/sanitizer-ld.c
Index: test/Driver/sanitizer-ld.c
===================================================================
--- test/Driver/sanitizer-ld.c
+++ test/Driver/sanitizer-ld.c
@@ -181,6 +181,18 @@
// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux -fuse-ld=ld -stdlib=platform -lstdc++ \
+// RUN: -fsanitize=type \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-TYSAN-LINUX-CXX %s
+//
+// CHECK-TYSAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-TYSAN-LINUX-CXX-NOT: stdc++
+// CHECK-TYSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.tysan-x86_64.a" "-no-whole-archive"
+// CHECK-TYSAN-LINUX-CXX: stdc++
+
+// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fuse-ld=ld -stdlib=platform -lstdc++ \
// RUN: -fsanitize=memory \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
Index: test/CodeGen/sanitize-type-attr.cpp
===================================================================
--- /dev/null
+++ test/CodeGen/sanitize-type-attr.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -fsanitize=type | FileCheck -check-prefix=TYSAN %s
+// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -fsanitize=type -fsanitize-blacklist=%t | FileCheck -check-prefix=BL %s
+
+// The sanitize_type attribute should be attached to functions
+// when TypeSanitizer is enabled, unless no_sanitize("type") attribute
+// is present.
+
+// WITHOUT: NoTYSAN1{{.*}}) [[NOATTR:#[0-9]+]]
+// BL: NoTYSAN1{{.*}}) [[NOATTR:#[0-9]+]]
+// TYSAN: NoTYSAN1{{.*}}) [[NOATTR:#[0-9]+]]
+__attribute__((no_sanitize("type")))
+int NoTYSAN1(int *a) { return *a; }
+
+// WITHOUT: NoTYSAN2{{.*}}) [[NOATTR]]
+// BL: NoTYSAN2{{.*}}) [[NOATTR]]
+// TYSAN: NoTYSAN2{{.*}}) [[NOATTR]]
+__attribute__((no_sanitize("type")))
+int NoTYSAN2(int *a);
+int NoTYSAN2(int *a) { return *a; }
+
+// WITHOUT: NoTYSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// BL: NoTYSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+// TYSAN: NoTYSAN3{{.*}}) [[NOATTR:#[0-9]+]]
+__attribute__((no_sanitize("type")))
+int NoTYSAN3(int *a) { return *a; }
+
+// WITHOUT: TYSANOk{{.*}}) [[NOATTR]]
+// BL: TYSANOk{{.*}}) [[NOATTR]]
+// TYSAN: TYSANOk{{.*}}) [[WITH:#[0-9]+]]
+int TYSANOk(int *a) { return *a; }
+
+// WITHOUT: TemplateTYSANOk{{.*}}) [[NOATTR]]
+// BL: TemplateTYSANOk{{.*}}) [[NOATTR]]
+// TYSAN: TemplateTYSANOk{{.*}}) [[WITH]]
+template<int i>
+int TemplateTYSANOk() { return i; }
+
+// WITHOUT: TemplateNoTYSAN{{.*}}) [[NOATTR]]
+// BL: TemplateNoTYSAN{{.*}}) [[NOATTR]]
+// TYSAN: TemplateNoTYSAN{{.*}}) [[NOATTR]]
+template<int i>
+__attribute__((no_sanitize("type")))
+int TemplateNoTYSAN() { return i; }
+
+int force_instance = TemplateTYSANOk<42>()
+ + TemplateNoTYSAN<42>();
+
+// Check that __cxx_global_var_init* get the sanitize_type attribute.
+int global1 = 0;
+int global2 = *(int*)((char*)&global1+1);
+// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
+// BL: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
+// TYSAN: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]]
+
+// Make sure that we don't add globals to the list for which we don't have a
+// specific type description.
+struct SX { int a, b; };
+SX sx;
+
+// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
+
+// BL: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
+
+// TYSAN: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
+// TYSAN: attributes [[WITH]] = { noinline nounwind sanitize_type{{.*}} }
+
+// TYSAN-DAG: !llvm.tysan.globals = !{[[G1MD:![0-9]+]], [[G2MD:![0-9]+]], [[G3MD:![0-9]+]]}
+// TYSAN-DAG: [[G1MD]] = !{i32* @force_instance, [[INTMD:![0-9]+]]}
+// TYSAN-DAG: [[INTMD]] = !{!"int",
+// TYSAN-DAG: [[G2MD]] = !{i32* @global1, [[INTMD]]}
+// TYSAN-DAG: [[G3MD]] = !{i32* @global2, [[INTMD]]}
+// TYSAN-DAG: Simple C++ TBAA
+
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1138,6 +1138,7 @@
.Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow))
.Case("efficiency_sanitizer",
LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency))
+ .Case("type_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Type))
// Objective-C features
.Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
Index: lib/Driver/ToolChains/Linux.cpp
===================================================================
--- lib/Driver/ToolChains/Linux.cpp
+++ lib/Driver/ToolChains/Linux.cpp
@@ -837,6 +837,8 @@
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch)
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
+ Res |= SanitizerKind::Type;
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
Res |= SanitizerKind::Thread;
if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64)
Res |= SanitizerKind::Memory;
Index: lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- lib/Driver/ToolChains/CommonArgs.cpp
+++ lib/Driver/ToolChains/CommonArgs.cpp
@@ -595,6 +595,8 @@
}
if (SanArgs.needsEsanRt())
StaticRuntimes.push_back("esan");
+ if (SanArgs.needsTysanRt())
+ StaticRuntimes.push_back("tysan");
}
static void addLibFuzzerRuntime(const ToolChain &TC,
Index: lib/Driver/SanitizerArgs.cpp
===================================================================
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -30,9 +30,10 @@
NeedsUbsanCxxRt = Vptr | CFI,
NotAllowedWithTrap = Vptr,
RequiresPIE = DataFlow,
- NeedsUnwindTables = Address | Thread | Memory | DataFlow,
+ NeedsUnwindTables = Address | Thread | Memory | DataFlow | Type,
SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined |
- Integer | Nullability | DataFlow | Fuzzer | FuzzerNoLink,
+ Integer | Nullability | DataFlow | Type |
+ Fuzzer | FuzzerNoLink,
RecoverableByDefault = Undefined | Integer | Nullability,
Unrecoverable = Unreachable | Return,
LegacyFsanitizeRecoverMask = Undefined | Integer,
@@ -103,6 +104,8 @@
BlacklistFile = "cfi_blacklist.txt";
else if (Kinds & Undefined)
BlacklistFile = "ubsan_blacklist.txt";
+ else if (Kinds & Type)
+ BlacklistFile = "tysan_blacklist.txt";
if (BlacklistFile) {
clang::SmallString<64> Path(D.ResourceDir);
@@ -350,7 +353,10 @@
std::make_pair(Efficiency, Leak),
std::make_pair(Efficiency, Thread),
std::make_pair(Efficiency, Memory),
- std::make_pair(Efficiency, KernelAddress)};
+ std::make_pair(Efficiency, KernelAddress),
+ std::make_pair(Type, Address), std::make_pair(Type, KernelAddress),
+ std::make_pair(Type, Memory), std::make_pair(Type, Leak),
+ std::make_pair(Type, Thread), std::make_pair(Type, Efficiency)};
for (auto G : IncompatibleGroups) {
SanitizerMask Group = G.first;
if (Kinds & Group) {
Index: lib/CodeGen/SanitizerMetadata.h
===================================================================
--- lib/CodeGen/SanitizerMetadata.h
+++ lib/CodeGen/SanitizerMetadata.h
@@ -42,6 +42,7 @@
void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc,
StringRef Name, QualType Ty, bool IsDynInit = false,
bool IsBlacklisted = false);
+ void reportGlobalToTySan(llvm::GlobalVariable *GV, const VarDecl &D);
void disableSanitizerForGlobal(llvm::GlobalVariable *GV);
void disableSanitizerForInstruction(llvm::Instruction *I);
private:
Index: lib/CodeGen/SanitizerMetadata.cpp
===================================================================
--- lib/CodeGen/SanitizerMetadata.cpp
+++ lib/CodeGen/SanitizerMetadata.cpp
@@ -72,6 +72,31 @@
IsBlacklisted);
}
+void SanitizerMetadata::reportGlobalToTySan(llvm::GlobalVariable *GV,
+ const VarDecl &D) {
+ if (!CGM.getLangOpts().Sanitize.has(SanitizerKind::Type))
+ return;
+
+ for (auto Attr : D.specific_attrs<NoSanitizeAttr>())
+ if (Attr->getMask() & SanitizerKind::Type)
+ return;
+
+ QualType QTy = D.getType();
+ llvm::MDNode *TBAAInfo = CGM.getTBAAInfo(QTy);
+ if (!TBAAInfo || TBAAInfo == CGM.getTBAAInfo(CGM.getContext().CharTy))
+ return;
+
+ llvm::Metadata *GlobalMetadata[] = {
+ llvm::ConstantAsMetadata::get(GV), TBAAInfo
+ };
+
+ llvm::MDNode *ThisGlobal =
+ llvm::MDNode::get(CGM.getLLVMContext(), GlobalMetadata);
+ llvm::NamedMDNode *TysanGlobals =
+ CGM.getModule().getOrInsertNamedMetadata("llvm.tysan.globals");
+ TysanGlobals->addOperand(ThisGlobal);
+}
+
void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
// For now, just make sure the global is not modified by the ASan
// instrumentation.
Index: lib/CodeGen/CodeGenTBAA.cpp
===================================================================
--- lib/CodeGen/CodeGenTBAA.cpp
+++ lib/CodeGen/CodeGenTBAA.cpp
@@ -90,8 +90,10 @@
llvm::MDNode *
CodeGenTBAA::getTBAAInfo(QualType QTy) {
- // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
- if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
+ // At -O0 or relaxed aliasing, TBAA is not emitted for regular types (unless
+ // we're running TypeSanitizer).
+ if (!Features.Sanitize.has(SanitizerKind::Type) &&
+ (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing))
return nullptr;
// If the type has the may_alias attribute (even on a typedef), it is
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -128,8 +128,9 @@
if (LangOpts.CUDA)
createCUDARuntime();
- // Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
- if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
+ // Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0
+ // (as does TypeSanitizer).
+ if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Thread | SanitizerKind::Type) ||
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
TBAA.reset(new CodeGenTBAA(Context, VMContext, CodeGenOpts, getLangOpts(),
getCXXABI().getMangleContext()));
@@ -2882,6 +2883,7 @@
EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor);
+ SanitizerMD->reportGlobalToTySan(GV, *D);
// Emit global variable debug information.
if (CGDebugInfo *DI = getModuleDebugInfo())
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -785,6 +785,8 @@
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
if (SanOpts.has(SanitizerKind::SafeStack))
Fn->addFnAttr(llvm::Attribute::SafeStack);
+ if (SanOpts.has(SanitizerKind::Type))
+ Fn->addFnAttr(llvm::Attribute::SanitizeType);
// Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
// .cxx_destruct, __destroy_helper_block_ and all of their calees at run time.
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -326,6 +326,8 @@
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack))
Fn->addFnAttr(llvm::Attribute::SafeStack);
+ if (getLangOpts().Sanitize.has(SanitizerKind::Type))
+ Fn->addFnAttr(llvm::Attribute::SanitizeType);
}
return Fn;
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -430,6 +430,7 @@
CGM.setStaticLocalDeclAddress(&D, castedAddr);
CGM.getSanitizerMetadata()->reportGlobalToASan(var, D);
+ CGM.getSanitizerMetadata()->reportGlobalToTySan(var, D);
// Emit global variable debug descriptor for static vars.
CGDebugInfo *DI = getDebugInfo();
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -283,6 +283,11 @@
PM.add(createEfficiencySanitizerPass(Opts));
}
+static void addTypeSanitizerPass(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ PM.add(createTypeSanitizerPass());
+}
+
static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
const CodeGenOptions &CodeGenOpts) {
TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
@@ -581,6 +586,13 @@
addEfficiencySanitizerPass);
}
+ if (LangOpts.Sanitize.has(SanitizerKind::Type)) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addTypeSanitizerPass);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addTypeSanitizerPass);
+ }
+
// Set up the per-function pass manager.
FPM.add(new TargetLibraryInfoWrapperPass(*TLII));
if (CodeGenOpts.VerifyModule)
Index: include/clang/Driver/SanitizerArgs.h
===================================================================
--- include/clang/Driver/SanitizerArgs.h
+++ include/clang/Driver/SanitizerArgs.h
@@ -67,6 +67,7 @@
bool needsEsanRt() const {
return Sanitizers.hasOneOf(SanitizerKind::Efficiency);
}
+ bool needsTysanRt() const { return Sanitizers.has(SanitizerKind::Type); }
bool requiresPIE() const;
bool needsUnwindTables() const;
Index: include/clang/Basic/Sanitizers.def
===================================================================
--- include/clang/Basic/Sanitizers.def
+++ include/clang/Basic/Sanitizers.def
@@ -135,6 +135,9 @@
SANITIZER_GROUP("efficiency-all", Efficiency,
EfficiencyCacheFrag | EfficiencyWorkingSet)
+// TypeSanitizer
+SANITIZER("type", Type)
+
// Magic group, containing all sanitizers. For example, "-fno-sanitize=all"
// can be used to disable all the sanitizers.
SANITIZER_GROUP("all", All, ~0ULL)
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits