]> granicus.if.org Git - clang/commitdiff
[Sanitizer] Introduce SanitizerMetadata class.
authorAlexey Samsonov <vonosmas@gmail.com>
Fri, 1 Aug 2014 21:35:28 +0000 (21:35 +0000)
committerAlexey Samsonov <vonosmas@gmail.com>
Fri, 1 Aug 2014 21:35:28 +0000 (21:35 +0000)
It is responsible for generating metadata consumed by sanitizer instrumentation
passes in the backend. Move several methods from CodeGenModule to SanitizerMetadata.
For now the class is stateless, but soon it won't be the case.

Instead of creating globals providing source-level information to ASan, we will create
metadata nodes/strings which will be turned into actual global variables in the
backend (if needed).

No functionality change.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214564 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CMakeLists.txt
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/SanitizerMetadata.cpp [new file with mode: 0644]
lib/CodeGen/SanitizerMetadata.h [new file with mode: 0644]

index b42a44342c45717ca8f8c45a346bcde9d0d0f437..7caa4b241e33e6bb77a5d9bad4ed3c3678f983ab 100644 (file)
@@ -345,7 +345,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
   DMEntry = castedAddr;
   CGM.setStaticLocalDeclAddress(&D, castedAddr);
 
-  CGM.reportGlobalToASan(var, D);
+  CGM.getSanitizerMetadata()->reportGlobalToASan(var, D);
 
   // Emit global variable debug descriptor for static vars.
   CGDebugInfo *DI = getDebugInfo();
index 512b323ba1091be10e21c7092f72dcba67118138..c83cc0ad970e64ca728ef16df7af442188d21f0e 100644 (file)
@@ -2127,7 +2127,7 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
       CGM.getModule(), Descriptor->getType(),
       /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, Descriptor);
   GV->setUnnamedAddr(true);
-  CGM.disableSanitizerForGlobal(GV);
+  CGM.getSanitizerMetadata()->disableSanitizerForGlobal(GV);
 
   // Remember the descriptor for this type.
   CGM.setTypeDescriptorInMap(T, GV);
@@ -2177,7 +2177,7 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
   PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc);
   if (PLoc.isValid()) {
     auto FilenameGV = CGM.GetAddrOfConstantCString(PLoc.getFilename(), ".src");
-    CGM.disableSanitizerForGlobal(FilenameGV);
+    CGM.getSanitizerMetadata()->disableSanitizerForGlobal(FilenameGV);
     Filename = FilenameGV;
     Line = PLoc.getLine();
     Column = PLoc.getColumn();
@@ -2224,7 +2224,7 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
       new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
                                llvm::GlobalVariable::PrivateLinkage, Info);
   InfoPtr->setUnnamedAddr(true);
-  CGM.disableSanitizerForGlobal(InfoPtr);
+  CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
 
   SmallVector<llvm::Value *, 4> Args;
   SmallVector<llvm::Type *, 4> ArgTypes;
index 00a87d87a2908a3d9cc6ed6296077b56b52d8a11..1adba48aada99b0c36b8a999c3338210c09afe72 100644 (file)
@@ -61,6 +61,7 @@ add_clang_library(clangCodeGen
   MicrosoftCXXABI.cpp
   ModuleBuilder.cpp
   SanitizerBlacklist.cpp
+  SanitizerMetadata.cpp
   TargetInfo.cpp
 
   DEPENDS
index 55d47060ff932940cc6ac243098c50002b3bb00e..33325b24e5a20c7d5d7e1311d07ad25579fe90d6 100644 (file)
@@ -88,7 +88,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
       BlockObjectDispose(nullptr), BlockDescriptorType(nullptr),
       GenericBlockLiteralType(nullptr), LifetimeStartFn(nullptr),
       LifetimeEndFn(nullptr), SanitizerBL(llvm::SpecialCaseList::createOrDie(
-                                  CGO.SanitizerBlacklistFile)) {
+                                  CGO.SanitizerBlacklistFile)),
+      SanitizerMD(new SanitizerMetadata(*this)) {
 
   // Initialize the type cache.
   llvm::LLVMContext &LLVMContext = M.getContext();
@@ -1933,7 +1934,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
   if (NeedsGlobalCtor || NeedsGlobalDtor)
     EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
 
-  reportGlobalToASan(GV, *D, NeedsGlobalCtor);
+  SanitizerMD->reportGlobalToASan(GV, *D, NeedsGlobalCtor);
 
   // Emit global variable debug information.
   if (CGDebugInfo *DI = getModuleDebugInfo())
@@ -1941,72 +1942,6 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
       DI->EmitGlobalVariable(GV, D);
 }
 
