Skip to content

Commit 8ef303c

Browse files
committed
port from find_foreign_static to canonical_alloc_id
1 parent 5d8fbfc commit 8ef303c

File tree

3 files changed

+54
-24
lines changed

3 files changed

+54
-24
lines changed

src/eval.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
5858
),
5959
);
6060
// Complete initialization.
61+
MemoryExtra::init_extern_statics(&mut ecx)?;
6162
EnvVars::init(&mut ecx, config.excluded_env_vars);
6263

6364
// Setup first stack-frame

src/machine.rs

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
use std::borrow::Cow;
55
use std::cell::RefCell;
6+
use std::collections::HashMap;
67
use std::num::NonZeroU64;
78
use std::rc::Rc;
89

@@ -12,7 +13,7 @@ use rustc::mir;
1213
use rustc::ty::{
1314
self,
1415
layout::{LayoutOf, Size},
15-
Ty, TyCtxt,
16+
Ty,
1617
};
1718
use rustc_ast::attr;
1819
use rustc_hir::def_id::DefId;
@@ -74,7 +75,11 @@ pub struct MemoryExtra {
7475
pub stacked_borrows: Option<stacked_borrows::MemoryExtra>,
7576
pub intptrcast: intptrcast::MemoryExtra,
7677

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

@@ -85,7 +90,34 @@ impl MemoryExtra {
8590
} else {
8691
None
8792
};
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(())
89121
}
90122
}
91123

@@ -267,32 +299,29 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
267299
Ok(())
268300
}
269301

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+
};
274312
let attrs = tcx.get_attrs(def_id);
275313
let link_name = match attr::first_attr_value_str_by_name(&attrs, sym::link_name) {
276314
Some(name) => name.as_str(),
277315
None => tcx.item_name(def_id).as_str(),
278316
};
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+
}
296325
}
297326

298327
fn init_allocation_extra<'b>(

src/stacked_borrows.rs

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

0 commit comments

Comments
 (0)