Skip to content

Commit f228038

Browse files
committed
port from find_foreign_static to canonical_alloc_id
1 parent 489f8cf commit f228038

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

src/eval.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
5656
),
5757
);
5858
// Complete initialization.
59+
MemoryExtra::init_extern_statics(&mut ecx)?;
5960
EnvVars::init(&mut ecx, config.excluded_env_vars);
6061

6162
// Setup first stack-frame

src/machine.rs

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
use std::borrow::Cow;
55
use std::cell::RefCell;
66
use std::rc::Rc;
7+
use std::collections::HashMap;
78

89
use rand::rngs::StdRng;
910

10-
use rustc_hir::def_id::DefId;
1111
use rustc::mir;
1212
use rustc::ty::{
1313
self,
1414
layout::{LayoutOf, Size},
15-
Ty, TyCtxt,
15+
Ty,
1616
};
1717
use rustc_span::{source_map::Span, symbol::sym};
1818
use syntax::attr;
@@ -73,7 +73,11 @@ pub struct MemoryExtra {
7373
pub stacked_borrows: stacked_borrows::MemoryExtra,
7474
pub intptrcast: intptrcast::MemoryExtra,
7575

76+
/// Mapping extern static names to their canonical allocation.
77+
pub(crate) extern_statics: HashMap<&'static str, AllocId>,
78+
7679
/// The random number generator used for resolving non-determinism.
80+
/// Needs to be queried by ptr_to_int, hence needs interior mutability.
7781
pub(crate) rng: RefCell<StdRng>,
7882

7983
/// Whether to enforce the validity invariant.
@@ -85,10 +89,30 @@ impl MemoryExtra {
8589
MemoryExtra {
8690
stacked_borrows: Rc::new(RefCell::new(GlobalState::new(tracked_pointer_tag))),
8791
intptrcast: Default::default(),
92+
extern_statics: HashMap::default(),
8893
rng: RefCell::new(rng),
8994
validate,
9095
}
9196
}
97+
98+
/// Sets up the "extern statics" for this machine.
99+
pub fn init_extern_statics<'mir, 'tcx>(this: &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx> {
100+
match this.tcx.sess.target.target.target_os.as_str() {
101+
"linux" => {
102+
// "__cxa_thread_atexit_impl"
103+
// This should be all-zero, pointer-sized.
104+
let layout = this.layout_of(this.tcx.types.usize)?;
105+
let place = this.allocate(layout, MiriMemoryKind::Machine.into());
106+
this.write_scalar(Scalar::from_machine_usize(0, &*this.tcx), place.into())?;
107+
this.memory.extra.extern_statics.insert(
108+
"__cxa_thread_atexit_impl",
109+
place.ptr.assert_ptr().alloc_id,
110+
).unwrap_none();
111+
}
112+
_ => {} // No "extern statics" supported on this platform
113+
}
114+
Ok(())
115+
}
92116
}
93117

94118
/// The machine itself.
@@ -263,32 +287,32 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
263287
Ok(())
264288
}
265289

266-
fn find_foreign_static(
267-
tcx: TyCtxt<'tcx>,
268-
def_id: DefId,
269-
) -> InterpResult<'tcx, Cow<'tcx, Allocation>> {
290+
fn canonical_alloc_id(
291+
mem: &Memory<'mir, 'tcx, Self>,
292+
id: AllocId,
293+
) -> AllocId {
294+
let tcx = mem.tcx;
295+
// Figure out if this is an extern static, and if yes, which one.
296+
let def_id = match tcx.alloc_map.lock().get(id) {
297+
Some(GlobalAlloc::Static(def_id)) if tcx.is_foreign_item(def_id) => def_id,
298+
_ => {
299+
// No need to canonicalize anything.
300+
return id;
301+
}
302+
};
270303
let attrs = tcx.get_attrs(def_id);
271304
let link_name = match attr::first_attr_value_str_by_name(&attrs, sym::link_name) {
272305
Some(name) => name.as_str(),
273306
None => tcx.item_name(def_id).as_str(),
274307
};
275-
276-
let alloc = match &*link_name {
277-
"__cxa_thread_atexit_impl" => {
278-
// This should be all-zero, pointer-sized.
279-
let size = tcx.data_layout.pointer_size;
280-
let data = vec![0; size.bytes() as usize];
281-
Allocation::from_bytes(&data, tcx.data_layout.pointer_align.abi)
282-
}
283-
_ => throw_unsup_format!("can't access foreign static: {}", link_name),
284-
};
285-
Ok(Cow::Owned(alloc))
286-
}
287-
288-
#[inline(always)]
289-
fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
290-
// We are not interested in detecting loops.
291-
Ok(())
308+
// Check if we know this one.
309+
if let Some(canonical_id) = mem.extra.extern_statics.get(&*link_name) {
310+
trace!("canonical_alloc_id: {:?} ({}) -> {:?}", id, link_name, canonical_id);
311+
*canonical_id
312+
} else {
313+
// Return original id; `Memory::get_static_alloc` will throw an error.
314+
id
315+
}
292316
}
293317

294318
fn init_allocation_extra<'b>(

src/stacked_borrows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ impl Stacks {
448448
// Thus we call `static_base_ptr` such that the global pointers get the same tag
449449
// as what we use here.
450450
// The base pointer is not unique, so the base permission is `SharedReadWrite`.
451-
MemoryKind::Machine(MiriMemoryKind::Static) =>
451+
MemoryKind::Machine(MiriMemoryKind::Static) | MemoryKind::Machine(MiriMemoryKind::Machine) =>
452452
(extra.borrow_mut().static_base_ptr(id), Permission::SharedReadWrite),
453453
// Everything else we handle entirely untagged for now.
454454
// FIXME: experiment with more precise tracking.

0 commit comments

Comments
 (0)