Skip to content

Commit 7b78956

Browse files
committed
[sanitizer] Place module_ctor/module_dtor in llvm.used
This removes an abuse of ELF linker behaviors while keeping Mach-O/COFF linker behaviors unchanged. ELF: when module_ctor is in a comdat, this patch removes reliance on a linker abuse (an SHT_INIT_ARRAY in a section group retains the whole group) by using SHF_GNU_RETAIN. No linker behavior difference when module_ctor is not in a comdat. Mach-O: module_ctor gets `N_NO_DEAD_STRIP`. No linker behavior difference because module_ctor is already referenced by a `S_MOD_INIT_FUNC_POINTERS` section (GC root). PE/COFF: no-op. SanitizerCoverage already appends module_ctor to `llvm.used`. Other sanitizers: llvm.used for local linkage is not implemented in `TargetLoweringObjectFileCOFF::emitLinkerDirectives` (once implemented or switched to a non-local linkage, COFF can use module_ctor in comdat (i.e. generalize ELF-specific rL301586)). There is no object file size difference. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D106246
1 parent 7898e7c commit 7b78956

File tree

11 files changed

+18
-8
lines changed

11 files changed

+18
-8
lines changed

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,8 @@ Instruction *ModuleAddressSanitizer::CreateAsanModuleDtor(Module &M) {
21382138
GlobalValue::InternalLinkage, 0, kAsanModuleDtorName, &M);
21392139
AsanDtorFunction->addAttribute(AttributeList::FunctionIndex,
21402140
Attribute::NoUnwind);
2141+
// Ensure Dtor cannot be discarded, even if in a comdat.
2142+
appendToUsed(M, {AsanDtorFunction});
21412143
BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction);
21422144

21432145
return ReturnInst::Create(*C, AsanDtorBB);

llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,6 @@ Function *ModuleSanitizerCoverage::CreateInitCallsForSections(
384384
// to include the sancov constructor. This way the linker can deduplicate
385385
// the constructors but always leave one copy.
386386
CtorFunc->setLinkage(GlobalValue::WeakODRLinkage);
387-
appendToUsed(M, CtorFunc);
388387
}
389388
return CtorFunc;
390389
}

llvm/lib/Transforms/Utils/ModuleUtils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ Function *llvm::createSanitizerCtor(Module &M, StringRef CtorName) {
128128
Ctor->addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
129129
BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor);
130130
ReturnInst::Create(M.getContext(), CtorBB);
131+
// Ensure Ctor cannot be discarded, even if in a comdat.
132+
appendToUsed(M, {Ctor});
131133
return Ctor;
132134
}
133135

llvm/test/Instrumentation/AddressSanitizer/basic.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
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"
1010
target triple = "x86_64-unknown-linux-gnu"
11-
; CHECK: @llvm.global_ctors = {{.*}}@asan.module_ctor
11+
; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @asan.module_ctor to i8*)]
12+
; CHECK: @llvm.global_ctors = {{.*}}{ i32 1, void ()* @asan.module_ctor, i8* bitcast (void ()* @asan.module_ctor to i8*) }
1213

1314
define i32 @test_load(i32* %a) sanitize_address {
1415
; CHECK-LABEL: @test_load

llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ target triple = "x86_64-unknown-linux-gnu"
1010
; module ctor/dtor
1111

1212
; CHECK: @___asan_gen_ = private constant [8 x i8] c"<stdin>\00", align 1
13-
; CHECK: llvm.global_ctors
14-
; CHECK: llvm.global_dtors
13+
; CHECK: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @asan.module_ctor to i8*), i8* bitcast (void ()* @asan.module_dtor to i8*)], section "llvm.metadata"
14+
; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* bitcast (void ()* @asan.module_ctor to i8*) }]
15+
; CHECK: @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_dtor, i8* bitcast (void ()* @asan.module_dtor to i8*) }]
1516

1617
; Test that we don't instrument global arrays with static initializer
1718
; indexed with constants in-bounds. But instrument all other cases.

