hctim updated this revision to Diff 434145.
hctim marked 2 inline comments as done.
hctim added a comment.
Herald added subscribers: llvm-commits, ormris, jdoerfert, steven_wu, hiraditya.
Herald added a project: LLVM.

Add TODO() comments from Kirill's notes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126929/new/

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-alias.cpp
  clang/test/CodeGen/asan-globals-odr.cpp
  clang/test/CodeGen/asan-static-odr.cpp
  clang/test/CodeGen/asan-strings.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/AsmParser/LLToken.h
  llvm/include/llvm/IR/GlobalValue.h
  llvm/lib/AsmParser/LLLexer.cpp
  llvm/lib/AsmParser/LLParser.cpp
  llvm/lib/IR/AsmWriter.cpp
  llvm/lib/IR/Globals.cpp

Index: llvm/lib/IR/Globals.cpp
===================================================================
--- llvm/lib/IR/Globals.cpp
+++ llvm/lib/IR/Globals.cpp
@@ -223,7 +223,6 @@
 using GlobalSanitizer = GlobalValue::SanitizerMetadata::GlobalSanitizer;
 const SanitizerMetadata &GlobalValue::getSanitizerMetadata() const {
   assert(hasSanitizerMetadata());
-  assert(getContext().pImpl->GlobalValueSanitizerMetadata.count(this));
   return getContext().pImpl->GlobalValueSanitizerMetadata[this];
 }
 
