@@ -1364,6 +1364,46 @@ impl ToJson for SanitizerSet {
1364
1364
}
1365
1365
}
1366
1366
1367
+ #[ derive( Clone , Copy , PartialEq , Hash , Debug ) ]
1368
+ /// Sanitizers supported by a target.
1369
+ pub struct SanitizerSupport {
1370
+ /// Sanitizers supported by a target that can be used on stable.
1371
+ pub stable : SanitizerSet ,
1372
+ /// Sanitizers supported by a target that cannot be used on stable.
1373
+ pub unstable : SanitizerSet ,
1374
+ }
1375
+
1376
+ impl SanitizerSupport {
1377
+ /// Returns the set of stable sanitizers.
1378
+ pub fn stable_sanitizers ( & self ) -> SanitizerSet {
1379
+ self . stable
1380
+ }
1381
+
1382
+ /// Returns the set of supported sanitizers.
1383
+ pub fn supported_sanitizers ( & self ) -> SanitizerSet {
1384
+ self . stable | self . unstable
1385
+ }
1386
+
1387
+ /// Returns the set of unstable sanitizers.
1388
+ pub fn unstable_sanitizers ( & self ) -> SanitizerSet {
1389
+ self . unstable
1390
+ }
1391
+
1392
+ /// Returns the set of unsupported sanitizers.
1393
+ pub fn unsupported_sanitizers ( & self ) -> SanitizerSet {
1394
+ SanitizerSet :: empty ( ) - ( self . stable | self . unstable )
1395
+ }
1396
+ }
1397
+
1398
+ impl ToJson for SanitizerSupport {
1399
+ fn to_json ( & self ) -> Json {
1400
+ let mut object = serde_json:: Map :: new ( ) ;
1401
+ object. insert ( "stable" . to_string ( ) , self . stable . to_json ( ) ) ;
1402
+ object. insert ( "unstable" . to_string ( ) , self . unstable . to_json ( ) ) ;
1403
+ Json :: Object ( object)
1404
+ }
1405
+ }
1406
+
1367
1407
#[ derive( Clone , Copy , PartialEq , Hash , Debug ) ]
1368
1408
pub enum FramePointer {
1369
1409
/// Forces the machine code generator to always preserve the frame pointers.
@@ -2271,7 +2311,7 @@ pub struct TargetOptions {
2271
2311
/// Note that the support here is at a codegen level. If the machine code with sanitizer
2272
2312
/// enabled can generated on this target, but the necessary supporting libraries are not
2273
2313
/// distributed with the target, the sanitizer should still appear in this list for the target.
2274
- pub supported_sanitizers : SanitizerSet ,
2314
+ pub supported_sanitizers : SanitizerSupport ,
2275
2315
2276
2316
/// If present it's a default value to use for adjusting the C ABI.
2277
2317
pub default_adjusted_cabi : Option < Abi > ,
@@ -2506,7 +2546,10 @@ impl Default for TargetOptions {
2506
2546
split_debuginfo : Default :: default ( ) ,
2507
2547
// `Off` is supported by default, but targets can remove this manually, e.g. Windows.
2508
2548
supported_split_debuginfo : Cow :: Borrowed ( & [ SplitDebuginfo :: Off ] ) ,
2509
- supported_sanitizers : SanitizerSet :: empty ( ) ,
2549
+ supported_sanitizers : SanitizerSupport {
2550
+ stable : SanitizerSet :: empty ( ) ,
2551
+ unstable : SanitizerSet :: empty ( ) ,
2552
+ } ,
2510
2553
default_adjusted_cabi : None ,
2511
2554
c_enum_min_bits : None ,
2512
2555
generate_arange_section : true ,
@@ -2697,6 +2740,35 @@ impl Target {
2697
2740
2698
2741
let mut incorrect_type = vec ! [ ] ;
2699
2742
2743
+ let parse_sanitizer_set = |sanitizers_json : & Json | -> Result < SanitizerSet , String > {
2744
+ let mut sanitizer_set = SanitizerSet :: empty ( ) ;
2745
+ if let Some ( sanitizers) = sanitizers_json. as_array ( ) {
2746
+ for sanitizer in sanitizers {
2747
+ let name = sanitizer
2748
+ . as_str ( )
2749
+ . ok_or_else ( || "Sanitizer name must be a string" . to_string ( ) ) ?;
2750
+ sanitizer_set |= match name {
2751
+ "address" => SanitizerSet :: ADDRESS ,
2752
+ "cfi" => SanitizerSet :: CFI ,
2753
+ "dataflow" => SanitizerSet :: DATAFLOW ,
2754
+ "kcfi" => SanitizerSet :: KCFI ,
2755
+ "kernel-address" => SanitizerSet :: KERNELADDRESS ,
2756
+ "leak" => SanitizerSet :: LEAK ,
2757
+ "memory" => SanitizerSet :: MEMORY ,
2758
+ "memtag" => SanitizerSet :: MEMTAG ,
2759
+ "safestack" => SanitizerSet :: SAFESTACK ,
2760
+ "shadow-call-stack" => SanitizerSet :: SHADOWCALLSTACK ,
2761
+ "thread" => SanitizerSet :: THREAD ,
2762
+ "hwaddress" => SanitizerSet :: HWADDRESS ,
2763
+ _ => return Err ( format ! ( "unknown sanitizer {}" , name) ) ,
2764
+ } ;
2765
+ }
2766
+ } else {
2767
+ return Err ( "Expected a list of sanitizers" . to_string ( ) ) ;
2768
+ }
2769
+ Ok ( sanitizer_set)
2770
+ } ;
2771
+
2700
2772
macro_rules! key {
2701
2773
( $key_name: ident) => ( {
2702
2774
let name = ( stringify!( $key_name) ) . replace( "_" , "-" ) ;
@@ -2930,32 +3002,17 @@ impl Target {
2930
3002
) ) ,
2931
3003
} ) . unwrap_or( Ok ( ( ) ) )
2932
3004
} ) ;
2933
- ( $key_name: ident, SanitizerSet ) => ( {
2934
- let name = ( stringify!( $key_name) ) . replace( "_" , "-" ) ;
2935
- if let Some ( o) = obj. remove( & name) {
2936
- if let Some ( a) = o. as_array( ) {
2937
- for s in a {
2938
- base. $key_name |= match s. as_str( ) {
2939
- Some ( "address" ) => SanitizerSet :: ADDRESS ,
2940
- Some ( "cfi" ) => SanitizerSet :: CFI ,
2941
- Some ( "dataflow" ) => SanitizerSet :: DATAFLOW ,
2942
- Some ( "kcfi" ) => SanitizerSet :: KCFI ,
2943
- Some ( "kernel-address" ) => SanitizerSet :: KERNELADDRESS ,
2944
- Some ( "leak" ) => SanitizerSet :: LEAK ,
2945
- Some ( "memory" ) => SanitizerSet :: MEMORY ,
2946
- Some ( "memtag" ) => SanitizerSet :: MEMTAG ,
2947
- Some ( "safestack" ) => SanitizerSet :: SAFESTACK ,
2948
- Some ( "shadow-call-stack" ) => SanitizerSet :: SHADOWCALLSTACK ,
2949
- Some ( "thread" ) => SanitizerSet :: THREAD ,
2950
- Some ( "hwaddress" ) => SanitizerSet :: HWADDRESS ,
2951
- Some ( s) => return Err ( format!( "unknown sanitizer {}" , s) ) ,
2952
- _ => return Err ( format!( "not a string: {:?}" , s) ) ,
2953
- } ;
2954
- }
2955
- } else {
2956
- incorrect_type. push( name)
2957
- }
2958
- }
3005
+ ( $key_name: ident, SanitizerSupport ) => ( {
3006
+ let stable_sanitizers_json = obj. remove( "stable" )
3007
+ . unwrap_or_else( || serde_json:: Value :: Array ( Vec :: new( ) ) ) ;
3008
+ let unstable_sanitizers_json = obj. remove( "unstable" )
3009
+ . unwrap_or_else( || serde_json:: Value :: Array ( Vec :: new( ) ) ) ;
3010
+ let stable_sanitizers = parse_sanitizer_set( & stable_sanitizers_json) ?;
3011
+ let unstable_sanitizers = parse_sanitizer_set( & unstable_sanitizers_json) ?;
3012
+ base. $key_name = SanitizerSupport {
3013
+ stable: stable_sanitizers,
3014
+ unstable: unstable_sanitizers,
3015
+ } ;
2959
3016
Ok :: <( ) , String >( ( ) )
2960
3017
} ) ;
2961
3018
( $key_name: ident, link_self_contained_components) => ( {
@@ -3237,7 +3294,7 @@ impl Target {
3237
3294
key ! ( debuginfo_kind, DebuginfoKind ) ?;
3238
3295
key ! ( split_debuginfo, SplitDebuginfo ) ?;
3239
3296
key ! ( supported_split_debuginfo, fallible_list) ?;
3240
- key ! ( supported_sanitizers, SanitizerSet ) ?;
3297
+ key ! ( supported_sanitizers, SanitizerSupport ) ?;
3241
3298
key ! ( default_adjusted_cabi, Option <Abi >) ?;
3242
3299
key ! ( generate_arange_section, bool ) ;
3243
3300
key ! ( supports_stack_protector, bool ) ;
0 commit comments