Skip to content

Commit 0ff0892

Browse files
authored
[Clang][CodeGen] Add disable_sanitizer_instrumentation attribute to multiversion resolvers (#167516)
- Fixes #163369 - Segmentation fault occurred because resolver was calling TSan instrumentation functions (__tsan_func_entry, __tsan_func_exit) but as the resolver is run by the dynamic linker at load time, TSan is not initialized yet so the current thread pointer is null. - This PR adds the DisableSanitizerInstrumentation attribute to the multiversion function resolvers to avoid issues like this. - Added regression test for TSan segfault.
1 parent 7eeae8e commit 0ff0892

26 files changed

+323
-253
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4938,6 +4938,11 @@ void CodeGenModule::setMultiVersionResolverAttributes(llvm::Function *Resolver,
49384938

49394939
setDSOLocal(Resolver);
49404940

4941+
// The resolver must be exempt from sanitizer instrumentation, as it can run
4942+
// before the sanitizer is initialized.
4943+
// (https://github.com/llvm/llvm-project/issues/163369)
4944+
Resolver->addFnAttr(llvm::Attribute::DisableSanitizerInstrumentation);
4945+
49414946
// Set the default target-specific attributes, such as PAC and BTI ones on
49424947
// AArch64. Not passing Decl to prevent setting unrelated attributes,
49434948
// as Resolver can be shared by multiple declarations.

clang/test/CodeGen/AArch64/fmv-detection.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ int caller() {
437437
// CHECK-NEXT: ret i32 [[CALL]]
438438
//
439439
//
440-
// CHECK-LABEL: define {{[^@]+}}@fmv.resolver() comdat {
440+
// CHECK-LABEL: define {{[^@]+}}@fmv.resolver() {{[#0-9]* }}comdat {
441441
// CHECK-NEXT: resolver_entry:
442442
// CHECK-NEXT: call void @__init_cpu_features_resolver()
443443
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8

clang/test/CodeGen/AArch64/fmv-mix-explicit-implicit-default.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,22 +107,26 @@ int caller6(void) { return no_def_explicit_default_first(); }
107107
// CHECK-NEXT: ret i32 [[CALL]]
108108
//
109109
//
110-
// CHECK-LABEL: define {{[^@]+}}@implicit_default_decl_first.resolver() comdat {
110+
// CHECK-LABEL: define {{[^@]+}}@implicit_default_decl_first.resolver()
111+
// CHECK-SAME: #[[ATTR_RESOLVER:[0-9]+]] comdat {
111112
// CHECK-NEXT: resolver_entry:
112113
// CHECK-NEXT: ret ptr @implicit_default_decl_first.default
113114
//
114115
//
115-
// CHECK-LABEL: define {{[^@]+}}@explicit_default_def_first.resolver() comdat {
116+
// CHECK-LABEL: define {{[^@]+}}@explicit_default_def_first.resolver()
117+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
116118
// CHECK-NEXT: resolver_entry:
117119
// CHECK-NEXT: ret ptr @explicit_default_def_first.default
118120
//
119121
//
120-
// CHECK-LABEL: define {{[^@]+}}@implicit_default_def_first.resolver() comdat {
122+
// CHECK-LABEL: define {{[^@]+}}@implicit_default_def_first.resolver()
123+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
121124
// CHECK-NEXT: resolver_entry:
122125
// CHECK-NEXT: ret ptr @implicit_default_def_first.default
123126
//
124127
//
125-
// CHECK-LABEL: define {{[^@]+}}@explicit_default_decl_first.resolver() comdat {
128+
// CHECK-LABEL: define {{[^@]+}}@explicit_default_decl_first.resolver()
129+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
126130
// CHECK-NEXT: resolver_entry:
127131
// CHECK-NEXT: ret ptr @explicit_default_decl_first.default
128132
//

clang/test/CodeGen/AArch64/fmv-priority.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
33

44
// Priority biskmasks after feature dependency expansion:
5-
//
65
// MSB LSB
7-
//
86
// sme2 | wfxt | sme | bf16 | | | fp16 | simd | fp
97
// -----+------+-----+------+-------+------+------+------+---
108
// sme2 | | sme | bf16 | rcpc2 | rcpc | fp16 | simd | fp
11-
//
129
// Dependencies should not affect priorities, since a
1310
// feature can only depend on lower priority features:
1411
// https://github.com/ARM-software/acle/pull/376
@@ -32,7 +29,8 @@ int call() { return fn(); }
3229
// CHECK-NEXT: ret i32 [[CALL]]
3330
//
3431
//
35-
// CHECK-LABEL: define weak_odr ptr @fn.resolver() comdat {
32+
// CHECK-LABEL: define weak_odr ptr @fn.resolver()
33+
// CHECK-SAME: #[[ATTR_RESOLVER:[0-9]+]] comdat {
3634
// CHECK-NEXT: [[RESOLVER_ENTRY:.*:]]
3735
// CHECK-NEXT: call void @__init_cpu_features_resolver()
3836
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8

clang/test/CodeGen/AArch64/fmv-resolver-emission.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
258258
// CHECK-NEXT: ret void
259259
//
260260
//
261-
// CHECK-LABEL: define {{[^@]+}}@used_before_default_def.resolver() comdat {
261+
// CHECK-LABEL: define {{[^@]+}}@used_before_default_def.resolver()
262+
// CHECK-SAME: #[[ATTR_RESOLVER:[0-9]+]] comdat {
262263
// CHECK-NEXT: resolver_entry:
263264
// CHECK-NEXT: call void @__init_cpu_features_resolver()
264265
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -272,7 +273,8 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
272273
// CHECK-NEXT: ret ptr @used_before_default_def.default
273274
//
274275
//
275-
// CHECK-LABEL: define {{[^@]+}}@used_after_default_def.resolver() comdat {
276+
// CHECK-LABEL: define {{[^@]+}}@used_after_default_def.resolver()
277+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
276278
// CHECK-NEXT: resolver_entry:
277279
// CHECK-NEXT: call void @__init_cpu_features_resolver()
278280
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -286,7 +288,8 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
286288
// CHECK-NEXT: ret ptr @used_after_default_def.default
287289
//
288290
//
289-
// CHECK-LABEL: define {{[^@]+}}@not_used_with_default.resolver() comdat {
291+
// CHECK-LABEL: define {{[^@]+}}@not_used_with_default.resolver()
292+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
290293
// CHECK-NEXT: resolver_entry:
291294
// CHECK-NEXT: call void @__init_cpu_features_resolver()
292295
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -300,7 +303,8 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
300303
// CHECK-NEXT: ret ptr @not_used_with_default.default
301304
//
302305
//
303-
// CHECK-LABEL: define {{[^@]+}}@indirect_use.resolver() comdat {
306+
// CHECK-LABEL: define {{[^@]+}}@indirect_use.resolver()
307+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
304308
// CHECK-NEXT: resolver_entry:
305309
// CHECK-NEXT: call void @__init_cpu_features_resolver()
306310
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -328,7 +332,8 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
328332
// CHECK-NEXT: ret void
329333
//
330334
//
331-
// CHECK-LABEL: define {{[^@]+}}@internal_func.resolver() {
335+
// CHECK-LABEL: define {{[^@]+}}@internal_func.resolver()
336+
// CHECK-SAME: #[[ATTR_RESOLVER]] {
332337
// CHECK-NEXT: resolver_entry:
333338
// CHECK-NEXT: call void @__init_cpu_features_resolver()
334339
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -356,7 +361,8 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
356361
// CHECK-NEXT: ret void
357362
//
358363
//
359-
// CHECK-LABEL: define {{[^@]+}}@linkonce_func.resolver() comdat {
364+
// CHECK-LABEL: define {{[^@]+}}@linkonce_func.resolver()
365+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
360366
// CHECK-NEXT: resolver_entry:
361367
// CHECK-NEXT: call void @__init_cpu_features_resolver()
362368
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -370,7 +376,8 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
370376
// CHECK-NEXT: ret ptr @linkonce_func.default
371377
//
372378
//
373-
// CHECK-LABEL: define {{[^@]+}}@clones_with_default.resolver() comdat {
379+
// CHECK-LABEL: define {{[^@]+}}@clones_with_default.resolver()
380+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
374381
// CHECK-NEXT: resolver_entry:
375382
// CHECK-NEXT: call void @__init_cpu_features_resolver()
376383
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -383,6 +390,7 @@ __attribute__((target_clones("aes"))) void clones_without_default(void) {}
383390
// CHECK: resolver_else:
384391
// CHECK-NEXT: ret ptr @clones_with_default.default
385392
//
393+
// CHECK: attributes #[[ATTR_RESOLVER]] = { disable_sanitizer_instrumentation }
386394
//.
387395
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
388396
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}

clang/test/CodeGen/AArch64/mixed-target-attributes.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
127127
// CHECK-NEXT: ret i32 0
128128
//
129129
//
130-
// CHECK-LABEL: define {{[^@]+}}@implicit_default.resolver() comdat {
130+
// CHECK-LABEL: define {{[^@]+}}@implicit_default.resolver()
131+
// CHECK-SAME: #[[ATTR_RESOLVER:[0-9]+]] comdat {
131132
// CHECK-NEXT: resolver_entry:
132133
// CHECK-NEXT: call void @__init_cpu_features_resolver()
133134
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -165,7 +166,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
165166
// CHECK-NEXT: ret ptr @implicit_default.default
166167
//
167168
//
168-
// CHECK-LABEL: define {{[^@]+}}@explicit_default.resolver() comdat {
169+
// CHECK-LABEL: define {{[^@]+}}@explicit_default.resolver()
170+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
169171
// CHECK-NEXT: resolver_entry:
170172
// CHECK-NEXT: call void @__init_cpu_features_resolver()
171173
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -203,7 +205,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
203205
// CHECK-NEXT: ret ptr @explicit_default.default
204206
//
205207
//
206-
// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver() comdat {
208+
// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver()
209+
// CHECK-SAME: #[[ATTR_RESOLVER]] comdat {
207210
// CHECK-NEXT: resolver_entry:
208211
// CHECK-NEXT: call void @__init_cpu_features_resolver()
209212
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8

clang/test/CodeGen/AArch64/resolver-attributes.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,20 @@ __attribute__((ifunc("ifunc_resolver"))) int ifunc(void);
4646
// BTI: define internal ptr @static_target_clones.resolver() #[[ATTR_RESOLVER]]
4747
// BTI: define internal ptr @static_target_version.resolver() #[[ATTR_RESOLVER]]
4848

49-
// In NOBTI case, no attribute groups are assigned to the resolver functions:
50-
// NOBTI: define weak_odr ptr @global_target_clones.resolver(){{( comdat)?}} {
51-
// NOBTI: define weak_odr ptr @global_target_version.resolver(){{( comdat)?}} {
52-
// NOBTI: define internal ptr @static_target_clones.resolver() {
53-
// NOBTI: define internal ptr @static_target_version.resolver() {
49+
// In NOBTI case, only "no_sanitizer_instrumentation" attributes are added to the resolver
5450

55-
// HIDDEN: define weak_odr hidden ptr @global_target_clones.resolver(){{( comdat)?}} {
56-
// HIDDEN: define weak_odr hidden ptr @global_target_version.resolver(){{( comdat)?}} {
57-
// HIDDEN: define internal ptr @static_target_clones.resolver() {
58-
// HIDDEN: define internal ptr @static_target_version.resolver() {
51+
// NOBTI: define weak_odr ptr @global_target_clones.resolver() [[ATTR_RESOLVER:(#[0-9]+)?]]{{( comdat)?}}
52+
// NOBTI: define weak_odr ptr @global_target_version.resolver() [[ATTR_RESOLVER]]{{( comdat)?}}
53+
// NOBTI: define internal ptr @static_target_clones.resolver() [[ATTR_RESOLVER]]
54+
// NOBTI: define internal ptr @static_target_version.resolver() [[ATTR_RESOLVER]]
55+
56+
// HIDDEN: define weak_odr hidden ptr @global_target_clones.resolver() [[ATTR_RESOLVER:(#[0-9]+)?]]{{( comdat)?}}
57+
// HIDDEN: define weak_odr hidden ptr @global_target_version.resolver() [[ATTR_RESOLVER]]{{( comdat)?}}
58+
// HIDDEN: define internal ptr @static_target_clones.resolver() [[ATTR_RESOLVER]]
59+
// HIDDEN: define internal ptr @static_target_version.resolver() [[ATTR_RESOLVER]]
5960

6061
// ELF: attributes #[[ATTR_IFUNC_RESOLVER]] = { {{.*}}"branch-target-enforcement"{{.*}} }
6162

6263
// BTI: attributes #[[ATTR_RESOLVER]] = { {{.*}}"branch-target-enforcement"{{.*}} }
64+
//
65+
// NOBTI: attributes [[ATTR_RESOLVER]] = { disable_sanitizer_instrumentation }

0 commit comments

Comments
 (0)