[asan/win] Align global registration metadata to its size
authorReid Kleckner <rnk@google.com>
Tue, 29 Nov 2016 01:32:21 +0000 (01:32 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 29 Nov 2016 01:32:21 +0000 (01:32 +0000)
This way, when the linker adds padding between globals, we can skip over
the zero padding bytes and reliably find the start of the next metadata
global.

llvm-svn: 288096

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
llvm/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll

index db9dd1f..42d3cb6 100644 (file)
@@ -1561,6 +1561,7 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
   size_t n = GlobalsToChange.size();
   if (n == 0) return false;
 
+  auto &DL = M.getDataLayout();
   bool UseComdatMetadata = TargetTriple.isOSBinFormatCOFF();
   bool UseMachOGlobalsSection = ShouldUseMachOGlobalsSection();
   bool UseMetadataArray = !(UseComdatMetadata || UseMachOGlobalsSection);
@@ -1578,6 +1579,10 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
   StructType *GlobalStructTy =
       StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy,
                       IntptrTy, IntptrTy, IntptrTy, nullptr);
+  unsigned SizeOfGlobalStruct = DL.getTypeAllocSize(GlobalStructTy);
+  assert((isPowerOf2_32(SizeOfGlobalStruct) ||
+          !TargetTriple.isOSBinFormatCOFF()) &&
+         "global metadata will not be padded appropriately");
   SmallVector<Constant *, 16> Initializers(UseMetadataArray ? n : 0);
 
   // On recent Mach-O platforms, use a structure which binds the liveness of
@@ -1596,7 +1601,6 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
   GlobalVariable *ModuleName = createPrivateGlobalForString(
       M, M.getModuleIdentifier(), /*AllowMerging*/ false);
 
-  auto &DL = M.getDataLayout();
   for (size_t i = 0; i < n; i++) {
     static const uint64_t kMaxGlobalRedzone = 1 << 18;
     GlobalVariable *G = GlobalsToChange[i];
@@ -1743,7 +1747,14 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
         Initializer, Twine("__asan_global_") +
                              GlobalValue::getRealLinkageName(G->getName()));
     Metadata->setSection(getGlobalMetadataSection());
-    Metadata->setAlignment(1); // Don't leave padding in between.
+
+    // The MSVC linker always inserts padding when linking incrementally. We
+    // cope with that by aligning each struct to its size, which must be a power
+    // of two.
+    if (TargetTriple.isOSBinFormatCOFF())
+      Metadata->setAlignment(SizeOfGlobalStruct);
+    else
+      Metadata->setAlignment(1); // Don't leave padding in between.
 
     // On platforms that support comdats, put the metadata and the
     // instrumented global in the same group. This ensures that the metadata
index 446b355..686b506 100644 (file)
@@ -13,7 +13,7 @@ $mystr = comdat any
 
 ; CHECK: $dead_global = comdat noduplicates
 ; CHECK: @dead_global = local_unnamed_addr global { i32, [60 x i8] } { i32 42, [60 x i8] zeroinitializer }, comdat, align 32
-; CHECK: @__asan_global_dead_global = internal global { {{.*}} }, section ".ASAN$GL", comdat($dead_global), align 1
+; CHECK: @__asan_global_dead_global = internal global { {{.*}} }, section ".ASAN$GL", comdat($dead_global), align 64
 
 @dead_global = local_unnamed_addr global i32 42, align 4
 @mystr = linkonce_odr unnamed_addr constant [5 x i8] c"main\00", comdat, align 1