update the environ shim when environment changes

This commit is contained in:
Christian Poveda 2020-03-04 13:24:01 -05:00
parent d13fe01f82
commit 4f5fdc5810
No known key found for this signature in database
GPG key ID: 27525EF5E7420A50
3 changed files with 38 additions and 24 deletions

View file

@ -77,8 +77,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
),
);
// Complete initialization.
EnvVars::init(&mut ecx, config.excluded_env_vars);
MemoryExtra::init_extern_statics(&mut ecx)?;
EnvVars::init(&mut ecx, config.excluded_env_vars);
// Setup first stack-frame
let main_instance = ty::Instance::mono(tcx, main_id);

View file

@ -70,7 +70,7 @@ pub struct AllocExtra {
/// Extra global memory data
#[derive(Clone, Debug)]
pub struct MemoryExtra {
pub struct MemoryExtra<'tcx> {
pub stacked_borrows: Option<stacked_borrows::MemoryExtra>,
pub intptrcast: intptrcast::MemoryExtra,
@ -85,11 +85,11 @@ pub struct MemoryExtra {
/// (helps for debugging memory leaks).
tracked_alloc_id: Option<AllocId>,
/// The `AllocId` for the `environ` static.
pub(crate) environ: Option<Scalar<Tag>>,
/// Place where the `environ` static is stored.
pub(crate) environ: Option<MPlaceTy<'tcx, Tag>>,
}
impl MemoryExtra {
impl<'tcx> MemoryExtra<'tcx> {
pub fn new(rng: StdRng, stacked_borrows: bool, tracked_pointer_tag: Option<PtrId>, tracked_alloc_id: Option<AllocId>) -> Self {
let stacked_borrows = if stacked_borrows {
Some(Rc::new(RefCell::new(stacked_borrows::GlobalState::new(tracked_pointer_tag))))
@ -107,7 +107,7 @@ impl MemoryExtra {
}
/// Sets up the "extern statics" for this machine.
pub fn init_extern_statics<'mir, 'tcx>(
pub fn init_extern_statics<'mir>(
this: &mut MiriEvalContext<'mir, 'tcx>,
) -> InterpResult<'tcx> {
match this.tcx.sess.target.target.target_os.as_str() {
@ -126,12 +126,13 @@ impl MemoryExtra {
// "environ"
let layout = this.layout_of(this.tcx.types.usize)?;
let place = this.allocate(layout, MiriMemoryKind::Machine.into());
this.write_scalar(this.memory.extra.environ.unwrap(), place.into())?;
this.write_scalar(Scalar::from_machine_usize(0, &*this.tcx), place.into())?;
this.memory
.extra
.extern_statics
.insert(Symbol::intern("environ"), place.ptr.assert_ptr().alloc_id)
.unwrap_none();
this.memory.extra.environ = Some(place);
}
_ => {} // No "extern statics" supported on this platform
}
@ -217,7 +218,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
type MemoryKinds = MiriMemoryKind;
type FrameExtra = FrameData<'tcx>;
type MemoryExtra = MemoryExtra;
type MemoryExtra = MemoryExtra<'tcx>;
type AllocExtra = AllocExtra;
type PointerTag = Tag;
type ExtraFnVal = Dlsym;
@ -343,7 +344,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
}
fn init_allocation_extra<'b>(
memory_extra: &MemoryExtra,
memory_extra: &MemoryExtra<'tcx>,
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKinds>>,
@ -380,7 +381,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
}
#[inline(always)]
fn tag_static_base_pointer(memory_extra: &MemoryExtra, id: AllocId) -> Self::PointerTag {
fn tag_static_base_pointer(memory_extra: &MemoryExtra<'tcx>, id: AllocId) -> Self::PointerTag {
if let Some(stacked_borrows) = memory_extra.stacked_borrows.as_ref() {
stacked_borrows.borrow_mut().static_base_ptr(id)
} else {

View file

@ -21,29 +21,16 @@ impl EnvVars {
ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
excluded_env_vars: Vec<String>,
) {
let mut vars = Vec::new();
if ecx.machine.communicate {
for (name, value) in env::vars() {
if !excluded_env_vars.contains(&name) {
let var_ptr =
alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx);
ecx.machine.env_vars.map.insert(OsString::from(name), var_ptr);
vars.push(var_ptr.into());
}
}
}
// Add the trailing null pointer
vars.push(Scalar::from_int(0, ecx.pointer_size()));
// Make an array with all these pointers inside Miri.
let tcx = ecx.tcx;
let environ_layout =
ecx.layout_of(tcx.mk_array(tcx.mk_imm_ptr(tcx.types.u8), vars.len() as u64)).unwrap();
let environ_place = ecx.allocate(environ_layout, MiriMemoryKind::Machine.into());
for (idx, var) in vars.into_iter().enumerate() {
let place = ecx.mplace_field(environ_place, idx as u64).unwrap();
ecx.write_scalar(var, place.into()).unwrap();
}
ecx.memory.extra.environ = Some(environ_place.ptr.into());
ecx.update_environ().unwrap();
}
}
@ -94,6 +81,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
if let Some((name, value)) = new {
let var_ptr = alloc_env_var_as_c_str(&name, &value, &mut this);
if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) {
this.update_environ()?;
this.memory
.deallocate(var, None, MiriMemoryKind::Machine.into())?;
}
@ -112,6 +100,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let name = this.read_os_str_from_c_str(name_ptr)?.to_owned();
if !name.is_empty() && !name.to_string_lossy().contains('=') {
success = Some(this.machine.env_vars.map.remove(&name));
this.update_environ()?;
}
}
if let Some(old) = success {
@ -165,4 +154,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
}
}
fn update_environ(&mut self) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
// Collect all the pointers to each variable in a vector.
let mut vars: Vec<Scalar<Tag>> = this.machine.env_vars.map.values().map(|&ptr| ptr.into()).collect();
// Add the trailing null pointer.
vars.push(Scalar::from_int(0, this.pointer_size()));
// Make an array with all these pointers inside Miri.
let tcx = this.tcx;
let vars_layout =
this.layout_of(tcx.mk_array(tcx.types.usize, vars.len() as u64))?;
let vars_place = this.allocate(vars_layout, MiriMemoryKind::Machine.into());
for (idx, var) in vars.into_iter().enumerate() {
let place = this.mplace_field(vars_place, idx as u64)?;
this.write_scalar(var, place.into())?;
}
this.write_scalar(
vars_place.ptr,
this.memory.extra.environ.unwrap().into(),
)?;
Ok(())
}
}