12 files changed +94
-0
lines changed Original file line number Diff line number Diff line change @@ -56,6 +56,8 @@ codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO
56
56
codegen_llvm_run_passes = failed to run LLVM passes
57
57
codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: { $llvm_err }
58
58
59
+ codegen_llvm_sanitizer_kcfi_arity_requires_llvm_20_1_0 = `-Zsanitizer-kcfi-arity` requires LLVM 20.1.0 or later.
60
+
59
61
codegen_llvm_sanitizer_memtag_requires_mte =
60
62
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
61
63
Original file line number Diff line number Diff line change @@ -328,6 +328,17 @@ pub(crate) unsafe fn create_module<'ll>(
328
328
}
329
329
}
330
330
331
+ // Add "kcfi-arity" module flag if KCFI arity indicator is enabled. (See
332
+ // https://github.com/llvm/llvm-project/pull/117121.)
333
+ if sess. is_sanitizer_kcfi_arity_enabled ( ) && sess. is_sanitizer_kcfi_enabled ( ) {
334
+ // KCFI arity requires LLVM 20.1.0 or later.
335
+ if llvm_version < ( 20 , 1 , 0 ) {
336
+ tcx. dcx ( ) . emit_err ( crate :: errors:: SanitizerKcfiArityRequiresLLVM2010 ) ;
337
+ }
338
+
339
+ llvm:: add_module_flag_u32 ( llmod, llvm:: ModuleFlagMergeBehavior :: Override , "kcfi-arity" , 1 ) ;
340
+ }
341
+
331
342
// Control Flow Guard is currently only supported by MSVC and LLVM on Windows.
332
343
if sess. target . is_like_msvc
333
344
|| ( sess. target . options . os == "windows"
Original file line number Diff line number Diff line change @@ -217,3 +217,7 @@ pub(crate) struct MismatchedDataLayout<'a> {
217
217
pub ( crate ) struct FixedX18InvalidArch < ' a > {
218
218
pub arch : & ' a str ,
219
219
}
220
+
221
+ #[ derive( Diagnostic ) ]
222
+ #[ diag( codegen_llvm_sanitizer_kcfi_arity_requires_llvm_20_1_0) ]
223
+ pub ( crate ) struct SanitizerKcfiArityRequiresLLVM2010 ;
Original file line number Diff line number Diff line change @@ -852,6 +852,7 @@ fn test_unstable_options_tracking_hash() {
852
852
tracked ! ( sanitizer_cfi_generalize_pointers, Some ( true ) ) ;
853
853
tracked ! ( sanitizer_cfi_normalize_integers, Some ( true ) ) ;
854
854
tracked ! ( sanitizer_dataflow_abilist, vec![ String :: from( "/rustc/abc" ) ] ) ;
855
+ tracked ! ( sanitizer_kcfi_arity, Some ( true ) ) ;
855
856
tracked ! ( sanitizer_memory_track_origins, 2 ) ;
856
857
tracked ! ( sanitizer_recover, SanitizerSet :: ADDRESS ) ;
857
858
tracked ! ( saturating_float_casts, Some ( true ) ) ;
Original file line number Diff line number Diff line change @@ -94,6 +94,8 @@ session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Cli
94
94
95
95
session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`
96
96
97
+ session_sanitizer_kcfi_arity_requires_kcfi = `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`
98
+
97
99
session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort`
98
100
99
101
session_sanitizer_not_supported = { $us } sanitizer is not supported for this target
Original file line number Diff line number Diff line change @@ -147,6 +147,10 @@ pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi;
147
147
#[ diag( session_sanitizer_cfi_normalize_integers_requires_cfi) ]
148
148
pub ( crate ) struct SanitizerCfiNormalizeIntegersRequiresCfi ;
149
149
150
+ #[ derive( Diagnostic ) ]
151
+ #[ diag( session_sanitizer_kcfi_arity_requires_kcfi) ]
152
+ pub ( crate ) struct SanitizerKcfiArityRequiresKcfi ;
153
+
150
154
#[ derive( Diagnostic ) ]
151
155
#[ diag( session_sanitizer_kcfi_requires_panic_abort) ]
152
156
pub ( crate ) struct SanitizerKcfiRequiresPanicAbort ;
Original file line number Diff line number Diff line change @@ -2433,6 +2433,8 @@ written to standard error output)"),
2433
2433
"enable normalizing integer types (default: no)" ) ,
2434
2434
sanitizer_dataflow_abilist: Vec <String > = ( Vec :: new( ) , parse_comma_list, [ TRACKED ] ,
2435
2435
"additional ABI list files that control how shadow parameters are passed (comma separated)" ) ,
2436
+ sanitizer_kcfi_arity: Option <bool > = ( None , parse_opt_bool, [ TRACKED ] ,
2437
+ "enable KCFI arity indicator (default: no)" ) ,
2436
2438
sanitizer_memory_track_origins: usize = ( 0 , parse_sanitizer_memory_track_origins, [ TRACKED ] ,
2437
2439
"enable origins tracking in MemorySanitizer" ) ,
2438
2440
sanitizer_recover: SanitizerSet = ( SanitizerSet :: empty( ) , parse_sanitizers, [ TRACKED ] ,
Original file line number Diff line number Diff line change @@ -382,6 +382,10 @@ impl Session {
382
382
self . opts . unstable_opts . sanitizer_cfi_normalize_integers == Some ( true )
383
383
}
384
384
385
+ pub fn is_sanitizer_kcfi_arity_enabled ( & self ) -> bool {
386
+ self . opts . unstable_opts . sanitizer_kcfi_arity == Some ( true )
387
+ }
388
+
385
389
pub fn is_sanitizer_kcfi_enabled ( & self ) -> bool {
386
390
self . opts . unstable_opts . sanitizer . contains ( SanitizerSet :: KCFI )
387
391
}
@@ -1204,6 +1208,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
1204
1208
}
1205
1209
}
1206
1210
1211
+ // KCFI arity indicator requires KCFI.
1212
+ if sess. is_sanitizer_kcfi_arity_enabled ( ) && !sess. is_sanitizer_kcfi_enabled ( ) {
1213
+ sess. dcx ( ) . emit_err ( errors:: SanitizerKcfiArityRequiresKcfi ) ;
1214
+ }
1215
+
1207
1216
// LLVM CFI pointer generalization requires CFI or KCFI.
1208
1217
if sess. is_sanitizer_cfi_generalize_pointers_enabled ( ) {
1209
1218
if !( sess. is_sanitizer_cfi_enabled ( ) || sess. is_sanitizer_kcfi_enabled ( ) ) {
Original file line number Diff line number Diff line change
1
+ // Verifies that KCFI arity indicator is emitted.
2
+ //
3
+ //@ add-core-stubs
4
+ //@ revisions: x86_64
5
+ //@ assembly-output: emit-asm
6
+ //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Zsanitizer-kcfi-arity
7
+ //@[x86_64] needs-llvm-components: x86
8
+ //@ min-llvm-version: 20.1.0
9
+
10
+ #![ crate_type = "lib" ]
11
+
12
+ pub fn foo ( f : fn ( i32 ) -> i32 , arg : i32 ) -> i32 {
13
+ // CHECK-LABEL: __cfi__{{.*}}3foo{{.*}}:
14
+ // CHECK-NEXT: nop
15
+ // CHECK-NEXT: nop
16
+ // CHECK-NEXT: nop
17
+ // CHECK-NEXT: nop
18
+ // CHECK-NEXT: nop
19
+ // CHECK-NEXT: nop
20
+ // CHECK-NEXT: nop
21
+ // CHECK-NEXT: nop
22
+ // CHECK-NEXT: nop
23
+ // CHECK-NEXT: nop
24
+ // CHECK-NEXT: nop
25
+ // CHECK-NEXT: mov eax, 653723426
26
+ f ( arg)
27
+ }
Original file line number Diff line number Diff line change
1
+ // Verifies that "kcfi-arity" module flag is added.
2
+ //
3
+ //@ add-core-stubs
4
+ //@ revisions: x86_64
5
+ //@ [x86_64] compile-flags: --target x86_64-unknown-none
6
+ //@ [x86_64] needs-llvm-components: x86
7
+ //@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Zsanitizer-kcfi-arity
8
+ //@ min-llvm-version: 20.1.0
9
+
10
+ #![ feature( no_core, lang_items) ]
11
+ #![ crate_type = "lib" ]
12
+ #![ no_core]
13
+
14
+ extern crate minicore;
15
+ use minicore:: * ;
16
+
17
+ pub fn foo ( ) { }
18
+
19
+ // CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi-arity", i32 1}
Original file line number Diff line number Diff line change
1
+ // Verifies that `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`.
2
+ //
3
+ //@ needs-sanitizer-kcfi
4
+ //@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-kcfi-arity
5
+ //@ min-llvm-version: 20.1.0
6
+
7
+ #![ feature( no_core) ]
8
+ #![ no_core]
9
+ #![ no_main]
Original file line number Diff line number Diff line change
1
+ error: `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`
2
+
3
+ error: aborting due to 1 previous error
4
+
0 commit comments