]> granicus.if.org Git - clang/commitdiff
Make sure globals created by UBSan are not instrumented by ASan.
authorAlexey Samsonov <vonosmas@gmail.com>
Fri, 18 Jul 2014 17:50:06 +0000 (17:50 +0000)
committerAlexey Samsonov <vonosmas@gmail.com>
Fri, 18 Jul 2014 17:50:06 +0000 (17:50 +0000)
Summary:
This change adds description of globals created by UBSan
instrumentation (UBSan handlers, type descriptors, filenames) to
llvm.asan.globals metadata, effectively "blacklisting" them. This can
dramatically decrease the data section in binaries built with UBSan+ASan,
as UBSan tends to create a lot of handlers, and ASan instrumentation
increases the global size to at least 64 bytes.

Test Plan: clang regression test suite

Reviewers: rsmith

Reviewed By: rsmith

Subscribers: cfe-commits, byoungyoung, kcc

Differential Revision: http://reviews.llvm.org/D4575

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

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
test/CodeGenCXX/catch-undef-behavior.cpp

index 63731b7b7d06c02bbec9b944ae3da36b87ffa8e5..b08af949b4b7fb0cc9293eb7b1294f5666e18096 100644 (file)
@@ -2127,6 +2127,7 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
       CGM.getModule(), Descriptor->getType(),
       /*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, Descriptor);
   GV->setUnnamedAddr(true);
+  CGM.disableSanitizerForGlobal(GV);
 
   // Remember the descriptor for this type.
   CGM.setTypeDescriptorInMap(T, GV);
@@ -2170,14 +2171,23 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) {
 /// \endcode
 /// For an invalid SourceLocation, the Filename pointer is null.
 llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
+  llvm::Constant *Filename;
+  int Line, Column;
+
   PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc);
+  if (PLoc.isValid()) {
+    auto FilenameGV = CGM.GetAddrOfConstantCString(PLoc.getFilename(), ".src");
+    CGM.disableSanitizerForGlobal(FilenameGV);
+    Filename = FilenameGV;
+    Line = PLoc.getLine();
+    Column = PLoc.getColumn();
+  } else {
+    Filename = llvm::Constant::getNullValue(Int8PtrTy);
+    Line = Column = 0;
+  }
 
-  llvm::Constant *Data[] = {
-    PLoc.isValid() ? CGM.GetAddrOfConstantCString(PLoc.getFilename(), ".src")
-                   : llvm::Constant::getNullValue(Int8PtrTy),
-    Builder.getInt32(PLoc.isValid() ? PLoc.getLine() : 0),
-    Builder.getInt32(PLoc.isValid() ? PLoc.getColumn() : 0)
-  };
+  llvm::Constant *Data[] = {Filename, Builder.getInt32(Line),
+                            Builder.getInt32(Column)};
 
   return llvm::ConstantStruct::getAnon(Data);
 }
@@ -2214,6 +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);
 
   SmallVector<llvm::Value *, 4> Args;
   SmallVector<llvm::Type *, 4> ArgTypes;
index 6c33f9227926cd9814c11b908306fd36983fc762..bd7acf9d1ac76d4e475d71734959e2eba05d1791 100644 (file)
@@ -1951,11 +1951,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
 
 void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV,
                                        SourceLocation Loc, StringRef Name,
-                                       bool IsDynInit) {
+                                       bool IsDynInit, bool IsBlacklisted) {
   if (!LangOpts.Sanitize.Address)
     return;
   IsDynInit &= !SanitizerBL.isIn(*GV, "init");
-  bool IsBlacklisted = SanitizerBL.isIn(*GV);
+  IsBlacklisted |= SanitizerBL.isIn(*GV);
 
   llvm::GlobalVariable *LocDescr = nullptr;
   llvm::GlobalVariable *GlobalName = nullptr;
@@ -2008,6 +2008,13 @@ void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV,
   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.
index d6b694a8824668958ad1da30b59ef8c6b62fc72a..c65598e96df0c6ecefb198cb29f101d5bd7a4229 100644 (file)
@@ -1018,7 +1018,11 @@ public:
   void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D,
                           bool IsDynInit = false);
   void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc,
-                          StringRef Name, bool IsDynInit = false);
+                          StringRef Name, bool IsDynInit = false,
+                          bool IsBlacklisted = false);
+
+  /// Disable sanitizer instrumentation for this global.
+  void disableSanitizerForGlobal(llvm::GlobalVariable *GV);
 
   void addDeferredVTable(const CXXRecordDecl *RD) {
     DeferredVTables.push_back(RD);
index d97893378e27be590113901fb445b839ca0e17fe..f875d9299e9f66baa045dc18bd9f50681f6f7864 100644 (file)
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN
 
 struct S {
   double d;
@@ -6,6 +7,12 @@ struct S {
   virtual int f();
 };
 
+// Check that type descriptor global is not modified by ASan.
+// CHECK-ASAN: [[TYPE_DESCR:@[0-9]+]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'S'\00" }
+
+// Check that type mismatch handler is not modified by ASan.
+// CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* [[TYPE_DESCR]], {{.*}} }
+
 struct T : S {};
 
 // CHECK-LABEL: @_Z17reference_binding
@@ -31,6 +38,7 @@ void reference_binding(int *p, S *q) {
 }
 
 // CHECK-LABEL: @_Z13member_access
+// CHECK-ASAN-LABEL: @_Z13member_access
 void member_access(S *p) {
   // (1a) Check 'p' is appropriately sized and aligned for member access.