From c2ee6e2169dc2dc3cd6fa4ff868f2c1a2524fe97 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 29 Nov 2016 01:32:21 +0000 Subject: [PATCH] [asan/win] Align global registration metadata to its size 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288096 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/AddressSanitizer.cpp | 15 +++++++++++++-- .../AddressSanitizer/global_metadata_windows.ll | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index db9dd1f8c61..42d3cb68446 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -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 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 diff --git a/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll b/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll index 446b355931e..686b506a96c 100644 --- a/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll +++ b/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll @@ -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 -- 2.50.1