diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-02-12 00:37:52 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-02-12 00:37:52 +0000 |
commit | ba6ca87ffb280bc274229bac588cfc87242ccd94 (patch) | |
tree | 62f56a4310ff949a0197e2acbf5252526f49dada /llvm | |
parent | 0466c7ce23237cd9bac71884cc5d87d0ceb54359 (diff) | |
download | bcm5719-llvm-ba6ca87ffb280bc274229bac588cfc87242ccd94.tar.gz bcm5719-llvm-ba6ca87ffb280bc274229bac588cfc87242ccd94.zip |
[msan] Put msan constructor in a comdat.
MSan adds a constructor to each translation unit that calls
__msan_init, and does nothing else. The idea is to run __msan_init
before any instrumented code. This results in multiple constructors
and multiple .init_array entries in the final binary, one per
translation unit. This is absolutely unnecessary; one would be
enough.
This change moves the constructors to a comdat group in order to drop
the extra ones.
llvm-svn: 260632
Diffstat (limited to 'llvm')
5 files changed, 51 insertions, 18 deletions
diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h index 0f23d34de5d..1b7180c8617 100644 --- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -34,10 +34,12 @@ template <class PtrType> class SmallPtrSetImpl; /// This wraps the function in the appropriate structure and stores it along /// side other global constructors. For details see /// http://llvm.org/docs/LangRef.html#intg_global_ctors -void appendToGlobalCtors(Module &M, Function *F, int Priority); +void appendToGlobalCtors(Module &M, Function *F, int Priority, + Constant *Data = nullptr); /// Same as appendToGlobalCtors(), but for global dtors. -void appendToGlobalDtors(Module &M, Function *F, int Priority); +void appendToGlobalDtors(Module &M, Function *F, int Priority, + Constant *Data = nullptr); /// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect /// the initializer elements of that global in Set and return the global itself. diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index b26a4b55505..6ebf6e20a4a 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -540,8 +540,10 @@ bool MemorySanitizer::doInitialization(Module &M) { createSanitizerCtorAndInitFunctions(M, kMsanModuleCtorName, kMsanInitName, /*InitArgTypes=*/{}, /*InitArgs=*/{}); + Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName); + MsanCtorFunction->setComdat(MsanCtorComdat); - appendToGlobalCtors(M, MsanCtorFunction, 0); + appendToGlobalCtors(M, MsanCtorFunction, 0, MsanCtorFunction); if (TrackOrigins) new GlobalVariable(M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage, diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp index 040ae963b34..609daad0f29 100644 --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -21,8 +21,8 @@ using namespace llvm; -static void appendToGlobalArray(const char *Array, - Module &M, Function *F, int Priority) { +static void appendToGlobalArray(const char *Array, Module &M, Function *F, + int Priority, Constant *Data) { IRBuilder<> IRB(M.getContext()); FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); @@ -31,15 +31,26 @@ static void appendToGlobalArray(const char *Array, SmallVector<Constant *, 16> CurrentCtors; StructType *EltTy; if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) { - // If there is a global_ctors array, use the existing struct type, which can - // have 2 or 3 fields. ArrayType *ATy = cast<ArrayType>(GVCtor->getValueType()); - EltTy = cast<StructType>(ATy->getElementType()); + StructType *OldEltTy = cast<StructType>(ATy->getElementType()); + // Upgrade a 2-field global array type to the new 3-field format if needed. + if (Data && OldEltTy->getNumElements() < 3) + EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy), + IRB.getInt8PtrTy(), nullptr); + else + EltTy = OldEltTy; if (Constant *Init = GVCtor->getInitializer()) { unsigned n = Init->getNumOperands(); CurrentCtors.reserve(n + 1); - for (unsigned i = 0; i != n; ++i) - CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); + for (unsigned i = 0; i != n; ++i) { + auto Ctor = cast<Constant>(Init->getOperand(i)); + if (EltTy != OldEltTy) + Ctor = ConstantStruct::get( + EltTy, Ctor->getAggregateElement((unsigned)0), + Ctor->getAggregateElement(1), + Constant::getNullValue(IRB.getInt8PtrTy()), nullptr); + CurrentCtors.push_back(Ctor); + } } GVCtor->eraseFromParent(); } else { @@ -54,7 +65,8 @@ static void appendToGlobalArray(const char *Array, CSVals[1] = F; // FIXME: Drop support for the two element form in LLVM 4.0. if (EltTy->getNumElements() >= 3) - CSVals[2] = llvm::Constant::getNullValue(IRB.getInt8PtrTy()); + CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy()) + : Constant::getNullValue(IRB.getInt8PtrTy()); Constant *RuntimeCtorInit = ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements())); @@ -70,12 +82,12 @@ static void appendToGlobalArray(const char *Array, GlobalValue::AppendingLinkage, NewInit, Array); } -void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) { - appendToGlobalArray("llvm.global_ctors", M, F, Priority); +void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) { + appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data); } -void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) { - appendToGlobalArray("llvm.global_dtors", M, F, Priority); +void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) { + appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data); } GlobalVariable * @@ -132,4 +144,3 @@ std::pair<Function *, Function *> llvm::createSanitizerCtorAndInitFunctions( } return std::make_pair(Ctor, InitFunction); } - diff --git a/llvm/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll b/llvm/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll new file mode 100644 index 00000000000..fb4f5c59797 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll @@ -0,0 +1,17 @@ +; MSan converts 2-element global_ctors to 3-element when adding the new entry. +; RUN: opt < %s -msan -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: $msan.module_ctor = comdat any +; CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* null }, { i32, void ()*, i8* } { i32 0, void ()* @msan.module_ctor, i8* bitcast (void ()* @msan.module_ctor to i8*) }] + +@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }] + +define internal void @f() { +entry: + ret void +} + +; CHECK: define internal void @msan.module_ctor() comdat { diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll b/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll index cacc9b749dd..10a56d6c60a 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -4,7 +4,8 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -; CHECK: @llvm.global_ctors {{.*}} @msan.module_ctor +; CHECK: $msan.module_ctor = comdat any +; CHECK: @llvm.global_ctors {{.*}} { i32 0, void ()* @msan.module_ctor, i8* bitcast (void ()* @msan.module_ctor to i8*) } ; Check the presence and the linkage type of __msan_track_origins and ; other interface symbols. @@ -981,5 +982,5 @@ define i8* @MismatchingCallMustTailCall(i32 %a) sanitize_memory { ; CHECK-NEXT: ret i8* -; CHECK-LABEL: define internal void @msan.module_ctor +; CHECK-LABEL: define internal void @msan.module_ctor() comdat { ; CHECK: call void @__msan_init() |