Skip to content

Commit 9d03dd6

Browse files
committed
Auto merge of #977 - christianpoveda:last-error-ptr, r=oli-obk
Move last error into memory These changes move the `Evaluator::last_error` into miri's memory and implement the `__errno_location()` shim (which is used by the file handling functions when they fail).
2 parents de4a846 + 459c65a commit 9d03dd6

File tree

5 files changed

+276
-180
lines changed

5 files changed

+276
-180
lines changed

src/eval.rs

+44-27
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
use rand::rngs::StdRng;
44
use rand::SeedableRng;
55

6-
use syntax::source_map::DUMMY_SP;
7-
use rustc::ty::{self, TyCtxt};
8-
use rustc::ty::layout::{LayoutOf, Size, Align};
96
use rustc::hir::def_id::DefId;
7+
use rustc::ty::layout::{Align, LayoutOf, Size};
8+
use rustc::ty::{self, TyCtxt};
9+
use syntax::source_map::DUMMY_SP;
1010

1111
use crate::{
12-
InterpResult, InterpError, InterpCx, StackPopCleanup, struct_error,
13-
Scalar, Tag, Pointer, FnVal,
14-
MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt, HelpersEvalContextExt,
15-
EnvVars,
12+
struct_error, EnvVars, Evaluator, FnVal, HelpersEvalContextExt, InterpCx, InterpError,
13+
InterpResult, MemoryExtra, MiriMemoryKind, Pointer, Scalar, StackPopCleanup, Tag,
14+
TlsEvalContextExt,
1615
};
1716

1817
/// Configuration needed to spawn a Miri instance.
@@ -40,7 +39,10 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
4039
tcx.at(syntax::source_map::DUMMY_SP),
4140
ty::ParamEnv::reveal_all(),
4241
Evaluator::new(config.communicate),
43-
MemoryExtra::new(StdRng::seed_from_u64(config.seed.unwrap_or(0)), config.validate),
42+
MemoryExtra::new(
43+
StdRng::seed_from_u64(config.seed.unwrap_or(0)),
44+
config.validate,
45+
),
4446
);
4547
// Complete initialization.
4648
EnvVars::init(&mut ecx, config.excluded_env_vars);
@@ -50,9 +52,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
5052
let main_mir = ecx.load_mir(main_instance.def, None)?;
5153

5254
if !main_mir.return_ty().is_unit() || main_mir.arg_count != 0 {
53-
throw_unsup_format!(
54-
"miri does not support main functions without `fn()` type signatures"
55-
);
55+
throw_unsup_format!("miri does not support main functions without `fn()` type signatures");
5656
}
5757

5858
let start_id = tcx.lang_items().start_fn().unwrap();
@@ -62,9 +62,10 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
6262
ecx.tcx.tcx,
6363
ty::ParamEnv::reveal_all(),
6464
start_id,
65-
ecx.tcx.mk_substs(
66-
::std::iter::once(ty::subst::GenericArg::from(main_ret_ty)))
67-
).unwrap();
65+
ecx.tcx
66+
.mk_substs(::std::iter::once(ty::subst::GenericArg::from(main_ret_ty))),
67+
)
68+
.unwrap();
6869
let start_mir = ecx.load_mir(start_instance.def, None)?;
6970

7071
if start_mir.arg_count != 3 {
@@ -91,7 +92,9 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
9192
let mut args = ecx.frame().body.args_iter();
9293

9394
// First argument: pointer to `main()`.
94-
let main_ptr = ecx.memory_mut().create_fn_alloc(FnVal::Instance(main_instance));
95+
let main_ptr = ecx
96+
.memory_mut()
97+
.create_fn_alloc(FnVal::Instance(main_instance));
9598
let dest = ecx.local_place(args.next().unwrap())?;
9699
ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
97100

@@ -124,16 +127,23 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
124127
// Add `0` terminator.
125128
let mut arg = arg.into_bytes();
126129
arg.push(0);
127-
argvs.push(ecx.memory_mut().allocate_static_bytes(arg.as_slice(), MiriMemoryKind::Static.into()));
130+
argvs.push(
131+
ecx.memory_mut()
132+
.allocate_static_bytes(arg.as_slice(), MiriMemoryKind::Static.into()),
133+
);
128134
}
129135
// Make an array with all these pointers, in the Miri memory.
130-
let argvs_layout = ecx.layout_of(ecx.tcx.mk_array(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8), argvs.len() as u64))?;
136+
let argvs_layout = ecx.layout_of(
137+
ecx.tcx
138+
.mk_array(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8), argvs.len() as u64),
139+
)?;
131140
let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Env.into());
132141
for (idx, arg) in argvs.into_iter().enumerate() {
133142
let place = ecx.mplace_field(argvs_place, idx as u64)?;
134143
ecx.write_scalar(Scalar::Ptr(arg), place.into())?;
135144
}
136-
ecx.memory_mut().mark_immutable(argvs_place.ptr.assert_ptr().alloc_id)?;
145+
ecx.memory_mut()
146+
.mark_immutable(argvs_place.ptr.assert_ptr().alloc_id)?;
137147
// Write a pointer to that place as the argument.
138148
let argv = argvs_place.ptr;
139149
ecx.write_scalar(argv, dest)?;
@@ -145,7 +155,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
145155
}
146156
// Store command line as UTF-16 for Windows `GetCommandLineW`.
147157
{
148-
let tcx = &{ecx.tcx.tcx};
158+
let tcx = &{ ecx.tcx.tcx };
149159
let cmd_utf16: Vec<u16> = cmd.encode_utf16().collect();
150160
let cmd_ptr = ecx.memory_mut().allocate(
151161
Size::from_bytes(cmd_utf16.len() as u64 * 2),
@@ -168,16 +178,22 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
168178
}
169179
}
170180

