Index: llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -309,15 +309,24 @@ kHwasanInitName, /*InitArgTypes=*/{}, /*InitArgs=*/{}); - appendToGlobalCtors(M, HwasanCtorFunction, 0); - } + Comdat *CtorComdat = M.getOrInsertComdat(kHwasanModuleCtorName); + HwasanCtorFunction->setComdat(CtorComdat); + appendToGlobalCtors(M, HwasanCtorFunction, 0, HwasanCtorFunction); + + // Create a zero-length global in __hwasan_frame so that the linker will + // always create start and stop symbols. + // + // N.B. If we ever start creating associated metadata in this pass this + // global will need to be associated with the ctor. + Type *Int8Arr0Ty = ArrayType::get(Int8Ty, 0); + auto GV = + new GlobalVariable(M, Int8Arr0Ty, /*isConstantGlobal*/ true, + GlobalVariable::PrivateLinkage, + Constant::getNullValue(Int8Arr0Ty), "__hwasan"); + GV->setSection(getFrameSection()); + GV->setComdat(CtorComdat); + appendToCompilerUsed(M, GV); - // Create a call to __hwasan_init_frames. - if (HwasanCtorFunction) { - // Create a dummy frame description for the CTOR function. - // W/o it we would have to create the call to __hwasan_init_frames after - // all functions are instrumented (i.e. need to have a ModulePass). - createFrameGlobal(*HwasanCtorFunction, ""); IRBuilder<> IRBCtor(HwasanCtorFunction->getEntryBlock().getTerminator()); IRBCtor.CreateCall( declareSanitizerInitFunction(M, "__hwasan_init_frames", @@ -742,10 +751,9 @@ GV->setSection(getFrameSection()); appendToCompilerUsed(M, GV); // Put GV into the F's Comadat so that if F is deleted GV can be deleted too. - if (&F != HwasanCtorFunction) - if (auto Comdat = - GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) - GV->setComdat(Comdat); + if (auto Comdat = + GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) + GV->setComdat(Comdat); } Value *HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, Index: llvm/test/Instrumentation/HWAddressSanitizer/basic.ll =================================================================== --- llvm/test/Instrumentation/HWAddressSanitizer/basic.ll +++ llvm/test/Instrumentation/HWAddressSanitizer/basic.ll @@ -5,6 +5,9 @@ ; RUN: opt < %s -hwasan -hwasan-recover=0 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT,ZERO-BASED-SHADOW ; RUN: opt < %s -hwasan -hwasan-recover=1 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,ZERO-BASED-SHADOW +; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @hwasan.module_ctor, i8* bitcast (void ()* @hwasan.module_ctor to i8*) }] +; CHECK: @__hwasan = private constant [0 x i8] zeroinitializer, section "__hwasan_frames", comdat($hwasan.module_ctor) + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64--linux-android" @@ -352,7 +355,7 @@ ; CHECK: declare void @__hwasan_init() -; CHECK: define internal void @hwasan.module_ctor() { +; CHECK: define internal void @hwasan.module_ctor() comdat { ; CHECK-NEXT: call void @__hwasan_init() ; CHECK-NEXT: call void @__hwasan_init_frames( ; CHECK-NEXT: ret void Index: llvm/test/Instrumentation/HWAddressSanitizer/with-calls.ll =================================================================== --- llvm/test/Instrumentation/HWAddressSanitizer/with-calls.ll +++ llvm/test/Instrumentation/HWAddressSanitizer/with-calls.ll @@ -197,7 +197,7 @@ ; CHECK: declare void @__hwasan_init() -; CHECK: define internal void @hwasan.module_ctor() { +; CHECK: define internal void @hwasan.module_ctor() comdat { ; CHECK-NEXT: call void @__hwasan_init() ; CHECK-NEXT: call void @__hwasan_init_frames( ; CHECK-NEXT: ret void