@@ -14,6 +14,7 @@ use rustc_hir::{
14
14
def_id:: { CrateNum , DefId , CRATE_DEF_INDEX , LOCAL_CRATE } ,
15
15
} ;
16
16
use rustc_index:: IndexVec ;
17
+ use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
17
18
use rustc_middle:: middle:: dependency_format:: Linkage ;
18
19
use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
19
20
use rustc_middle:: mir;
@@ -163,22 +164,39 @@ pub fn iter_exported_symbols<'tcx>(
163
164
tcx : TyCtxt < ' tcx > ,
164
165
mut f : impl FnMut ( CrateNum , DefId ) -> InterpResult < ' tcx > ,
165
166
) -> 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.
166
185
// `dependency_formats` includes all the transitive informations needed to link a crate,
167
186
// which is what we need here since we need to dig out `exported_symbols` from all transitive
168
187
// dependencies.
169
188
let dependency_formats = tcx. dependency_formats ( ( ) ) ;
189
+ // Find the dependencies of the executable we are running.
170
190
let dependency_format = dependency_formats
171
191
. iter ( )
172
192
. find ( |( crate_type, _) | * crate_type == CrateType :: Executable )
173
193
. 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
+ } ) {
182
200
// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
183
201
// from a Rust crate.
184
202
for & ( symbol, _export_info) in tcx. exported_symbols ( cnum) {
0 commit comments