Index: include/llvm/Transforms/Utils/ModuleUtils.h =================================================================== --- include/llvm/Transforms/Utils/ModuleUtils.h +++ include/llvm/Transforms/Utils/ModuleUtils.h @@ -53,7 +53,8 @@ std::pair createSanitizerCtorAndInitFunctions( Module &M, StringRef CtorName, StringRef InitName, ArrayRef InitArgTypes, ArrayRef InitArgs, - StringRef VersionCheckName = StringRef()); + StringRef VersionCheckName = StringRef(), + bool PassArgcArgvEnvp = false); /// Rename all the anon functions in the module using a hash computed from /// the list of public globals in the module. Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1712,10 +1712,12 @@ TargetTriple = Triple(M.getTargetTriple()); if (!CompileKernel) { + Triple TargetTriple(M.getTargetTriple()); + bool WithArgcArgvEnvp = TargetTriple.isOSLinux(); std::tie(AsanCtorFunction, AsanInitFunction) = createSanitizerCtorAndInitFunctions( M, kAsanModuleCtorName, kAsanInitName, - /*InitArgTypes=*/{}, /*InitArgs=*/{}, kAsanVersionCheckName); + /*InitArgTypes=*/{}, /*InitArgs=*/{}, kAsanVersionCheckName, WithArgcArgvEnvp); appendToGlobalCtors(M, AsanCtorFunction, kAsanCtorAndDtorPriority); } Mapping = getShadowMapping(TargetTriple, LongSize, CompileKernel); Index: lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- lib/Transforms/Utils/ModuleUtils.cpp +++ lib/Transforms/Utils/ModuleUtils.cpp @@ -24,6 +24,7 @@ int Priority, Constant *Data) { IRBuilder<> IRB(M.getContext()); FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); + Constant *FnPtr = ConstantExpr::getPointerCast(F, FnTy->getPointerTo()); // Get the current set of static global constructors and add the new ctor // to the list. @@ -61,7 +62,7 @@ // Build a 2 or 3 field global_ctor entry. We don't take a comdat key. Constant *CSVals[3]; CSVals[0] = IRB.getInt32(Priority); - CSVals[1] = F; + CSVals[1] = FnPtr; // FIXME: Drop support for the two element form in LLVM 4.0. if (EltTy->getNumElements() >= 3) CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy()) @@ -102,21 +103,41 @@ std::pair llvm::createSanitizerCtorAndInitFunctions( Module &M, StringRef CtorName, StringRef InitName, ArrayRef InitArgTypes, ArrayRef InitArgs, - StringRef VersionCheckName) { + StringRef VersionCheckName, bool PassArgcArgvEnvp) { assert(!InitName.empty() && "Expected init function name"); assert(InitArgTypes.size() == InitArgTypes.size() && "Sanitizer's init function expects different number of arguments"); - Function *Ctor = Function::Create( - FunctionType::get(Type::getVoidTy(M.getContext()), false), - GlobalValue::InternalLinkage, CtorName, &M); + LLVMContext &C = M.getContext(); + Type *VoidTy = Type::getVoidTy(C); + FunctionType *CtorTy, *InitTy; + if (PassArgcArgvEnvp) { + Type *IntTy = Type::getInt32Ty(C); + Type *CharPtrPtrTy = Type::getInt8Ty(C)->getPointerTo(0)->getPointerTo(0); + SmallVector CtorParamTypes{IntTy, CharPtrPtrTy, CharPtrPtrTy}; + SmallVector InitParamTypes{IntTy, CharPtrPtrTy, CharPtrPtrTy}; + InitParamTypes.append(InitArgTypes.begin(), InitArgTypes.end()); + CtorTy = FunctionType::get(VoidTy, CtorParamTypes, false); + InitTy = FunctionType::get(VoidTy, InitParamTypes, false); + } else { + CtorTy = FunctionType::get(VoidTy, false); + InitTy = FunctionType::get(VoidTy, InitArgTypes, false); + } + Function *Ctor = + Function::Create(CtorTy, GlobalValue::InternalLinkage, CtorName, &M); BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor); IRBuilder<> IRB(ReturnInst::Create(M.getContext(), CtorBB)); - Function *InitFunction = - checkSanitizerInterfaceFunction(M.getOrInsertFunction( - InitName, FunctionType::get(IRB.getVoidTy(), InitArgTypes, false), - AttributeSet())); + Function *InitFunction = checkSanitizerInterfaceFunction( + M.getOrInsertFunction(InitName, InitTy, AttributeSet())); InitFunction->setLinkage(Function::ExternalLinkage); - IRB.CreateCall(InitFunction, InitArgs); + if (PassArgcArgvEnvp) { + SmallVector Args; + for (auto &CtorArg : Ctor->args()) + Args.push_back(&CtorArg); + Args.append(InitArgs.begin(), InitArgs.end()); + IRB.CreateCall(InitFunction, Args); + } else { + IRB.CreateCall(InitFunction, InitArgs); + } if (!VersionCheckName.empty()) { Function *VersionCheckFunction = checkSanitizerInterfaceFunction(M.getOrInsertFunction( Index: test/Instrumentation/AddressSanitizer/basic.ll =================================================================== --- test/Instrumentation/AddressSanitizer/basic.ll +++ test/Instrumentation/AddressSanitizer/basic.ll @@ -4,7 +4,6 @@ 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" target triple = "x86_64-unknown-linux-gnu" -; CHECK: @llvm.global_ctors = {{.*}}@asan.module_ctor define i32 @test_load(i32* %a) sanitize_address { ; CHECK-LABEL: @test_load @@ -170,8 +169,5 @@ ; CHECK: __asan_memcpy ; CHECK: ret void -; CHECK: define internal void @asan.module_ctor() -; CHECK: call void @__asan_init() - ; PROF ; CHECK: ![[PROF]] = !{!"branch_weights", i32 1, i32 100000} Index: test/Instrumentation/AddressSanitizer/ctor.ll =================================================================== --- /dev/null +++ test/Instrumentation/AddressSanitizer/ctor.ll @@ -0,0 +1,12 @@ +; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -asan -asan-module -S | FileCheck %s --check-prefix=CHECK-ARGS +; RUN: opt -mtriple=x86_64-unknown-unknown < %s -asan -asan-module -S | FileCheck %s --check-prefix=CHECK-NO-ARGS +; RUN: opt -mtriple=x86_64-apple-darwin < %s -asan -asan-module -S | FileCheck %s --check-prefix=CHECK-NO-ARGS + +; CHECK-ARGS: @llvm.global_ctors = appending global [{{.*}}void ()* bitcast (void (i32, i8**, i8**)* @asan.module_ctor to void ()* +; CHECK-NO-ARGS: @llvm.global_ctors = appending global [{{.*}}void ()* @asan.module_ctor + +; CHECK-ARGS: define internal void @asan.module_ctor(i32{{.*}}, i8**{{.*}}, i8**{{.*}}) +; CHECK-ARGS: call void @__asan_init(i32{{.*}}, i8**{{.*}}, i8**{{.*}}) + +; CHECK-NO-ARGS: define internal void @asan.module_ctor() +; CHECK-NO-ARGS: call void @__asan_init()