Index: llvm/lib/IR/AsmWriter.cpp
===================================================================
--- llvm/lib/IR/AsmWriter.cpp
+++ llvm/lib/IR/AsmWriter.cpp
@@ -3542,14 +3542,22 @@
 
   if (GV->hasSanitizerMetadata()) {
     SanitizerMetadata MD = GV->getSanitizerMetadata();
-    if (MD.Sanitizer & SanitizerMetadata::NoSanitize) {
+    if (MD.HasSanitizer(SanitizerMetadata::NoSanitize)) {
       Out << ", no_sanitize";
     } else {
-      if (MD.Sanitizer & SanitizerMetadata::NoAddress)
+      if (MD.HasSanitizer(SanitizerMetadata::Address))
+        Out << ", sanitize_address";
+      if (MD.HasSanitizer(SanitizerMetadata::HWAddress))
+        Out << ", sanitize_hwaddress";
+      if (MD.HasSanitizer(SanitizerMetadata::Memtag))
+        Out << ", sanitize_address";
+      if (MD.HasSanitizer(SanitizerMetadata::NoAddress))
         Out << ", no_sanitize_address";
-      if (MD.Sanitizer & SanitizerMetadata::NoHWAddress)
+      if (MD.HasSanitizer(SanitizerMetadata::NoHWAddress))
         Out << ", no_sanitize_hwaddress";
-      if (MD.IsDynInit)
+      if (MD.HasSanitizer(SanitizerMetadata::NoMemtag))
+        Out << ", no_sanitize_memtag";
+      if (MD.HasSanitizer(GlobalSanitizer::Address) && MD.IsDynInit)
         Out << ", sanitize_address_dyninit";
     }
   }
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -1109,8 +1109,12 @@
 static bool isSanitizer(lltok::Kind Kind) {
   switch (Kind) {
   case lltok::kw_no_sanitize:
+  case lltok::kw_sanitize_address:
   case lltok::kw_no_sanitize_address:
+  case lltok::kw_sanitize_hwaddress:
   case lltok::kw_no_sanitize_hwaddress:
+  case lltok::kw_sanitize_memtag:
+  case lltok::kw_no_sanitize_memtag:
   case lltok::kw_sanitize_address_dyninit:
     return true;
   default:
@@ -1125,15 +1129,32 @@
 
   switch (Lex.getKind()) {
   case lltok::kw_no_sanitize:
-    Meta.Sanitizer |= GlobalSanitizer::NoSanitize;
+    Meta.AddSanitizer(GlobalSanitizer::NoSanitize);
+    break;
+  case lltok::kw_sanitize_address:
+    Meta.AddSanitizer(GlobalSanitizer::Address);
     break;
   case lltok::kw_no_sanitize_address:
-    Meta.Sanitizer |= GlobalSanitizer::NoAddress;
+    Meta.AddSanitizer(GlobalSanitizer::NoAddress);
+    break;
+  case lltok::kw_sanitize_hwaddress:
+    Meta.AddSanitizer(GlobalSanitizer::HWAddress);
     break;
   case lltok::kw_no_sanitize_hwaddress:
-    Meta.Sanitizer |= GlobalSanitizer::NoHWAddress;
+    Meta.AddSanitizer(GlobalSanitizer::NoHWAddress);
+    break;
+  case lltok::kw_sanitize_memtag:
+    Meta.AddSanitizer(GlobalSanitizer::Memtag);
+    break;
+  case lltok::kw_no_sanitize_memtag:
+    Meta.AddSanitizer(GlobalSanitizer::NoMemtag);
     break;
   case lltok::kw_sanitize_address_dyninit:
+    if (!GV->hasSanitizerMetadata() ||
+        !Meta.HasSanitizer(SanitizerMetadata::Address)) {
+      return tokError(
+          "sanitize_address_dyninit must only occur after sanitize_address");
+    }
     Meta.IsDynInit = true;
     break;
   default:
Index: llvm/lib/AsmParser/LLLexer.cpp
===================================================================
--- llvm/lib/AsmParser/LLLexer.cpp
+++ llvm/lib/AsmParser/LLLexer.cpp
@@ -580,11 +580,17 @@
   KEYWORD(prefix);
   KEYWORD(prologue);
 
-  // Sanitizer keywords.
+  // Sanitizer keywords. Some are inherited from Attributes.td. See LLToken.h
+  // for more information.
+#define DEFINED_IN_ATTRIBUTES_TD_NO_OP(var)
   KEYWORD(no_sanitize);
+  DEFINED_IN_ATTRIBUTES_TD_NO_OP(sanitize_address);
   KEYWORD(no_sanitize_address);
-  KEYWORD(no_sanitize_hwaddress);
   KEYWORD(sanitize_address_dyninit);
+  DEFINED_IN_ATTRIBUTES_TD_NO_OP(sanitize_hwaddress);
+  KEYWORD(no_sanitize_hwaddress);
+  DEFINED_IN_ATTRIBUTES_TD_NO_OP(sanitize_memtag);
+  KEYWORD(no_sanitize_memtag);
 
   KEYWORD(ccc);
   KEYWORD(fastcc);
Index: llvm/include/llvm/IR/GlobalValue.h
===================================================================
--- llvm/include/llvm/IR/GlobalValue.h
+++ llvm/include/llvm/IR/GlobalValue.h
@@ -294,35 +294,39 @@
   StringRef getPartition() const;
   void setPartition(StringRef Part);
 
-  // ASan, HWASan and Memtag sanitizers have some instrumentation that applies
-  // specifically to global variables. This instrumentation is implicitly
-  // applied to all global variables when built with -fsanitize=*. What we need
-  // is a way to persist the information that a certain global variable should
-  // *not* have sanitizers applied, which occurs if:
-  //   1. The global variable is in the sanitizer ignore list, or
-  //   2. The global variable is created by the sanitizers itself for internal
-  //      usage, or
-  //   3. The global variable has __attribute__((no_sanitize("..."))) or
-  //      __attribute__((disable_sanitizer_instrumentation)).
-  //
-  // This is important, a some IR passes like GlobalMerge can delete global
-  // variables and replace them with new ones. If the old variables were marked
-  // to be unsanitized, then the new ones should also be.
-  //
-  // In addition, this struct carries around some sanitizer-specific information
-  // that can only be produced by the frontend, like whether a global variable
-  // is dynamically initialized (from a C++ language perspective for ASan, which
-  // uses this information to do ODR checking).
   struct SanitizerMetadata {
     enum GlobalSanitizer : unsigned {
       NoSanitize = 1 << 0,
-      NoAddress = 1 << 1,
-      NoHWAddress = 1 << 2,
-      NoMemtag = 1 << 3,
+      Address = 1 << 1,
+      HWAddress = 1 << 2,
+      Memtag = 1 << 3,
+      NoAddress = 1 << 4,
+      NoHWAddress = 1 << 5,
+      NoMemtag = 1 << 6,
     };
     // Bitset of sanitizer options.
     std::underlying_type<GlobalSanitizer>::type Sanitizer = 0;
 
+    void AddSanitizer(GlobalSanitizer S) { Sanitizer |= S; }
+    void RemoveSanitizer(GlobalSanitizer S) { Sanitizer &= ~S; }
+    bool HasSanitizer(GlobalSanitizer S) const {
+      if (Sanitizer == GlobalSanitizer::NoSanitize)
+        return S == GlobalSanitizer::NoSanitize;
+      switch (S) {
+      case GlobalSanitizer::Address:
+        return (Sanitizer & S) && !(Sanitizer & GlobalSanitizer::NoAddress);
+      case GlobalSanitizer::HWAddress:
+        return (Sanitizer & S) && !(Sanitizer & GlobalSanitizer::NoHWAddress);
+      case GlobalSanitizer::Memtag:
+        return (Sanitizer & S) && !(Sanitizer & GlobalSanitizer::NoMemtag);
+      case GlobalSanitizer::NoSanitize: // clang doesn't see the handling above.
+      case GlobalSanitizer::NoAddress:
+      case GlobalSanitizer::NoHWAddress:
+      case GlobalSanitizer::NoMemtag:
+        return Sanitizer & S;
+      }
+    }
+
     // Metadata specific to ASan.
     bool IsDynInit = false;
   };
Index: llvm/include/llvm/AsmParser/LLToken.h
===================================================================
--- llvm/include/llvm/AsmParser/LLToken.h
+++ llvm/include/llvm/AsmParser/LLToken.h
@@ -425,16 +425,25 @@
   APFloat, // APFloatVal
   APSInt,  // APSInt
 
-// Extra sanitizer attributes that are used for global variables (GV's).
+// Extra sanitizer attributes that are used for global variables (GV's). Some
+// of the attributes are inherited from Attributes.td, but we have some
+// GV-specific additions.
+#define DEFINED_IN_ATTRIBUTES_TD_NO_OP(var)
   // GV's mentioned in -fsanitize-ignorelist=<file>.
   kw_no_sanitize,
+  DEFINED_IN_ATTRIBUTES_TD_NO_OP(kw_sanitize_address)
   // GV's with __attribute__((no_sanitize("address"))).
   kw_no_sanitize_address,
   // GV's where the clang++ frontend (when ASan is used) notes that this is
   // dynamically initialized, and thus needs ODR detection.
   kw_sanitize_address_dyninit,
+  DEFINED_IN_ATTRIBUTES_TD_NO_OP(kw_sanitize_hwaddress)
   // GV's with __attribute__((no_sanitize("hwaddress"))).
   kw_no_sanitize_hwaddress,
+  DEFINED_IN_ATTRIBUTES_TD_NO_OP(kw_sanitize_memtag)
+  // GV's with __attribute__((no_sanitize("memtag"))).
+  kw_no_sanitize_memtag,
+
 };
 } // end namespace lltok
 } // end namespace llvm
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -746,6 +746,10 @@
                          <global | constant> <Type> [<InitializerConstant>]
                          [, section "name"] [, partition "name"]
                          [, comdat [($name)]] [, align <Alignment>]
+                         [, no_sanitize] [, sanitize_address]
+                         [, no_sanitize_address] [, sanitize_hwaddress]
+                         [, no_sanitize_hwaddress] [, sanitize_memtag]
+                         [, no_sanitize_memtag] [, sanitize_address_dyninit]
                          (, !name !N)*
 
 For example, the following defines a global in a numbered address space
@@ -1570,9 +1574,9 @@
     Specify the desired alignment, which must be a power of two, in
     parentheses.
 ``"alloc-family"="FAMILY"``
-    This indicates which "family" an allocator function is part of. To avoid 
-    collisions, the family name should match the mangled name of the primary 
-    allocator function, that is "malloc" for malloc/calloc/realloc/free, 
+    This indicates which "family" an allocator function is part of. To avoid
+    collisions, the family name should match the mangled name of the primary
+    allocator function, that is "malloc" for malloc/calloc/realloc/free,
     "_Znwm" for ``::operator::new`` and ``::operator::delete``, and
     "_ZnwmSt11align_val_t" for aligned ``::operator::new`` and
     ``::operator::delete``. Matching malloc/realloc/free calls within a family
@@ -20461,7 +20465,7 @@
 The '``llvm.vp.fpext``' intrinsic extends the ``value`` from a smaller
 :ref:`floating-point <t_floating>` type to a larger :ref:`floating-point
 <t_floating>` type. The '``llvm.vp.fpext``' cannot be used to make a
-*no-op cast* because it always changes bits. Use ``bitcast`` to make a 
+*no-op cast* because it always changes bits. Use ``bitcast`` to make a
 *no-op cast* for a floating-point cast.
 The conversion is performed on lane positions below the explicit vector length
 and where the vector mask is true.  Masked-off lanes are undefined.
Index: clang/test/CodeGen/asan-strings.c
===================================================================
--- clang/test/CodeGen/asan-strings.c
+++ clang/test/CodeGen/asan-strings.c
@@ -10,8 +10,8 @@
 
 const char *foo(void) { return "asdf"; }
 
-// LINUX: @.str = private unnamed_addr constant [5 x i8] c"asdf\00", align 1
+// LINUX: @.str = private unnamed_addr constant [5 x i8] c"asdf\00", sanitize_address, align 1
 
-// WINDOWS: @"??_C@_04JIHMPGLA@asdf?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i8] c"asdf\00", comdat, align 1
+// WINDOWS: @"??_C@_04JIHMPGLA@asdf?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i8] c"asdf\00", sanitize_address, comdat, align 1
 
-// WINWRITE: @.str = private unnamed_addr global [5 x i8] c"asdf\00", align 1
+// WINWRITE: @.str = private unnamed_addr global [5 x i8] c"asdf\00", sanitize_address, align 1
Index: clang/test/CodeGen/asan-static-odr.cpp
===================================================================
--- clang/test/CodeGen/asan-static-odr.cpp
+++ clang/test/CodeGen/asan-static-odr.cpp
@@ -11,7 +11,7 @@
 
 // CHECK-NOT: __odr_asan_gen
 // CHECK-NOT: private alias
-// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, align 32
+// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, sanitize_address, align 32
 // CHECK: @0 = internal global {{.*}} [[VAR]] to i64), {{.*}}, i64 -1 }]
 // CHECK: call void @__asan_register_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)
 // CHECK: call void @__asan_unregister_globals(i64 ptrtoint ([1 x { i64, i64, i64, i64, i64, i64, i64, i64 }]* @0 to i64), i64 1)
Index: clang/test/CodeGen/asan-globals-odr.cpp
===================================================================
--- clang/test/CodeGen/asan-globals-odr.cpp
+++ clang/test/CodeGen/asan-globals-odr.cpp
@@ -14,7 +14,7 @@
   return global;
 }
 
-// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, align 32
+// CHECK: [[VAR:@.*global.*]] ={{.*}} global { i32, [28 x i8] } zeroinitializer, sanitize_address, align 32
 
 // INDICATOR0-NOT: __odr_asan_gen
 // INDICATOR1: [[ODR:@.*__odr_asan_gen_.*global.*]] = global i8 0, align 1
Index: clang/test/CodeGen/asan-globals-alias.cpp
===================================================================
--- clang/test/CodeGen/asan-globals-alias.cpp
+++ clang/test/CodeGen/asan-globals-alias.cpp
@@ -22,12 +22,12 @@
 struct input_device_id joydev_ids[] = { { {1}, 1234 } }; // KASAN ignored
 extern struct input_device_id __attribute__((alias("joydev_ids"))) __mod_joydev_ids_device_table;
 
-// ASAN: @aliased_global{{.*}} global { i32, [28 x i8] }{{.*}}, align 32
-// ASAN: @aliased_global_2{{.*}} global { i32, [28 x i8] }{{.*}}, align 32
-// ASAN: @joydev_ids{{.*}} global { {{.*}}[56 x i8] zeroinitializer }, align 32
+// ASAN: @aliased_global{{.*}} global { i32, [28 x i8] }{{.*}}, sanitize_address, align 32
+// ASAN: @aliased_global_2{{.*}} global { i32, [28 x i8] }{{.*}}, sanitize_address, align 32
+// ASAN: @joydev_ids{{.*}} global { {{.*}}[56 x i8] zeroinitializer }, sanitize_address, align 32
 // KASAN: @aliased_global{{.*}} global i32
 // KASAN: @aliased_global_2{{.*}} global i32
