hctim created this revision.
hctim added reviewers: vitalybuka, kstoimenov.
Herald added a project: All.
hctim requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
This patch adds generation of sanitizer metadata attributes (which were
added in D126100 <https://reviews.llvm.org/D126100>) to the clang frontend.
We still currently generate the `llvm.asan.globals` that's consumed by
the IR pass, but the plan is to eventually migrate off of that onto
purely debuginfo and these IR attributes.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D126929
Files:
clang/lib/CodeGen/CGDecl.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/SanitizerMetadata.cpp
clang/lib/CodeGen/SanitizerMetadata.h
clang/test/CodeGen/asan-globals.cpp
clang/test/CodeGen/sanitize-init-order.cpp
Index: clang/test/CodeGen/sanitize-init-order.cpp
===================================================================
--- clang/test/CodeGen/sanitize-init-order.cpp
+++ clang/test/CodeGen/sanitize-init-order.cpp
@@ -36,12 +36,29 @@
// Check that ASan init-order checking ignores structs with trivial default
// constructor.
+
+// CHECK: @s1 = global
+// CHECK-NOT: sanitize_address_dyninit
+// CHECK: @s2 = global
+// CHECK-NOT: sanitize_address_dyninit
+// CHECK: @s3 = global {{.*}}, sanitize_address_dyninit
+// CHECK: @{{.*}}array{{.*}} = global {{.*}}, sanitize_address_dyninit
+
// CHECK: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]+]], ![[GLOB_4:[0-9]+]]
// CHECK: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false}
// CHECK: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false}
// CHECK: ![[GLOB_3]] = !{%struct.PODWithCtorAndDtor* {{.*}}, i1 true, i1 false}
// CHECK: ![[GLOB_4]] = !{{{.*}}class.NS::PODWithCtor{{.*}}, i1 true, i1 false}
+// IGNORELIST: @s1 = global
+// IGNORELIST-NOT: sanitize_address_dyninit
+// IGNORELIST: @s2 = global
+// IGNORELIST-NOT: sanitize_address_dyninit
+// IGNORELIST: @s3 = global
+// IGNORELIST-NOT: sanitize_address_dyninit
+// IGNORELIST: @{{.*}}array{{.*}} = global
+// IGNORELIST-NOT: sanitize_address_dyninit
+
// IGNORELIST: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]+]], ![[GLOB_4:[0-9]+]]}
// IGNORELIST: ![[GLOB_1]] = !{%struct.PODStruct* {{.*}}, i1 false, i1 false}
// IGNORELIST: ![[GLOB_2]] = !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false}
Index: clang/test/CodeGen/asan-globals.cpp
===================================================================
--- clang/test/CodeGen/asan-globals.cpp
+++ clang/test/CodeGen/asan-globals.cpp
@@ -23,6 +23,9 @@
const char *literal = "Hello, world!";
}
+// ASAN: @dyn_init_global = global {{.*}}, sanitize_address_dyninit
+// KASAN: @dyn_init_global = global {{.*}}, sanitize_address_dyninit
+
// ASAN: sectioned_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32
// KASAN: sectioned_global{{.*}} global i32
// ASAN: @__special_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32
Index: clang/lib/CodeGen/SanitizerMetadata.h
===================================================================
--- clang/lib/CodeGen/SanitizerMetadata.h
+++ clang/lib/CodeGen/SanitizerMetadata.h
@@ -14,13 +14,15 @@
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/IR/GlobalVariable.h"
+
namespace llvm {
-class GlobalVariable;
class Instruction;
class MDNode;
-}
+} // namespace llvm
namespace clang {
class VarDecl;
@@ -34,19 +36,24 @@
void operator=(const SanitizerMetadata &) = delete;
CodeGenModule &CGM;
+
public:
SanitizerMetadata(CodeGenModule &CGM);
- void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D,
- bool IsDynInit = false);
- void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc,
- StringRef Name, QualType Ty, bool IsDynInit = false,
- bool IsExcluded = false);
+ void reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D,
+ bool IsDynInit = false);
+ void reportGlobal(llvm::GlobalVariable *GV, SourceLocation Loc,
+ StringRef Name, QualType Ty, bool IsDynInit = false,
+ SanitizerMask NoSanitizeMask = {});
void disableSanitizerForGlobal(llvm::GlobalVariable *GV);
void disableSanitizerForInstruction(llvm::Instruction *I);
+
private:
llvm::MDNode *getLocationMetadata(SourceLocation Loc);
+ void setASanSpecificMetadata(llvm::GlobalVariable::SanitizerMetadata &Meta,
+ llvm::GlobalVariable *GV, SourceLocation Loc,
+ QualType Ty, bool IsDynInit = false);
};
-} // end namespace CodeGen
-} // end namespace clang
+} // end namespace CodeGen
+} // end namespace clang
#endif
Index: clang/lib/CodeGen/SanitizerMetadata.cpp
===================================================================
--- clang/lib/CodeGen/SanitizerMetadata.cpp
+++ clang/lib/CodeGen/SanitizerMetadata.cpp
@@ -17,29 +17,86 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Constants.h"
+using GlobalVariable = llvm::GlobalVariable;
+using GVSanitizerMetadata = GlobalVariable::SanitizerMetadata;
+using GlobalSanitizer = GVSanitizerMetadata::GlobalSanitizer;
+
using namespace clang;
using namespace CodeGen;
SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
-static bool isAsanHwasanOrMemTag(const SanitizerSet& SS) {
+static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) {
return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress |
SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress |
SanitizerKind::MemTag);
}
-void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
- SourceLocation Loc, StringRef Name,
- QualType Ty, bool IsDynInit,
- bool IsExcluded) {
- if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
- return;
+void SanitizerMetadata::setASanSpecificMetadata(GVSanitizerMetadata &Meta,
+ GlobalVariable *GV,
+ SourceLocation Loc, QualType Ty,
+ bool IsDynInit) {
IsDynInit &= !CGM.isInNoSanitizeList(GV, Loc, Ty, "init");
- IsExcluded |= CGM.isInNoSanitizeList(GV, Loc, Ty);
+ Meta.IsDynInit = IsDynInit;
+}
+
+void SanitizerMetadata::reportGlobal(GlobalVariable *GV, SourceLocation Loc,
+ StringRef Name, QualType Ty,
+ bool IsDynInit,
+ SanitizerMask NoSanitizeMask) {
+
+ GVSanitizerMetadata Meta;
+ if (GV->hasSanitizerMetadata())
+ Meta = GV->getSanitizerMetadata();
+
+ bool IsExcluded = false;
+ if (CGM.isInNoSanitizeList(GV, Loc, Ty) ||
+ NoSanitizeMask == SanitizerKind::All) {
+ Meta.Sanitizer |= GlobalSanitizer::NoSanitize;
+ IsExcluded = true;
+ }
+
+ auto &SanTarget = CGM.getLangOpts().Sanitize;
+
+ if (!isAsanHwasanOrMemTag(SanTarget))
+ return;
+
+ SanitizerSet NoSanitizeSet;
+ NoSanitizeSet.Mask = NoSanitizeMask;
+
+ llvm::LLVMContext &VMContext = CGM.getLLVMContext();
+
+ if (SanTarget.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress)) {
+ if (NoSanitizeSet.hasOneOf(SanitizerKind::Address |
+ SanitizerKind::KernelAddress) ||
+ Meta.Sanitizer & GlobalSanitizer::NoAddress) {
+ Meta.Sanitizer |= GlobalSanitizer::NoAddress;
+ IsExcluded = true;
+ }
+ setASanSpecificMetadata(Meta, GV, Loc, Ty, IsDynInit);
+ }
+ if (SanTarget.hasOneOf(SanitizerKind::HWAddress |
+ SanitizerKind::KernelHWAddress)) {
+ if (NoSanitizeSet.hasOneOf(SanitizerKind::HWAddress |
+ SanitizerKind::KernelHWAddress) ||
+ Meta.Sanitizer & GlobalSanitizer::NoHWAddress) {
+ Meta.Sanitizer |= GlobalSanitizer::NoHWAddress;
+ IsExcluded = true;
+ }
+ }
+ if (SanTarget.hasOneOf(SanitizerKind::MemTag)) {
+ if (NoSanitizeSet.hasOneOf(SanitizerKind::MemTag) ||
+ Meta.Sanitizer & GlobalSanitizer::NoMemtag) {
+ Meta.Sanitizer |= GlobalSanitizer::NoMemtag;
+ IsExcluded = true;
+ }
+ }
+
+ GV->setSanitizerMetadata(Meta);
llvm::Metadata *LocDescr = nullptr;
llvm::Metadata *GlobalName = nullptr;
- llvm::LLVMContext &VMContext = CGM.getLLVMContext();
if (!IsExcluded) {
// Don't generate source location and global name if it is on
// the NoSanitizeList - it won't be instrumented anyway.
@@ -50,8 +107,8 @@
llvm::Metadata *GlobalMetadata[] = {
llvm::ConstantAsMetadata::get(GV), LocDescr, GlobalName,
- llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit)),
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt1Ty(VMContext), Meta.IsDynInit)),
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
llvm::Type::getInt1Ty(VMContext), IsExcluded))};
@@ -61,29 +118,27 @@
AsanGlobals->addOperand(ThisGlobal);
}
-void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
- const VarDecl &D, bool IsDynInit) {
- if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
- return;
+void SanitizerMetadata::reportGlobal(GlobalVariable *GV, const VarDecl &D,
+ bool IsDynInit) {
+ SanitizerMask NoSanitizeMask;
+ for (auto *Attr : D.specific_attrs<NoSanitizeAttr>()) {
+ NoSanitizeMask |= Attr->getMask();
+ }
+
+ if (D.hasAttr<DisableSanitizerInstrumentationAttr>()) {
+ NoSanitizeMask = SanitizerKind::All;
+ }
+
std::string QualName;
llvm::raw_string_ostream OS(QualName);
D.printQualifiedName(OS);
- bool IsExcluded = false;
- for (auto Attr : D.specific_attrs<NoSanitizeAttr>())
- if (Attr->getMask() & SanitizerKind::Address)
- IsExcluded = true;
- if (D.hasAttr<DisableSanitizerInstrumentationAttr>())
- IsExcluded = true;
- reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit,
- IsExcluded);
+ reportGlobal(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit,
+ NoSanitizeMask);
}
-void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
- // For now, just make sure the global is not modified by the ASan
- // instrumentation.
- if (isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
- reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true);
+void SanitizerMetadata::disableSanitizerForGlobal(GlobalVariable *GV) {
+ reportGlobal(GV, SourceLocation(), "", QualType(), false, SanitizerKind::All);
}
void SanitizerMetadata::disableSanitizerForInstruction(llvm::Instruction *I) {
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -2763,18 +2763,10 @@
bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV,
SourceLocation Loc, QualType Ty,
StringRef Category) const {
- // For now globals can be ignored only in ASan and KASan.
- const SanitizerMask EnabledAsanMask =
- LangOpts.Sanitize.Mask &
- (SanitizerKind::Address | SanitizerKind::KernelAddress |
- SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress |
- SanitizerKind::MemTag);
- if (!EnabledAsanMask)
- return false;
const auto &NoSanitizeL = getContext().getNoSanitizeList();
- if (NoSanitizeL.containsGlobal(EnabledAsanMask, GV->getName(), Category))
+ if (NoSanitizeL.containsGlobal(LangOpts.Sanitize.Mask, GV->getName(), Category))
return true;
- if (NoSanitizeL.containsLocation(EnabledAsanMask, Loc, Category))
+ if (NoSanitizeL.containsLocation(LangOpts.Sanitize.Mask, Loc, Category))
return true;
// Check global type.
if (!Ty.isNull()) {
@@ -2786,7 +2778,7 @@
// Only record types (classes, structs etc.) are ignored.
if (Ty->isRecordType()) {
std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy());
- if (NoSanitizeL.containsType(EnabledAsanMask, TypeStr, Category))
+ if (NoSanitizeL.containsType(LangOpts.Sanitize.Mask, TypeStr, Category))
return true;
}
}
@@ -4792,7 +4784,7 @@
if (NeedsGlobalCtor || NeedsGlobalDtor)
EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
- SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor);
+ SanitizerMD->reportGlobal(GV, *D, NeedsGlobalCtor);
// Emit global variable debug information.
if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -5678,7 +5670,7 @@
if (Entry)
*Entry = GV;
- SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>",
+ SanitizerMD->reportGlobal(GV, S->getStrTokenLoc(0), "<string literal>",
QualType());
return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV),
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -473,7 +473,7 @@
LocalDeclMap.find(&D)->second = Address(castedAddr, elemTy, alignment);
CGM.setStaticLocalDeclAddress(&D, castedAddr);
- CGM.getSanitizerMetadata()->reportGlobalToASan(var, D);
+ CGM.getSanitizerMetadata()->reportGlobal(var, D);
// Emit global variable debug descriptor for static vars.
CGDebugInfo *DI = getDebugInfo();
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits