@@ -1364,6 +1364,41 @@ 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
+
1393
+ impl ToJson for SanitizerSupport {
1394
+ fn to_json ( & self ) -> Json {
1395
+ let mut object = serde_json:: Map :: new ( ) ;
1396
+ object. insert ( "stable" . to_string ( ) , self . stable . to_json ( ) ) ;
1397
+ object. insert ( "unstable" . to_string ( ) , self . unstable . to_json ( ) ) ;
1398
+ Json :: Object ( object)
1399
+ }
1400
+ }
1401
+
1367
1402
#[ derive( Clone , Copy , PartialEq , Hash , Debug ) ]
1368
1403
pub enum FramePointer {
1369
1404
/// Forces the machine code generator to always preserve the frame pointers.
@@ -2284,7 +2319,7 @@ pub struct TargetOptions {
2284
2319
/// Note that the support here is at a codegen level. If the machine code with sanitizer
2285
2320
/// enabled can generated on this target, but the necessary supporting libraries are not
2286
2321
/// distributed with the target, the sanitizer should still appear in this list for the target.
2287
- pub supported_sanitizers : SanitizerSet ,
2322
+ pub supported_sanitizers : SanitizerSupport ,
2288
2323
2289
2324
/// Minimum number of bits in #[repr(C)] enum. Defaults to the size of c_int
2290
2325
pub c_enum_min_bits : Option < u64 > ,
@@ -2516,7 +2551,10 @@ impl Default for TargetOptions {
2516
2551
split_debuginfo : Default :: default ( ) ,
2517
2552
// `Off` is supported by default, but targets can remove this manually, e.g. Windows.
2518
2553
supported_split_debuginfo : Cow :: Borrowed ( & [ SplitDebuginfo :: Off ] ) ,
2519
- supported_sanitizers : SanitizerSet :: empty ( ) ,
2554
+ supported_sanitizers : SanitizerSupport {
2555
+ stable : SanitizerSet :: empty ( ) ,
2556
+ unstable : SanitizerSet :: empty ( ) ,
2557
+ } ,
2520
2558
c_enum_min_bits : None ,
2521
2559
generate_arange_section : true ,
2522
2560
supports_stack_protector : true ,
@@ -2718,6 +2756,35 @@ impl Target {
2718
2756
2719
2757
let mut incorrect_type = vec ! [ ] ;
2720
2758
2759
+ let parse_sanitizer_set = |sanitizers_json : & Json | -> Result < SanitizerSet , String > {
2760
+ let mut sanitizer_set = SanitizerSet :: empty ( ) ;
2761
+ if let Some ( sanitizers) = sanitizers_json. as_array ( ) {
2762
+ for sanitizer in sanitizers {
2763
+ let name = sanitizer
2764
+ . as_str ( )
2765
+ . ok_or_else ( || "Sanitizer name must be a string" . to_string ( ) ) ?;
2766
+ sanitizer_set |= match name {
2767
+ "address" => SanitizerSet :: ADDRESS ,
2768
+ "cfi" => SanitizerSet :: CFI ,
2769
+ "dataflow" => SanitizerSet :: DATAFLOW ,
2770
+ "kcfi" => SanitizerSet :: KCFI ,
2771
+ "kernel-address" => SanitizerSet :: KERNELADDRESS ,
2772
+ "leak" => SanitizerSet :: LEAK ,
2773
+ "memory" => SanitizerSet :: MEMORY ,
2774
+ "memtag" => SanitizerSet :: MEMTAG ,
2775
+ "safestack" => SanitizerSet :: SAFESTACK ,
2776
+ "shadow-call-stack" => SanitizerSet :: SHADOWCALLSTACK ,
2777
+ "thread" => SanitizerSet :: THREAD ,
2778
+ "hwaddress" => SanitizerSet :: HWADDRESS ,
2779
+ _ => return Err ( format ! ( "unknown sanitizer {}" , name) ) ,
2780
+ } ;
2781
+ }
2782
+ } else {
2783
+ return Err ( "Expected a list of sanitizers" . to_string ( ) ) ;
2784
+ }
2785
+ Ok ( sanitizer_set)
2786
+ } ;
2787
+
2721
2788
macro_rules! key {
2722
2789
( $key_name: ident) => ( {
2723
2790
let name = ( stringify!( $key_name) ) . replace( "_" , "-" ) ;
@@ -2951,32 +3018,17 @@ impl Target {
2951
3018
) ) ,
2952
3019
} ) . unwrap_or( Ok ( ( ) ) )
2953
3020
} ) ;
2954
- ( $key_name: ident, SanitizerSet ) => ( {
2955
- let name = ( stringify!( $key_name) ) . replace( "_" , "-" ) ;
2956
- if let Some ( o) = obj. remove( & name) {
2957
- if let Some ( a) = o. as_array( ) {
2958
- for s in a {
2959
- base. $key_name |= match s. as_str( ) {
2960
- Some ( "address" ) => SanitizerSet :: ADDRESS ,
2961
- Some ( "cfi" ) => SanitizerSet :: CFI ,
2962
- Some ( "dataflow" ) => SanitizerSet :: DATAFLOW ,
2963
- Some ( "kcfi" ) => SanitizerSet :: KCFI ,
2964
- Some ( "kernel-address" ) => SanitizerSet :: KERNELADDRESS ,
2965
- Some ( "leak" ) => SanitizerSet :: LEAK ,
2966
- Some ( "memory" ) => SanitizerSet :: MEMORY ,
2967
- Some ( "memtag" ) => SanitizerSet :: MEMTAG ,
2968
- Some ( "safestack" ) => SanitizerSet :: SAFESTACK ,
2969
- Some ( "shadow-call-stack" ) => SanitizerSet :: SHADOWCALLSTACK ,
2970
- Some ( "thread" ) => SanitizerSet :: THREAD ,
2971
- Some ( "hwaddress" ) => SanitizerSet :: HWADDRESS ,
2972
- Some ( s) => return Err ( format!( "unknown sanitizer {}" , s) ) ,
2973
- _ => return Err ( format!( "not a string: {:?}" , s) ) ,
2974
- } ;
2975
- }
2976
- } else {
2977
- incorrect_type. push( name)
2978
- }
2979
- }
3021
+ ( $key_name: ident, SanitizerSupport ) => ( {
3022
+ let stable_sanitizers_json = obj. remove( "stable" )
3023
+ . unwrap_or_else( || serde_json:: Value :: Array ( Vec :: new( ) ) ) ;
3024
+ let unstable_sanitizers_json = obj. remove( "unstable" )
3025
+ . unwrap_or_else( || serde_json:: Value :: Array ( Vec :: new( ) ) ) ;
3026
+ let stable_sanitizers = parse_sanitizer_set( & stable_sanitizers_json) ?;
3027
+ let unstable_sanitizers = parse_sanitizer_set( & unstable_sanitizers_json) ?;
3028
+ base. $key_name = SanitizerSupport {
3029
+ stable: stable_sanitizers,
3030
+ unstable: unstable_sanitizers,
3031
+ } ;
2980
3032
Ok :: <( ) , String >( ( ) )
2981
3033
} ) ;
2982
3034
( $key_name: ident, link_self_contained_components) => ( {
@@ -3248,7 +3300,7 @@ impl Target {
3248
3300
key ! ( debuginfo_kind, DebuginfoKind ) ?;
3249
3301
key ! ( split_debuginfo, SplitDebuginfo ) ?;
3250
3302
key ! ( supported_split_debuginfo, fallible_list) ?;
3251
- key ! ( supported_sanitizers, SanitizerSet ) ?;
3303
+ key ! ( supported_sanitizers, SanitizerSupport ) ?;
3252
3304
key ! ( generate_arange_section, bool ) ;
3253
3305
key ! ( supports_stack_protector, bool ) ;
3254
3306
key ! ( entry_name) ;
0 commit comments