-// KASAN: @joydev_ids{{.*}} global [1 x {{.*}}i64 1234 }], align 16
+// KASAN: @joydev_ids{{.*}} global [1 x {{.*}}i64 1234 }], sanitize_address, align 16
 
 // Check the aliases exist:
 // CHECK: @__global_alias ={{.*}} alias
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,98 @@
 #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.AddSanitizer(GlobalSanitizer::NoSanitize);
+    IsExcluded = true;
+  }
 
+  auto &SanTarget = CGM.getLangOpts().Sanitize;
+
+  // TODO(hctim): Can be removed when we migrate off of llvm.asan.globals. This
+  // prevents llvm.asan.globals from being emitted for
+  // __attribute__((disable_sanitizer_instrumentation)) and uses of
+  // -fsanitize-ignorelist when a sanitizer isn't enabled.
+  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.HasSanitizer(GlobalSanitizer::NoAddress)) {
+      Meta.AddSanitizer(GlobalSanitizer::NoAddress);
+      IsExcluded = true;
+    } else if (!IsExcluded) {
+      Meta.AddSanitizer(GlobalSanitizer::Address);
+    }
+    setASanSpecificMetadata(Meta, GV, Loc, Ty, IsDynInit);
+  }
+  if (SanTarget.hasOneOf(SanitizerKind::HWAddress |
+                         SanitizerKind::KernelHWAddress)) {
+    if (NoSanitizeSet.hasOneOf(SanitizerKind::HWAddress |
+                               SanitizerKind::KernelHWAddress) ||
+        Meta.HasSanitizer(GlobalSanitizer::NoHWAddress)) {
+      Meta.AddSanitizer(GlobalSanitizer::NoHWAddress);
+      IsExcluded = true;
+    } else if (!IsExcluded) {
+      Meta.AddSanitizer(GlobalSanitizer::HWAddress);
+    }
+  }
+  if (SanTarget.hasOneOf(SanitizerKind::MemTag)) {
+    if (NoSanitizeSet.hasOneOf(SanitizerKind::MemTag) ||
+        Meta.HasSanitizer(GlobalSanitizer::NoMemtag)) {
+      Meta.AddSanitizer(GlobalSanitizer::NoMemtag);
+      IsExcluded = true;
+    } else if (!IsExcluded) {
+      Meta.AddSanitizer(GlobalSanitizer::Memtag);
+    }
+  }
+
+  GV->setSanitizerMetadata(Meta);
+
+  // TODO(hctim): Code below can be removed when we migrate off of
+  // llvm.asan.globals onto the new metadata attributes.
   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 +119,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 +130,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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to