@@ -56,6 +56,8 @@ pub struct Std {
5656 force_recompile : bool ,
5757 extra_rust_args : & ' static [ & ' static str ] ,
5858 is_for_mir_opt_tests : bool ,
59+ /// Whether to build with AddressSanitizer enabled.
60+ asan : bool ,
5961}
6062
6163impl Std {
@@ -67,6 +69,7 @@ impl Std {
6769 force_recompile : false ,
6870 extra_rust_args : & [ ] ,
6971 is_for_mir_opt_tests : false ,
72+ asan : false ,
7073 }
7174 }
7275
@@ -107,6 +110,11 @@ impl Std {
107110 pub fn should_be_uplifted_from_stage_1 ( builder : & Builder < ' _ > , stage : u32 ) -> bool {
108111 stage > 1 && !builder. config . full_bootstrap
109112 }
113+
114+ pub fn asan ( mut self , asan : bool ) -> Self {
115+ self . asan = asan;
116+ self
117+ }
110118}
111119
112120impl Step for Std {
@@ -134,7 +142,7 @@ impl Step for Std {
134142 trace ! ( "download_rustc: {}" , builder. download_rustc( ) ) ;
135143 trace ! ( force_recompile) ;
136144
137- run . builder . ensure ( Std {
145+ let std = Std {
138146 // Note: we don't use compiler_for_std here, so that `x build library --stage 2`
139147 // builds a stage2 rustc.
140148 build_compiler : run. builder . compiler ( run. builder . top_stage , builder. host_target ) ,
@@ -143,7 +151,13 @@ impl Step for Std {
143151 force_recompile,
144152 extra_rust_args : & [ ] ,
145153 is_for_mir_opt_tests : false ,
146- } ) ;
154+ asan : false ,
155+ } ;
156+
157+ if builder. config . needs_sanitizer_runtime_built ( run. target ) {
158+ run. builder . ensure ( std. clone ( ) . asan ( true ) ) ;
159+ }
160+ run. builder . ensure ( std. asan ( false ) ) ;
147161 }
148162
149163 /// Builds the standard library.
@@ -182,8 +196,11 @@ impl Step for Std {
182196 && builder. config . is_host_target ( target)
183197 && !self . force_recompile
184198 {
185- let sysroot =
186- builder. ensure ( Sysroot { compiler : build_compiler, force_recompile : false } ) ;
199+ let sysroot = builder. ensure ( Sysroot {
200+ compiler : build_compiler,
201+ force_recompile : false ,
202+ asan : self . asan ,
203+ } ) ;
187204 cp_rustc_component_to_ci_sysroot (
188205 builder,
189206 & sysroot,
@@ -268,6 +285,9 @@ impl Step for Std {
268285 Kind :: Build ,
269286 ) ;
270287 std_cargo ( builder, target, & mut cargo, & self . crates ) ;
288+ if self . asan {
289+ cargo. rustflag ( "-Zsanitizer=address" ) ;
290+ }
271291 cargo
272292 } ;
273293
@@ -722,6 +742,8 @@ pub struct StdLink {
722742 crates : Vec < String > ,
723743 /// See [`Std::force_recompile`].
724744 force_recompile : bool ,
745+ /// Whether to build with AddressSanitizer enabled.
746+ asan : bool ,
725747}
726748
727749impl StdLink {
@@ -732,6 +754,7 @@ impl StdLink {
732754 target : std. target ,
733755 crates : std. crates ,
734756 force_recompile : std. force_recompile ,
757+ asan : std. asan ,
735758 }
736759 }
737760}
@@ -759,16 +782,25 @@ impl Step for StdLink {
759782 // NOTE: intentionally does *not* check `target == builder.build` to avoid having to add the same check in `test::Crate`.
760783 let ( libdir, hostdir) = if !self . force_recompile && builder. download_rustc ( ) {
761784 // NOTE: copies part of `sysroot_libdir` to avoid having to add a new `force_recompile` argument there too
762- let lib = builder. sysroot_libdir_relative ( self . compiler ) ;
785+ let lib = if self . asan {
786+ builder. sysroot_asan_libdir_relative ( self . compiler )
787+ } else {
788+ builder. sysroot_libdir_relative ( self . compiler )
789+ } ;
763790 let sysroot = builder. ensure ( crate :: core:: build_steps:: compile:: Sysroot {
764791 compiler : self . compiler ,
765792 force_recompile : self . force_recompile ,
793+ asan : self . asan ,
766794 } ) ;
767795 let libdir = sysroot. join ( lib) . join ( "rustlib" ) . join ( target) . join ( "lib" ) ;
768796 let hostdir = sysroot. join ( lib) . join ( "rustlib" ) . join ( compiler. host ) . join ( "lib" ) ;
769797 ( libdir, hostdir)
770798 } else {
771- let libdir = builder. sysroot_target_libdir ( target_compiler, target) ;
799+ let libdir = if self . asan {
800+ builder. sysroot_target_asan_libdir ( target_compiler, target)
801+ } else {
802+ builder. sysroot_target_libdir ( target_compiler, target)
803+ } ;
772804 let hostdir = builder. sysroot_target_libdir ( target_compiler, compiler. host ) ;
773805 ( libdir, hostdir)
774806 } ;
@@ -1001,11 +1033,18 @@ pub struct Rustc {
10011033 /// Using it within bootstrap can lead to confusing situation where lints are replayed
10021034 /// in two different steps.
10031035 crates : Vec < String > ,
1036+ /// Whether to build with AddressSanitizer enabled.
1037+ asan : bool ,
10041038}
10051039
10061040impl Rustc {
10071041 pub fn new ( build_compiler : Compiler , target : TargetSelection ) -> Self {
1008- Self { target, build_compiler, crates : Default :: default ( ) }
1042+ Self { target, build_compiler, crates : Default :: default ( ) , asan : false }
1043+ }
1044+
1045+ pub fn asan ( mut self , asan : bool ) -> Self {
1046+ self . asan = asan;
1047+ self
10091048 }
10101049}
10111050
@@ -1042,6 +1081,7 @@ impl Step for Rustc {
10421081 . compiler ( run. builder . top_stage . saturating_sub ( 1 ) , run. build_triple ( ) ) ,
10431082 target : run. target ,
10441083 crates,
1084+ asan : false ,
10451085 } ) ;
10461086 }
10471087
@@ -1059,8 +1099,11 @@ impl Step for Rustc {
10591099 if builder. download_rustc ( ) && build_compiler. stage != 0 {
10601100 trace ! ( stage = build_compiler. stage, "`download_rustc` requested" ) ;
10611101
1062- let sysroot =
1063- builder. ensure ( Sysroot { compiler : build_compiler, force_recompile : false } ) ;
1102+ let sysroot = builder. ensure ( Sysroot {
1103+ compiler : build_compiler,
1104+ force_recompile : false ,
1105+ asan : self . asan ,
1106+ } ) ;
10641107 cp_rustc_component_to_ci_sysroot (
10651108 builder,
10661109 & sysroot,
@@ -1071,7 +1114,7 @@ impl Step for Rustc {
10711114
10721115 // Build a standard library for `target` using the `build_compiler`.
10731116 // This will be the standard library that the rustc which we build *links to*.
1074- builder. std ( build_compiler, target) ;
1117+ builder. std_maybe_asan ( build_compiler, target, self . asan ) ;
10751118
10761119 if builder. config . keep_stage . contains ( & build_compiler. stage ) {
10771120 trace ! ( stage = build_compiler. stage, "`keep-stage` requested" ) ;
@@ -1112,6 +1155,7 @@ impl Step for Rustc {
11121155 build_compiler,
11131156 target,
11141157 self . crates ,
1158+ self . asan ,
11151159 ) ) ;
11161160
11171161 // Here we have performed an uplift, so we return the actual build compiler that "built"
@@ -1143,6 +1187,14 @@ impl Step for Rustc {
11431187 // NB: all RUSTFLAGS should be added to `rustc_cargo()` so they will be
11441188 // consistently applied by check/doc/test modes too.
11451189
1190+ if self . asan && build_compiler. stage > 0 {
1191+ cargo. rustflag ( "-Zsanitizer=address" ) ;
1192+ cargo. rustflag ( & format ! (
1193+ "-L{}" ,
1194+ builder. sysroot_asan_libdir_relative( build_compiler) . display( )
1195+ ) ) ;
1196+ }
1197+
11461198 for krate in & * self . crates {
11471199 cargo. arg ( "-p" ) . arg ( krate) ;
11481200 }
@@ -1523,6 +1575,8 @@ struct RustcLink {
15231575 target : TargetSelection ,
15241576 /// Not actually used; only present to make sure the cache invalidation is correct.
15251577 crates : Vec < String > ,
1578+ /// Whether to build with AddressSanitizer enabled.
1579+ asan : bool ,
15261580}
15271581
15281582impl RustcLink {
@@ -1534,6 +1588,7 @@ impl RustcLink {
15341588 sysroot_compiler : rustc. build_compiler ,
15351589 target : rustc. target ,
15361590 crates : rustc. crates ,
1591+ asan : rustc. asan ,
15371592 }
15381593 }
15391594
@@ -1543,8 +1598,9 @@ impl RustcLink {
15431598 sysroot_compiler : Compiler ,
15441599 target : TargetSelection ,
15451600 crates : Vec < String > ,
1601+ asan : bool ,
15461602 ) -> Self {
1547- Self { build_compiler, sysroot_compiler, target, crates }
1603+ Self { build_compiler, sysroot_compiler, target, crates, asan }
15481604 }
15491605}
15501606
@@ -1560,10 +1616,23 @@ impl Step for RustcLink {
15601616 let build_compiler = self . build_compiler ;
15611617 let sysroot_compiler = self . sysroot_compiler ;
15621618 let target = self . target ;
1619+
1620+ let target_libdir = if self . asan {
1621+ builder. sysroot_target_asan_libdir ( sysroot_compiler, target)
1622+ } else {
1623+ builder. sysroot_target_libdir ( sysroot_compiler, target)
1624+ } ;
1625+
1626+ let host_libdir = if self . asan {
1627+ builder. sysroot_target_asan_libdir ( sysroot_compiler, sysroot_compiler. host )
1628+ } else {
1629+ builder. sysroot_target_libdir ( sysroot_compiler, sysroot_compiler. host )
1630+ } ;
1631+
15631632 add_to_sysroot (
15641633 builder,
1565- & builder . sysroot_target_libdir ( sysroot_compiler , target ) ,
1566- & builder . sysroot_target_libdir ( sysroot_compiler , sysroot_compiler . host ) ,
1634+ & target_libdir ,
1635+ & host_libdir ,
15671636 & build_stamp:: librustc_stamp ( builder, build_compiler, target) ,
15681637 ) ;
15691638 }
@@ -1827,11 +1896,13 @@ pub struct Sysroot {
18271896 pub compiler : Compiler ,
18281897 /// See [`Std::force_recompile`].
18291898 force_recompile : bool ,
1899+ /// Whether to build with AddressSanitizer enabled.
1900+ asan : bool ,
18301901}
18311902
18321903impl Sysroot {
18331904 pub ( crate ) fn new ( compiler : Compiler ) -> Self {
1834- Sysroot { compiler, force_recompile : false }
1905+ Sysroot { compiler, force_recompile : false , asan : false }
18351906 }
18361907}
18371908
@@ -1849,18 +1920,18 @@ impl Step for Sysroot {
18491920 let compiler = self . compiler ;
18501921 let host_dir = builder. out . join ( compiler. host ) ;
18511922
1852- let sysroot_dir = |stage| {
1923+ let sysroot_dir = |stage, asan | {
18531924 if stage == 0 {
18541925 host_dir. join ( "stage0-sysroot" )
18551926 } else if self . force_recompile && stage == compiler. stage {
18561927 host_dir. join ( format ! ( "stage{stage}-test-sysroot" ) )
18571928 } else if builder. download_rustc ( ) && compiler. stage != builder. top_stage {
18581929 host_dir. join ( "ci-rustc-sysroot" )
18591930 } else {
1860- host_dir. join ( format ! ( "stage{stage}" ) )
1931+ host_dir. join ( format ! ( "stage{stage}{}" , if asan { "-asan" } else { "" } ) )
18611932 }
18621933 } ;
1863- let sysroot = sysroot_dir ( compiler. stage ) ;
1934+ let sysroot = sysroot_dir ( compiler. stage , self . asan ) ;
18641935 trace ! ( stage = ?compiler. stage, ?sysroot) ;
18651936
18661937 builder. do_if_verbose ( || {
@@ -1889,7 +1960,7 @@ impl Step for Sysroot {
18891960 // #102002, cleanup old toolchain folders when using download-rustc so people don't use them by accident.
18901961 for stage in 0 ..=2 {
18911962 if stage != compiler. stage {
1892- let dir = sysroot_dir ( stage) ;
1963+ let dir = sysroot_dir ( stage, self . asan ) ;
18931964 if !dir. ends_with ( "ci-rustc-sysroot" ) {
18941965 let _ = fs:: remove_dir_all ( dir) ;
18951966 }
@@ -2149,8 +2220,11 @@ impl Step for Assemble {
21492220 trace ! ( "`download-rustc` requested, reusing CI compiler for stage > 0" ) ;
21502221
21512222 builder. std ( target_compiler, target_compiler. host ) ;
2152- let sysroot =
2153- builder. ensure ( Sysroot { compiler : target_compiler, force_recompile : false } ) ;
2223+ let sysroot = builder. ensure ( Sysroot {
2224+ compiler : target_compiler,
2225+ force_recompile : false ,
2226+ asan : false ,
2227+ } ) ;
21542228 // Ensure that `libLLVM.so` ends up in the newly created target directory,
21552229 // so that tools using `rustc_private` can use it.
21562230 dist:: maybe_install_llvm_target ( builder, target_compiler. host , & sysroot) ;
@@ -2215,6 +2289,11 @@ impl Step for Assemble {
22152289 "building compiler libraries to link to"
22162290 ) ;
22172291
2292+ // Build ASAN-enabled rustc to populate the ASAN sysroot
2293+ if target_compiler. stage > 0 && builder. config . std_asan {
2294+ builder. ensure ( Rustc :: new ( build_compiler, target_compiler. host ) . asan ( true ) ) ;
2295+ }
2296+
22182297 // It is possible that an uplift has happened, so we override build_compiler here.
22192298 let BuiltRustc { build_compiler } =
22202299 builder. ensure ( Rustc :: new ( build_compiler, target_compiler. host ) ) ;
@@ -2249,11 +2328,7 @@ impl Step for Assemble {
22492328 } )
22502329 . collect :: < HashSet < _ > > ( ) ;
22512330
2252- let sysroot = builder. sysroot ( target_compiler) ;
2253- let rustc_libdir = builder. rustc_libdir ( target_compiler) ;
2254- t ! ( fs:: create_dir_all( & rustc_libdir) ) ;
2255- let src_libdir = builder. sysroot_target_libdir ( build_compiler, host) ;
2256- for f in builder. read_dir ( & src_libdir) {
2331+ let copy_link = |f : fs:: DirEntry , rustc_libdir : & Path | {
22572332 let filename = f. file_name ( ) . into_string ( ) . unwrap ( ) ;
22582333
22592334 let is_proc_macro = proc_macros. contains ( & filename) ;
@@ -2275,6 +2350,23 @@ impl Step for Assemble {
22752350 if is_dylib_or_debug && can_be_rustc_dynamic_dep && !is_proc_macro {
22762351 builder. copy_link ( & f. path ( ) , & rustc_libdir. join ( & filename) , FileType :: Regular ) ;
22772352 }
2353+ } ;
2354+
2355+ // Copy non-ASAN libraries to the sysroot.
2356+ let sysroot = builder. sysroot ( target_compiler) ;
2357+ let rustc_libdir = builder. rustc_libdir ( target_compiler) ;
2358+ t ! ( fs:: create_dir_all( & rustc_libdir) ) ;
2359+ let src_libdir = builder. sysroot_target_libdir ( build_compiler, host) ;
2360+ for f in builder. read_dir ( & src_libdir) {
2361+ copy_link ( f, & rustc_libdir) ;
2362+ }
2363+
2364+ // Copy ASAN libraries to the sysroot
2365+ let rustc_libdir = builder. sysroot_target_asan_libdir ( target_compiler, host) ;
2366+ t ! ( fs:: create_dir_all( & rustc_libdir) ) ;
2367+ let src_libdir = builder. sysroot_target_asan_libdir ( build_compiler, host) ;
2368+ for f in builder. read_dir ( & src_libdir) {
2369+ copy_link ( f, & rustc_libdir) ;
22782370 }
22792371
22802372 {
0 commit comments