Hi kcc, rsmith,

ASan init-order checking may print false positives for globals that
have no user-defined ctor, but have non-trivial dtor. Clang *should* emit
initializer for them to register dtor in __cxa_atexit, but the contents of the
global is not touched, and program may safely rely on zero-initialization.

http://llvm-reviews.chandlerc.com/D608

Files:
  lib/CodeGen/CodeGenModule.cpp
  test/CodeGen/sanitize-init-order.cpp

Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1812,22 +1812,31 @@
 
   SetCommonAttributes(D, GV);
 
-  // Emit the initializer function if necessary.
-  if (NeedsGlobalCtor || NeedsGlobalDtor)
-    EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
-
   // If we are compiling with ASan, add metadata indicating dynamically
-  // initialized globals.
+  // initialized globals. Do this before we emit initializer function.
   if (SanOpts.Address && NeedsGlobalCtor) {
-    llvm::Module &M = getModule();
+    // Check if this declaration is not a trivial default constructor.
+    bool IsTrivialDefaultCtor = false;
+    if (const CXXConstructExpr *E =
+        dyn_cast_or_null<CXXConstructExpr>(InitDecl->getInit())) {
+      const CXXConstructorDecl *CD = E->getConstructor();
+      IsTrivialDefaultCtor = (CD->isTrivial() && CD->isDefaultConstructor());
+    }
 
-    llvm::NamedMDNode *DynamicInitializers =
-        
M.getOrInsertNamedMetadata("llvm.asan.dynamically_initialized_globals");
-    llvm::Value *GlobalToAdd[] = { GV };
-    llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalToAdd);
-    DynamicInitializers->addOperand(ThisGlobal);
+    if (!IsTrivialDefaultCtor) {
+      llvm::Module &M = getModule();
+      llvm::NamedMDNode *DynamicInitializers =
+          
M.getOrInsertNamedMetadata("llvm.asan.dynamically_initialized_globals");
+      llvm::Value *GlobalToAdd[] = { GV };
+      llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalToAdd);
+      DynamicInitializers->addOperand(ThisGlobal);
+    }
   }
 
+  // Emit the initializer function if necessary.
+  if (NeedsGlobalCtor || NeedsGlobalDtor)
+    EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
+
   // Emit global variable debug information.
   if (CGDebugInfo *DI = getModuleDebugInfo())
     if (getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo)
Index: test/CodeGen/sanitize-init-order.cpp
===================================================================
--- /dev/null
+++ test/CodeGen/sanitize-init-order.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsanitize=address,init-order -emit-llvm -o - %s | 
FileCheck %s
+
+struct PODStruct {
+  int x;
+};
+PODStruct s1;
+
+struct PODWithDtor {
+  ~PODWithDtor() { }
+  int x;
+};
+PODWithDtor s2;
+
+struct PODWithCtorAndDtor {
+  PODWithCtorAndDtor() { }
+  ~PODWithCtorAndDtor() { }
+  int x;
+};
+PODWithCtorAndDtor s3;
+
+// Check that ASan init-order checking ignores structs with trivial default
+// constructor.
+// CHECK: !llvm.asan.dynamically_initialized_globals = !{[[GLOB:![0-9]+]]}
+// CHECK: [[GLOB]] = metadata !{%struct.PODWithCtorAndDtor
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1812,22 +1812,31 @@
 
   SetCommonAttributes(D, GV);
 
-  // Emit the initializer function if necessary.
-  if (NeedsGlobalCtor || NeedsGlobalDtor)
-    EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
-
   // If we are compiling with ASan, add metadata indicating dynamically
-  // initialized globals.
+  // initialized globals. Do this before we emit initializer function.
   if (SanOpts.Address && NeedsGlobalCtor) {
-    llvm::Module &M = getModule();
+    // Check if this declaration is not a trivial default constructor.
+    bool IsTrivialDefaultCtor = false;
+    if (const CXXConstructExpr *E =
+        dyn_cast_or_null<CXXConstructExpr>(InitDecl->getInit())) {
+      const CXXConstructorDecl *CD = E->getConstructor();
+      IsTrivialDefaultCtor = (CD->isTrivial() && CD->isDefaultConstructor());
+    }
 
-    llvm::NamedMDNode *DynamicInitializers =
-        M.getOrInsertNamedMetadata("llvm.asan.dynamically_initialized_globals");
-    llvm::Value *GlobalToAdd[] = { GV };
-    llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalToAdd);
-    DynamicInitializers->addOperand(ThisGlobal);
+    if (!IsTrivialDefaultCtor) {
+      llvm::Module &M = getModule();
+      llvm::NamedMDNode *DynamicInitializers =
+          M.getOrInsertNamedMetadata("llvm.asan.dynamically_initialized_globals");
+      llvm::Value *GlobalToAdd[] = { GV };
+      llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalToAdd);
+      DynamicInitializers->addOperand(ThisGlobal);
+    }
   }
 
+  // Emit the initializer function if necessary.
+  if (NeedsGlobalCtor || NeedsGlobalDtor)
+    EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
+
   // Emit global variable debug information.
   if (CGDebugInfo *DI = getModuleDebugInfo())
     if (getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo)
Index: test/CodeGen/sanitize-init-order.cpp
===================================================================
--- /dev/null
+++ test/CodeGen/sanitize-init-order.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsanitize=address,init-order -emit-llvm -o - %s | FileCheck %s
+
+struct PODStruct {
+  int x;
+};
+PODStruct s1;
+
+struct PODWithDtor {
+  ~PODWithDtor() { }
+  int x;
+};
+PODWithDtor s2;
+
+struct PODWithCtorAndDtor {
+  PODWithCtorAndDtor() { }
+  ~PODWithCtorAndDtor() { }
+  int x;
+};
+PODWithCtorAndDtor s3;
+
+// Check that ASan init-order checking ignores structs with trivial default
+// constructor.
+// CHECK: !llvm.asan.dynamically_initialized_globals = !{[[GLOB:![0-9]+]]}
+// CHECK: [[GLOB]] = metadata !{%struct.PODWithCtorAndDtor
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to