forked from OSchip/llvm-project
[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
This commit is contained in:
parent
0466c7ce23
commit
ba6ca87ffb
|
@ -34,10 +34,12 @@ template <class PtrType> class SmallPtrSetImpl;
|
||||||
/// This wraps the function in the appropriate structure and stores it along
|
/// This wraps the function in the appropriate structure and stores it along
|
||||||
/// side other global constructors. For details see
|
/// side other global constructors. For details see
|
||||||
/// http://llvm.org/docs/LangRef.html#intg_global_ctors
|
/// 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.
|
/// 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
|
/// \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.
|
/// the initializer elements of that global in Set and return the global itself.
|
||||||
|
|
|
@ -540,8 +540,10 @@ bool MemorySanitizer::doInitialization(Module &M) {
|
||||||
createSanitizerCtorAndInitFunctions(M, kMsanModuleCtorName, kMsanInitName,
|
createSanitizerCtorAndInitFunctions(M, kMsanModuleCtorName, kMsanInitName,
|
||||||
/*InitArgTypes=*/{},
|
/*InitArgTypes=*/{},
|
||||||
/*InitArgs=*/{});
|
/*InitArgs=*/{});
|
||||||
|
Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);
|
||||||
|
MsanCtorFunction->setComdat(MsanCtorComdat);
|
||||||
|
|
||||||
appendToGlobalCtors(M, MsanCtorFunction, 0);
|
appendToGlobalCtors(M, MsanCtorFunction, 0, MsanCtorFunction);
|
||||||
|
|
||||||
if (TrackOrigins)
|
if (TrackOrigins)
|
||||||
new GlobalVariable(M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
|
new GlobalVariable(M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static void appendToGlobalArray(const char *Array,
|
static void appendToGlobalArray(const char *Array, Module &M, Function *F,
|
||||||
Module &M, Function *F, int Priority) {
|
int Priority, Constant *Data) {
|
||||||
IRBuilder<> IRB(M.getContext());
|
IRBuilder<> IRB(M.getContext());
|
||||||
FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
|
FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
|
||||||
|
|
||||||
|
@ -31,15 +31,26 @@ static void appendToGlobalArray(const char *Array,
|
||||||
SmallVector<Constant *, 16> CurrentCtors;
|
SmallVector<Constant *, 16> CurrentCtors;
|
||||||
StructType *EltTy;
|
StructType *EltTy;
|
||||||
if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) {
|
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());
|
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()) {
|
if (Constant *Init = GVCtor->getInitializer()) {
|
||||||
unsigned n = Init->getNumOperands();
|
unsigned n = Init->getNumOperands();
|
||||||
CurrentCtors.reserve(n + 1);
|
CurrentCtors.reserve(n + 1);
|
||||||
for (unsigned i = 0; i != n; ++i)
|
for (unsigned i = 0; i != n; ++i) {
|
||||||
CurrentCtors.push_back(cast<Constant>(Init->getOperand(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();
|
GVCtor->eraseFromParent();
|
||||||
} else {
|
} else {
|
||||||
|
@ -54,7 +65,8 @@ static void appendToGlobalArray(const char *Array,
|
||||||
CSVals[1] = F;
|
CSVals[1] = F;
|
||||||
// FIXME: Drop support for the two element form in LLVM 4.0.
|
// FIXME: Drop support for the two element form in LLVM 4.0.
|
||||||
if (EltTy->getNumElements() >= 3)
|
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 =
|
Constant *RuntimeCtorInit =
|
||||||
ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements()));
|
ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements()));
|
||||||
|
|
||||||
|
@ -70,12 +82,12 @@ static void appendToGlobalArray(const char *Array,
|
||||||
GlobalValue::AppendingLinkage, NewInit, Array);
|
GlobalValue::AppendingLinkage, NewInit, Array);
|
||||||
}
|
}
|
||||||
|
|
||||||
void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority) {
|
void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) {
|
||||||
appendToGlobalArray("llvm.global_ctors", M, F, Priority);
|
appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority) {
|
void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) {
|
||||||
appendToGlobalArray("llvm.global_dtors", M, F, Priority);
|
appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalVariable *
|
GlobalVariable *
|
||||||
|
@ -132,4 +144,3 @@ std::pair<Function *, Function *> llvm::createSanitizerCtorAndInitFunctions(
|
||||||
}
|
}
|
||||||
return std::make_pair(Ctor, InitFunction);
|
return std::make_pair(Ctor, InitFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
|
@ -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 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"
|
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
|
; Check the presence and the linkage type of __msan_track_origins and
|
||||||
; other interface symbols.
|
; other interface symbols.
|
||||||
|
@ -981,5 +982,5 @@ define i8* @MismatchingCallMustTailCall(i32 %a) sanitize_memory {
|
||||||
; CHECK-NEXT: ret i8*
|
; 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()
|
; CHECK: call void @__msan_init()
|
||||||
|
|
Loading…
Reference in New Issue