-void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV,
-                                       SourceLocation Loc, StringRef Name,
-                                       bool IsDynInit, bool IsBlacklisted) {
-  if (!LangOpts.Sanitize.Address)
-    return;
-  IsDynInit &= !SanitizerBL.isIn(*GV, "init");
-  IsBlacklisted |= SanitizerBL.isIn(*GV);
-
-  llvm::GlobalVariable *LocDescr = nullptr;
-  llvm::GlobalVariable *GlobalName = nullptr;
-  if (!IsBlacklisted) {
-    // Don't generate source location and global name if it is blacklisted -
-    // it won't be instrumented anyway.
-    PresumedLoc PLoc = Context.getSourceManager().getPresumedLoc(Loc);
-    if (PLoc.isValid()) {
-      llvm::Constant *LocData[] = {
-          GetAddrOfConstantCString(PLoc.getFilename()),
-          llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
-                                 PLoc.getLine()),
-          llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
-                                 PLoc.getColumn()),
-      };
-      auto LocStruct = llvm::ConstantStruct::getAnon(LocData);
-      LocDescr = new llvm::GlobalVariable(TheModule, LocStruct->getType(), true,
-                                          llvm::GlobalValue::PrivateLinkage,
-                                          LocStruct, ".asan_loc_descr");
-      LocDescr->setUnnamedAddr(true);
-      // Add LocDescr to llvm.compiler.used, so that it won't be removed by
-      // the optimizer before the ASan instrumentation pass.
-      addCompilerUsedGlobal(LocDescr);
-    }
-    if (!Name.empty()) {
-      GlobalName = GetAddrOfConstantCString(Name);
-      // GlobalName shouldn't be removed by the optimizer.
-      addCompilerUsedGlobal(GlobalName);
-    }
-  }
-
-  llvm::Value *GlobalMetadata[] = {
-      GV, LocDescr, GlobalName,
-      llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit),
-      llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsBlacklisted)};
-
-  llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
-  llvm::NamedMDNode *AsanGlobals =
-      TheModule.getOrInsertNamedMetadata("llvm.asan.globals");
-  AsanGlobals->addOperand(ThisGlobal);
-}
-
-void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV,
-                                       const VarDecl &D, bool IsDynInit) {
-  if (!LangOpts.Sanitize.Address)
-    return;
-  std::string QualName;
-  llvm::raw_string_ostream OS(QualName);
-  D.printQualifiedName(OS);
-  reportGlobalToASan(GV, D.getLocation(), OS.str(), IsDynInit);
-}
-
-void CodeGenModule::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
-  // For now, just make sure the global is not modified by the ASan
-  // instrumentation.
-  if (LangOpts.Sanitize.Address)
-    reportGlobalToASan(GV, SourceLocation(), "", false, true);
-}
-
 static bool isVarDeclStrongDefinition(const VarDecl *D, bool NoCommon) {
   // Don't give variables common linkage if -fno-common was specified unless it
   // was overridden by a NoCommon attribute.
@@ -2800,7 +2735,7 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
   if (Entry)
     *Entry = GV;
 
-  reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>");
+  SanitizerMD->reportGlobalToASan(GV, S->getStrTokenLoc(0), "<string literal>");
   return GV;
 }
 
index 9533a8dabb205ad82af810f6debf42f5d9b76b07..326e4c7a290bc3aba90022a1667d472e5bfa3d29 100644 (file)
@@ -17,6 +17,7 @@
 #include "CGVTables.h"
 #include "CodeGenTypes.h"
 #include "SanitizerBlacklist.h"
+#include "SanitizerMetadata.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
@@ -473,6 +474,8 @@ class CodeGenModule : public CodeGenTypeCache {
 
   SanitizerBlacklist SanitizerBL;
 
+  std::unique_ptr<SanitizerMetadata> SanitizerMD;
+
   /// @}
 public:
   CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
@@ -1013,14 +1016,9 @@ public:
     return SanitizerBL;
   }
 
