@@ -14,6 +14,7 @@ use rustc_hir::{
1414 def_id:: { CrateNum , DefId , CRATE_DEF_INDEX , LOCAL_CRATE } ,
1515} ;
1616use rustc_index:: IndexVec ;
17+ use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
1718use rustc_middle:: middle:: dependency_format:: Linkage ;
1819use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
1920use rustc_middle:: mir;
@@ -163,22 +164,39 @@ pub fn iter_exported_symbols<'tcx>(
163164 tcx : TyCtxt < ' tcx > ,
164165 mut f : impl FnMut ( CrateNum , DefId ) -> InterpResult < ' tcx > ,
165166) -> InterpResult < ' tcx > {
167+ // First, the symbols in the local crate. We can't use `exported_symbols` here as that
168+ // skips `#[used]` statics (since `reachable_set` skips them in binary crates).
169+ // So we walk all HIR items ourselves instead.
170+ let crate_items = tcx. hir_crate_items ( ( ) ) ;
171+ for def_id in crate_items. definitions ( ) {
172+ let exported = tcx. def_kind ( def_id) . has_codegen_attrs ( ) && {
173+ let codegen_attrs = tcx. codegen_fn_attrs ( def_id) ;
174+ codegen_attrs. contains_extern_indicator ( )
175+ || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: RUSTC_STD_INTERNAL_SYMBOL )
176+ || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: USED )
177+ || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: USED_LINKER )
178+ } ;
179+ if exported {
180+ f ( LOCAL_CRATE , def_id. into ( ) ) ?;
181+ }
182+ }
183+
184+ // Next, all our dependencies.
166185 // `dependency_formats` includes all the transitive informations needed to link a crate,
167186 // which is what we need here since we need to dig out `exported_symbols` from all transitive
168187 // dependencies.
169188 let dependency_formats = tcx. dependency_formats ( ( ) ) ;
189+ // Find the dependencies of the executable we are running.
170190 let dependency_format = dependency_formats
171191 . iter ( )
172192 . find ( |( crate_type, _) | * crate_type == CrateType :: Executable )
173193 . expect ( "interpreting a non-executable crate" ) ;
174- for cnum in iter:: once ( LOCAL_CRATE ) . chain ( dependency_format. 1 . iter ( ) . enumerate ( ) . filter_map (
175- |( num, & linkage) | {
176- // We add 1 to the number because that's what rustc also does everywhere it
177- // calls `CrateNum::new`...
178- #[ allow( clippy:: arithmetic_side_effects) ]
179- ( linkage != Linkage :: NotLinked ) . then_some ( CrateNum :: new ( num + 1 ) )
180- } ,
181- ) ) {
194+ for cnum in dependency_format. 1 . iter ( ) . enumerate ( ) . filter_map ( |( num, & linkage) | {
195+ // We add 1 to the number because that's what rustc also does everywhere it
196+ // calls `CrateNum::new`...
197+ #[ allow( clippy:: arithmetic_side_effects) ]
198+ ( linkage != Linkage :: NotLinked ) . then_some ( CrateNum :: new ( num + 1 ) )
199+ } ) {
182200 // We can ignore `_export_info` here: we are a Rust crate, and everything is exported
183201 // from a Rust crate.
184202 for & ( symbol, _export_info) in tcx. exported_symbols ( cnum) {
0 commit comments