llvm/test/Instrumentation/HWAddressSanitizer/basic.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
; RUN: opt < %s -passes=hwasan -hwasan-recover=0 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,ABORT
1212
; RUN: opt < %s -passes=hwasan -hwasan-recover=1 -hwasan-mapping-offset=0 -S | FileCheck %s --check-prefixes=CHECK,RECOVER,RECOVER-ZERO-BASED-SHADOW
1313

14+
; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @hwasan.module_ctor to i8*)]
1415
; 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*) }]
1516

1617
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"

llvm/test/Instrumentation/HeapProfiler/basic.ll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
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"
1111
target triple = "x86_64-unknown-linux-gnu"
12-
; CHECK: @llvm.global_ctors = {{.*}}@memprof.module_ctor
12+
13+
; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @memprof.module_ctor to i8*)]
14+
; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @memprof.module_ctor, i8* null }]
1315

1416
define i32 @test_load(i32* %a) {
1517
entry:

llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
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"
1111
target triple = "x86_64-unknown-linux-gnu"
1212

13+
; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @msan.module_ctor to i8*)]
1314
; CHECK: @llvm.global_ctors {{.*}} { i32 0, void ()* @msan.module_ctor, i8* null }
1415

1516
; Check the presence and the linkage type of __msan_track_origins and

llvm/test/Instrumentation/SanitizerCoverage/inline-bool-flag.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
; CHECK: @__sancov_gen_ = private global [1 x i1] zeroinitializer, section "__sancov_bools", comdat($foo), align 1{{$}}
77
; CHECK: @__start___sancov_bools = extern_weak hidden global i1
88
; CHECK-NEXT: @__stop___sancov_bools = extern_weak hidden global i1
9-
; CHECK-NOT: @llvm.used =
9+
; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @sancov.module_ctor_bool_flag to i8*)], section "llvm.metadata"
1010
; CHECK: @llvm.compiler.used = appending global [1 x i8*] [i8* bitcast ([1 x i1]* @__sancov_gen_ to i8*)], section "llvm.metadata"
1111

1212
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"

llvm/test/Instrumentation/SanitizerCoverage/trace-pc-guard.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
; WIN: @__sancov_gen_ = private global [3 x i32] zeroinitializer, section ".SCOV$GM", comdat($foo), align 4{{$}}
1919
; WIN-NEXT: @__sancov_gen_.1 = private global [1 x i32] zeroinitializer, section ".SCOV$GM", comdat($CallViaVptr), align 4{{$}}
2020

21-
; ELF-NOT: @llvm.used =
21+
; ELF: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @sancov.module_ctor_trace_pc_guard to i8*)]
2222
; ELF: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast ([3 x i32]* @__sancov_gen_ to i8*), i8* bitcast ([1 x i32]* @__sancov_gen_.1 to i8*)], section "llvm.metadata"
23-
; MACHO: @llvm.used = appending global [2 x i8*] [i8* bitcast ([3 x i32]* @__sancov_gen_ to i8*), i8* bitcast ([1 x i32]* @__sancov_gen_.1 to i8*)], section "llvm.metadata"
23+
; MACHO: @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @sancov.module_ctor_trace_pc_guard to i8*), i8* bitcast ([3 x i32]* @__sancov_gen_ to i8*), i8* bitcast ([1 x i32]* @__sancov_gen_.1 to i8*)]
2424
; MACHO-NOT: @llvm.compiler.used =
2525
; WIN: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @sancov.module_ctor_trace_pc_guard to i8*)], section "llvm.metadata"
2626
; WIN-NEXT: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast ([3 x i32]* @__sancov_gen_ to i8*), i8* bitcast ([1 x i32]* @__sancov_gen_.1 to i8*)], section "llvm.metadata"

llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ entry:
1010
ret i32 %tmp1
1111
}
1212

13+
; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @tsan.module_ctor to i8*)]
1314
; CHECK: @llvm.global_ctors = {{.*}}@tsan.module_ctor
1415

1516
; CHECK: define i32 @read_4_bytes(i32* %a)

0 commit comments

Comments
 (0)