171-
assert!(args.next().is_none(), "start lang item has more arguments than expected");
181+
assert!(
182+
args.next().is_none(),
183+
"start lang item has more arguments than expected"
184+
);
185+
186+
// Set the last_error to 0
187+
let errno_layout = ecx.layout_of(ecx.tcx.types.u32)?;
188+
let errno_place = ecx.allocate(errno_layout, MiriMemoryKind::Static.into());
189+
ecx.write_scalar(Scalar::from_u32(0), errno_place.into())?;
190+
let errno_ptr = ecx.check_mplace_access(errno_place.into(), Some(Size::from_bits(32)))?;
191+
ecx.machine.last_error = errno_ptr;
172192

173193
Ok(ecx)
174194
}
175195

176-
pub fn eval_main<'tcx>(
177-
tcx: TyCtxt<'tcx>,
178-
main_id: DefId,
179-
config: MiriConfig,
180-
) {
196+
pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) {
181197
let mut ecx = match create_ecx(tcx, main_id, config) {
182198
Ok(ecx) => ecx,
183199
Err(mut err) => {
@@ -228,8 +244,9 @@ pub fn eval_main<'tcx>(
228244
// We iterate with indices because we need to look at the next frame (the caller).
229245
for idx in 0..frames.len() {
230246
let frame_info = &frames[idx];
231-
let call_site_is_local = frames.get(idx+1).map_or(false,
232-
|caller_info| caller_info.instance.def_id().is_local());
247+
let call_site_is_local = frames.get(idx + 1).map_or(false, |caller_info| {
248+
caller_info.instance.def_id().is_local()
249+
});
233250
if call_site_is_local {
234251
err.span_note(frame_info.call_site, &frame_info.to_string());
235252
} else {

src/machine.rs

+45-26
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
//! Global machine state as well as implementation of the interpreter engine
22
//! `Machine` trait.
33
4-
use std::rc::Rc;
54
use std::borrow::Cow;
65
use std::cell::RefCell;
6+
use std::rc::Rc;
77

88
use rand::rngs::StdRng;
99

10-
use syntax::attr;
11-
use syntax::symbol::sym;
1210
use rustc::hir::def_id::DefId;
13-
use rustc::ty::{self, Ty, TyCtxt, layout::{Size, LayoutOf}};
1411
use rustc::mir;
12+
use rustc::ty::{
13+
self,
14+
layout::{LayoutOf, Size},
15+
Ty, TyCtxt,
16+
};
17+
use syntax::attr;
18+
use syntax::symbol::sym;
1519

1620
use crate::*;
1721

1822
// Some global facts about the emulated machine.
19-
pub const PAGE_SIZE: u64 = 4*1024; // FIXME: adjust to target architecture
20-
pub const STACK_ADDR: u64 = 32*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
21-
pub const STACK_SIZE: u64 = 16*PAGE_SIZE; // whatever
23+
pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
24+
pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
25+
pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever
2226
pub const NUM_CPUS: u64 = 1;
2327

2428
/// Extra memory kinds
@@ -88,7 +92,7 @@ pub struct Evaluator<'tcx> {
8892
pub(crate) cmd_line: Option<Pointer<Tag>>,
8993

9094
/// Last OS error.
91-
pub(crate) last_error: u32,
95+
pub(crate) last_error: Option<Pointer<Tag>>,
9296

9397
/// TLS state.
9498
pub(crate) tls: TlsData<'tcx>,
@@ -109,7 +113,7 @@ impl<'tcx> Evaluator<'tcx> {
109113
argc: None,
110114
argv: None,
111115
cmd_line: None,
112-
last_error: 0,
116+
last_error: None,
113117
tls: TlsData::default(),
114118
communicate,
115119
file_handler: Default::default(),
@@ -146,7 +150,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
146150
type PointerTag = Tag;
147151
type ExtraFnVal = Dlsym;
148152

149-
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
153+
type MemoryMap = MonoHashMap<
154+
AllocId,
155+
(
156+
MemoryKind<MiriMemoryKind>,
157+
Allocation<Tag, Self::AllocExtra>,
158+
),
159+
>;
150160

151161
const STATIC_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Static);
152162

@@ -264,8 +274,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
264274
}
265275

266276
#[inline(always)]
267-
fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
268-
{
277+
fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
269278
// We are not interested in detecting loops.
270279
Ok(())
271280
}
@@ -275,7 +284,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
275284
id: AllocId,
276285
alloc: Cow<'b, Allocation>,
277286
kind: Option<MemoryKind<Self::MemoryKinds>>,
278-
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag) {
287+
) -> (
288+
Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>,
289+
Self::PointerTag,
290+
) {
279291
let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
280292
let alloc = alloc.into_owned();
281293
let (stacks, base_tag) = if !memory_extra.validate {
@@ -291,12 +303,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
291303
};
292304
let mut stacked_borrows = memory_extra.stacked_borrows.borrow_mut();
293305
let alloc: Allocation<Tag, Self::AllocExtra> = alloc.with_tags_and_extra(
294-
|alloc| if !memory_extra.validate {
295-
Tag::Untagged
296-
} else {
297-
// Only statics may already contain pointers at this point
298-
assert_eq!(kind, MiriMemoryKind::Static.into());
299-
stacked_borrows.static_base_ptr(alloc)
306+
|alloc| {
307+
if !memory_extra.validate {
308+
Tag::Untagged
309+
} else {
310+
// Only statics may already contain pointers at this point
311+
assert_eq!(kind, MiriMemoryKind::Static.into());
312+
stacked_borrows.static_base_ptr(alloc)
313+
}
300314
},
301315
AllocExtra {
302316
stacked_borrows: stacks,
@@ -306,14 +320,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
306320
}
307321

308322
#[inline(always)]
309-
fn tag_static_base_pointer(
310-
memory_extra: &MemoryExtra,
311-
id: AllocId,
312-
) -> Self::PointerTag {
323+
fn tag_static_base_pointer(memory_extra: &MemoryExtra, id: AllocId) -> Self::PointerTag {
313324
if !memory_extra.validate {
314325
Tag::Untagged
315326
} else {
316-
memory_extra.stacked_borrows.borrow_mut().static_base_ptr(id)
327+
memory_extra
328+
.stacked_borrows
329+
.borrow_mut()
330+
.static_base_ptr(id)
317331
}
318332
}
319333

@@ -325,7 +339,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
325339
) -> InterpResult<'tcx> {
326340
if !Self::enforce_validity(ecx) {
327341
// No tracking.
328-
Ok(())
342+
Ok(())
329343
} else {
330344
ecx.retag(kind, place)
331345
}
@@ -343,7 +357,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
343357
ecx: &mut InterpCx<'mir, 'tcx, Self>,
344358
extra: stacked_borrows::CallId,
345359
) -> InterpResult<'tcx> {
346-
Ok(ecx.memory().extra.stacked_borrows.borrow_mut().end_call(extra))
360+
Ok(ecx
361+
.memory()
362+
.extra
363+
.stacked_borrows
364+
.borrow_mut()
365+
.end_call(extra))
347366
}
348367

349368
#[inline(always)]

src/shims/env.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
143143
.write_bytes(tcx, buf, &bytes)?;
144144
return Ok(Scalar::Ptr(buf));
145145
}
146-
this.machine.last_error = this
147-
.eval_path_scalar(&["libc", "ERANGE"])?
148-
.unwrap()
149-
.to_u32()?;
146+
let erange = this.eval_libc("ERANGE")?;
147+
this.set_last_error(erange)?;
150148
}
151-
Err(e) => this.machine.last_error = e.raw_os_error().unwrap() as u32,
149+
Err(e) => this.consume_io_error(e)?,
152150
}
153151
Ok(Scalar::ptr_null(&*this.tcx))
154152
}
@@ -172,7 +170,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
172170
match env::set_current_dir(path) {
173171
Ok(()) => Ok(0),
174172
Err(e) => {
175-
this.machine.last_error = e.raw_os_error().unwrap() as u32;
173+
this.consume_io_error(e)?;
176174
Ok(-1)
177175
}
178176
}

0 commit comments

Comments
 (0)