3
3
4
4
use std:: borrow:: Cow ;
5
5
use std:: cell:: RefCell ;
6
+ use std:: collections:: HashMap ;
6
7
use std:: num:: NonZeroU64 ;
7
8
use std:: rc:: Rc ;
8
9
@@ -12,7 +13,7 @@ use rustc::mir;
12
13
use rustc:: ty:: {
13
14
self ,
14
15
layout:: { LayoutOf , Size } ,
15
- Ty , TyCtxt ,
16
+ Ty ,
16
17
} ;
17
18
use rustc_ast:: attr;
18
19
use rustc_hir:: def_id:: DefId ;
@@ -74,7 +75,11 @@ pub struct MemoryExtra {
74
75
pub stacked_borrows : Option < stacked_borrows:: MemoryExtra > ,
75
76
pub intptrcast : intptrcast:: MemoryExtra ,
76
77
78
+ /// Mapping extern static names to their canonical allocation.
79
+ pub ( crate ) extern_statics : HashMap < & ' static str , AllocId > ,
80
+
77
81
/// The random number generator used for resolving non-determinism.
82
+ /// Needs to be queried by ptr_to_int, hence needs interior mutability.
78
83
pub ( crate ) rng : RefCell < StdRng > ,
79
84
}
80
85
@@ -85,7 +90,34 @@ impl MemoryExtra {
85
90
} else {
86
91
None
87
92
} ;
88
- MemoryExtra { stacked_borrows, intptrcast : Default :: default ( ) , rng : RefCell :: new ( rng) }
93
+ MemoryExtra {
94
+ stacked_borrows,
95
+ intptrcast : Default :: default ( ) ,
96
+ extern_statics : HashMap :: default ( ) ,
97
+ rng : RefCell :: new ( rng) ,
98
+ }
99
+ }
100
+
101
+ /// Sets up the "extern statics" for this machine.
102
+ pub fn init_extern_statics < ' mir , ' tcx > (
103
+ this : & mut MiriEvalContext < ' mir , ' tcx > ,
104
+ ) -> InterpResult < ' tcx > {
105
+ match this. tcx . sess . target . target . target_os . as_str ( ) {
106
+ "linux" => {
107
+ // "__cxa_thread_atexit_impl"
108
+ // This should be all-zero, pointer-sized.
109
+ let layout = this. layout_of ( this. tcx . types . usize ) ?;
110
+ let place = this. allocate ( layout, MiriMemoryKind :: Machine . into ( ) ) ;
111
+ this. write_scalar ( Scalar :: from_machine_usize ( 0 , & * this. tcx ) , place. into ( ) ) ?;
112
+ this. memory
113
+ . extra
114
+ . extern_statics
115
+ . insert ( "__cxa_thread_atexit_impl" , place. ptr . assert_ptr ( ) . alloc_id )
116
+ . unwrap_none ( ) ;
117
+ }
118
+ _ => { } // No "extern statics" supported on this platform
119
+ }
120
+ Ok ( ( ) )
89
121
}
90
122
}
91
123
@@ -267,32 +299,29 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
267
299
Ok ( ( ) )
268
300
}
269
301
270
- fn find_foreign_static (
271
- tcx : TyCtxt < ' tcx > ,
272
- def_id : DefId ,
273
- ) -> InterpResult < ' tcx , Cow < ' tcx , Allocation > > {
302
+ fn canonical_alloc_id ( mem : & Memory < ' mir , ' tcx , Self > , id : AllocId ) -> AllocId {
303
+ let tcx = mem. tcx ;
304
+ // Figure out if this is an extern static, and if yes, which one.
305
+ let def_id = match tcx. alloc_map . lock ( ) . get ( id) {
306
+ Some ( GlobalAlloc :: Static ( def_id) ) if tcx. is_foreign_item ( def_id) => def_id,
307
+ _ => {
308
+ // No need to canonicalize anything.
309
+ return id;
310
+ }
311
+ } ;
274
312
let attrs = tcx. get_attrs ( def_id) ;
275
313
let link_name = match attr:: first_attr_value_str_by_name ( & attrs, sym:: link_name) {
276
314
Some ( name) => name. as_str ( ) ,
277
315
None => tcx. item_name ( def_id) . as_str ( ) ,
278
316
} ;
279
-
280
- let alloc = match & * link_name {
281
- "__cxa_thread_atexit_impl" => {
282
- // This should be all-zero, pointer-sized.
283
- let size = tcx. data_layout . pointer_size ;
284
- let data = vec ! [ 0 ; size. bytes( ) as usize ] ;
285
- Allocation :: from_bytes ( & data, tcx. data_layout . pointer_align . abi )
286
- }
287
- _ => throw_unsup_format ! ( "can't access foreign static: {}" , link_name) ,
288
- } ;
289
- Ok ( Cow :: Owned ( alloc) )
290
- }
291
-
292
- #[ inline( always) ]
293
- fn before_terminator ( _ecx : & mut InterpCx < ' mir , ' tcx , Self > ) -> InterpResult < ' tcx > {
294
- // We are not interested in detecting loops.
295
- Ok ( ( ) )
317
+ // Check if we know this one.
318
+ if let Some ( canonical_id) = mem. extra . extern_statics . get ( & * link_name) {
319
+ trace ! ( "canonical_alloc_id: {:?} ({}) -> {:?}" , id, link_name, canonical_id) ;
320
+ * canonical_id
321
+ } else {
322
+ // Return original id; `Memory::get_static_alloc` will throw an error.
323
+ id
324
+ }
296
325
}
297
326
298
327
fn init_allocation_extra < ' b > (
0 commit comments