-  void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D,
-                          bool IsDynInit = false);
-  void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc,
-                          StringRef Name, bool IsDynInit = false,
-                          bool IsBlacklisted = false);
-
-  /// Disable sanitizer instrumentation for this global.
-  void disableSanitizerForGlobal(llvm::GlobalVariable *GV);
+  SanitizerMetadata *getSanitizerMetadata() {
+    return SanitizerMD.get();
+  }
 
   void addDeferredVTable(const CXXRecordDecl *RD) {
     DeferredVTables.push_back(RD);
diff --git a/lib/CodeGen/SanitizerMetadata.cpp b/lib/CodeGen/SanitizerMetadata.cpp
new file mode 100644 (file)
index 0000000..4619152
--- /dev/null
@@ -0,0 +1,88 @@
+//===--- SanitizerMetadata.cpp - Blacklist for sanitizers -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Class which emits metadata consumed by sanitizer instrumentation passes.
+//
+//===----------------------------------------------------------------------===//
+#include "SanitizerMetadata.h"
+#include "CodeGenModule.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Constants.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
+
+void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
+                                           SourceLocation Loc, StringRef Name,
+                                           bool IsDynInit, bool IsBlacklisted) {
+  if (!CGM.getLangOpts().Sanitize.Address)
+    return;
+  IsDynInit &= !CGM.getSanitizerBlacklist().isIn(*GV, "init");
+  IsBlacklisted |= CGM.getSanitizerBlacklist().isIn(*GV);
+
+  llvm::GlobalVariable *LocDescr = nullptr;
+  llvm::GlobalVariable *GlobalName = nullptr;
+  llvm::LLVMContext &VMContext = CGM.getLLVMContext();
+  if (!IsBlacklisted) {
+    // Don't generate source location and global name if it is blacklisted -
+    // it won't be instrumented anyway.
+    PresumedLoc PLoc = CGM.getContext().getSourceManager().getPresumedLoc(Loc);
+    if (PLoc.isValid()) {
+      llvm::Constant *LocData[] = {
+          CGM.GetAddrOfConstantCString(PLoc.getFilename()),
+          llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
+                                 PLoc.getLine()),
+          llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
+                                 PLoc.getColumn()),
+      };
+      auto LocStruct = llvm::ConstantStruct::getAnon(LocData);
+      LocDescr = new llvm::GlobalVariable(
+          CGM.getModule(), LocStruct->getType(), true,
+          llvm::GlobalValue::PrivateLinkage, LocStruct, ".asan_loc_descr");
+      LocDescr->setUnnamedAddr(true);
+      // Add LocDescr to llvm.compiler.used, so that it won't be removed by
+      // the optimizer before the ASan instrumentation pass.
+      CGM.addCompilerUsedGlobal(LocDescr);
+    }
+    if (!Name.empty()) {
+      GlobalName = CGM.GetAddrOfConstantCString(Name);
+      // GlobalName shouldn't be removed by the optimizer.
+      CGM.addCompilerUsedGlobal(GlobalName);
+    }
+  }
+
+  llvm::Value *GlobalMetadata[] = {
+      GV, LocDescr, GlobalName,
+      llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit),
+      llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsBlacklisted)};
+
+  llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
+  llvm::NamedMDNode *AsanGlobals =
+      CGM.getModule().getOrInsertNamedMetadata("llvm.asan.globals");
+  AsanGlobals->addOperand(ThisGlobal);
+}
+
+void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
+                                           const VarDecl &D, bool IsDynInit) {
+  if (!CGM.getLangOpts().Sanitize.Address)
+    return;
+  std::string QualName;
+  llvm::raw_string_ostream OS(QualName);
+  D.printQualifiedName(OS);
+  reportGlobalToASan(GV, D.getLocation(), OS.str(), IsDynInit);
+}
+
+void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
+  // For now, just make sure the global is not modified by the ASan
+  // instrumentation.
+  if (CGM.getLangOpts().Sanitize.Address)
+    reportGlobalToASan(GV, SourceLocation(), "", false, true);
+}
diff --git a/lib/CodeGen/SanitizerMetadata.h b/lib/CodeGen/SanitizerMetadata.h
new file mode 100644 (file)
index 0000000..3062b4a
--- /dev/null
@@ -0,0 +1,47 @@
+//===--- SanitizerMetadata.h - Metadata for sanitizers ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Class which emits metadata consumed by sanitizer instrumentation passes.
+//
+//===----------------------------------------------------------------------===//
+#ifndef CLANG_CODEGEN_SANITIZERMETADATA_H
+#define CLANG_CODEGEN_SANITIZERMETADATA_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace llvm {
+class GlobalVariable;
+}
+
+namespace clang {
+class VarDecl;
+
+namespace CodeGen {
+
+class CodeGenModule;
+
+class SanitizerMetadata {
+  SanitizerMetadata(const SanitizerMetadata &) LLVM_DELETED_FUNCTION;
+  void operator=(const SanitizerMetadata &) LLVM_DELETED_FUNCTION;
+
+  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, bool IsDynInit = false,
+                          bool IsBlacklisted = false);
+  void disableSanitizerForGlobal(llvm::GlobalVariable *GV);
+};
+}  // end namespace CodeGen
+}  // end namespace clang
+
+#endif