Skip to content

Commit 1e9045b

Browse files
committed
Auto merge of #1461 - RalfJung:rwlock-win, r=RalfJung
Implement rwlocks on Windows Fixes #1059
2 parents bde2eb4 + 3a5bcb9 commit 1e9045b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+522
-262
lines changed

src/helpers.rs

+31
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
467467
}
468468
}
469469
}
470+
471+
fn read_scalar_at_offset(
472+
&self,
473+
op: OpTy<'tcx, Tag>,
474+
offset: u64,
475+
layout: TyAndLayout<'tcx>,
476+
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
477+
let this = self.eval_context_ref();
478+
let op_place = this.deref_operand(op)?;
479+
let offset = Size::from_bytes(offset);
480+
// Ensure that the following read at an offset is within bounds
481+
assert!(op_place.layout.size >= offset + layout.size);
482+
let value_place = op_place.offset(offset, MemPlaceMeta::None, layout, this)?;
483+
this.read_scalar(value_place.into())
484+
}
485+
486+
fn write_scalar_at_offset(
487+
&mut self,
488+
op: OpTy<'tcx, Tag>,
489+
offset: u64,
490+
value: impl Into<ScalarMaybeUninit<Tag>>,
491+
layout: TyAndLayout<'tcx>,
492+
) -> InterpResult<'tcx, ()> {
493+
let this = self.eval_context_mut();
494+
let op_place = this.deref_operand(op)?;
495+
let offset = Size::from_bytes(offset);
496+
// Ensure that the following read at an offset is within bounds
497+
assert!(op_place.layout.size >= offset + layout.size);
498+
let value_place = op_place.offset(offset, MemPlaceMeta::None, layout, this)?;
499+
this.write_scalar(value, value_place.into())
500+
}
470501
}
471502

472503
/// Check that the number of args is what we expect.

src/shims/dlsym.rs

+10-33
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,24 @@
11
use rustc_middle::mir;
22

33
use crate::*;
4-
use helpers::check_arg_count;
4+
use shims::posix::dlsym as posix;
5+
use shims::windows::dlsym as windows;
56

67
#[derive(Debug, Copy, Clone)]
8+
#[allow(non_camel_case_types)]
79
pub enum Dlsym {
8-
GetEntropy,
10+
Posix(posix::Dlsym),
11+
Windows(windows::Dlsym),
912
}
1013

1114
impl Dlsym {
1215
// Returns an error for unsupported symbols, and None if this symbol
1316
// should become a NULL pointer (pretend it does not exist).
1417
pub fn from_str(name: &[u8], target_os: &str) -> InterpResult<'static, Option<Dlsym>> {
15-
use self::Dlsym::*;
16-
let name = String::from_utf8_lossy(name);
18+
let name = &*String::from_utf8_lossy(name);
1719
Ok(match target_os {
18-
"linux" => match &*name {
19-
"__pthread_get_minstack" => None,
20-
_ => throw_unsup_format!("unsupported Linux dlsym: {}", name),
21-
}
22-
"macos" => match &*name {
23-
"getentropy" => Some(GetEntropy),
24-
_ => throw_unsup_format!("unsupported macOS dlsym: {}", name),
25-
}
26-
"windows" => match &*name {
27-
"SetThreadStackGuarantee" => None,
28-
"AcquireSRWLockExclusive" => None,
29-
"GetSystemTimePreciseAsFileTime" => None,
30-
_ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
31-
}
20+
"linux" | "macos" => posix::Dlsym::from_str(name, target_os)?.map(Dlsym::Posix),
21+
"windows" => windows::Dlsym::from_str(name)?.map(Dlsym::Windows),
3222
os => bug!("dlsym not implemented for target_os {}", os),
3323
})
3424
}
@@ -42,23 +32,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4232
args: &[OpTy<'tcx, Tag>],
4333
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
4434
) -> InterpResult<'tcx> {
45-
use self::Dlsym::*;
46-
4735
let this = self.eval_context_mut();
48-
let (dest, ret) = ret.expect("we don't support any diverging dlsym");
49-
5036
match dlsym {
51-
GetEntropy => {
52-
let &[ptr, len] = check_arg_count(args)?;
53-
let ptr = this.read_scalar(ptr)?.not_undef()?;
54-
let len = this.read_scalar(len)?.to_machine_usize(this)?;
55-
this.gen_random(ptr, len)?;
56-
this.write_null(dest)?;
57-
}
37+
Dlsym::Posix(dlsym) => posix::EvalContextExt::call_dlsym(this, dlsym, args, ret),
38+
Dlsym::Windows(dlsym) => windows::EvalContextExt::call_dlsym(this, dlsym, args, ret),
5839
}
59-
60-
this.dump_place(*dest);
61-
this.go_to_block(ret);
62-
Ok(())
6340
}
6441
}

src/shims/foreign_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
129129
// This matches calls to the foreign item `panic_impl`.
130130
// The implementation is provided by the function with the `#[panic_handler]` attribute.
131131
"panic_impl" => {
132-
this.check_panic_supported()?;
133132
let panic_impl_id = tcx.lang_items().panic_impl().unwrap();
134133
let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id);
135134
return Ok(Some(&*this.load_mir(panic_impl_instance.def, None)?));

src/shims/mod.rs

-8
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5252
return this.emulate_foreign_item(instance.def_id(), args, ret, unwind);
5353
}
5454

55-
// Better error message for panics on Windows.
56-
let def_id = instance.def_id();
57-
if Some(def_id) == this.tcx.lang_items().begin_panic_fn() ||
58-
Some(def_id) == this.tcx.lang_items().panic_impl()
59-
{
60-
this.check_panic_supported()?;
61-
}
62-
6355
// Otherwise, load the MIR.
6456
Ok(Some(&*this.load_mir(instance.def, None)?))
6557
}

src/shims/panic.rs

-8
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,6 @@ pub struct CatchUnwindData<'tcx> {
3434

3535
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
3636
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
37-
/// Check if panicking is supported on this target, and give a good error otherwise.
38-
fn check_panic_supported(&self) -> InterpResult<'tcx> {
39-
match self.eval_context_ref().tcx.sess.target.target.target_os.as_str() {
40-
"linux" | "macos" => Ok(()),
41-
_ => throw_unsup_format!("panicking is not supported on this target"),
42-
}
43-
}
44-
4537
/// Handles the special `miri_start_panic` intrinsic, which is called
4638
/// by libpanic_unwind to delegate the actual unwinding process to Miri.
4739
fn handle_miri_start_panic(

src/shims/posix/dlsym.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use rustc_middle::mir;
2+
3+
use crate::*;
4+
use shims::posix::linux::dlsym as linux;
5+
use shims::posix::macos::dlsym as macos;
6+
7+
#[derive(Debug, Copy, Clone)]
8+
pub enum Dlsym {
9+
Linux(linux::Dlsym),
10+
MacOs(macos::Dlsym),
11+
}
12+
13+
impl Dlsym {
14+
// Returns an error for unsupported symbols, and None if this symbol
15+
// should become a NULL pointer (pretend it does not exist).
16+
pub fn from_str(name: &str, target_os: &str) -> InterpResult<'static, Option<Dlsym>> {
17+
Ok(match target_os {
18+
"linux" => linux::Dlsym::from_str(name)?.map(Dlsym::Linux),
19+
"macos" => macos::Dlsym::from_str(name)?.map(Dlsym::MacOs),
20+
_ => unreachable!(),
21+
})
22+
}
23+
}
24+
25+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
26+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
27+
fn call_dlsym(
28+
&mut self,
29+
dlsym: Dlsym,
30+
args: &[OpTy<'tcx, Tag>],
31+
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
32+
) -> InterpResult<'tcx> {
33+
let this = self.eval_context_mut();
34+
match dlsym {
35+
Dlsym::Linux(dlsym) => linux::EvalContextExt::call_dlsym(this, dlsym, args, ret),
36+
Dlsym::MacOs(dlsym) => macos::EvalContextExt::call_dlsym(this, dlsym, args, ret),
37+
}
38+
}
39+
}

src/shims/posix/linux/dlsym.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use rustc_middle::mir;
2+
3+
use crate::*;
4+
5+
#[derive(Debug, Copy, Clone)]
6+
pub enum Dlsym {
7+
}
8+
9+
impl Dlsym {
10+
// Returns an error for unsupported symbols, and None if this symbol
11+
// should become a NULL pointer (pretend it does not exist).
12+
pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
13+
Ok(match &*name {
14+
"__pthread_get_minstack" => None,
15+
_ => throw_unsup_format!("unsupported Linux dlsym: {}", name),
16+
})
17+
}
18+
}
19+
20+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
21+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
22+
fn call_dlsym(
23+
&mut self,
24+
dlsym: Dlsym,
25+
_args: &[OpTy<'tcx, Tag>],
26+
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
27+
) -> InterpResult<'tcx> {
28+
let this = self.eval_context_mut();
29+
let (_dest, _ret) = ret.expect("we don't support any diverging dlsym");
30+
assert!(this.tcx.sess.target.target.target_os == "linux");
31+
32+
match dlsym {}
33+
}
34+
}

src/shims/posix/linux/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod foreign_items;
2+
pub mod dlsym;

src/shims/posix/macos/dlsym.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use rustc_middle::mir;
2+
3+
use crate::*;
4+
use helpers::check_arg_count;
5+
6+
#[derive(Debug, Copy, Clone)]
7+
#[allow(non_camel_case_types)]
8+
pub enum Dlsym {
9+
getentropy,
10+
}
11+
12+
impl Dlsym {
13+
// Returns an error for unsupported symbols, and None if this symbol
14+
// should become a NULL pointer (pretend it does not exist).
15+
pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
16+
Ok(match name {
17+
"getentropy" => Some(Dlsym::getentropy),
18+
_ => throw_unsup_format!("unsupported macOS dlsym: {}", name),
19+
})
20+
}
21+
}
22+
23+
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
24+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
25+
fn call_dlsym(
26+
&mut self,
27+
dlsym: Dlsym,
28+
args: &[OpTy<'tcx, Tag>],
29+
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
30+
) -> InterpResult<'tcx> {
31+
let this = self.eval_context_mut();
32+
let (dest, ret) = ret.expect("we don't support any diverging dlsym");
33+
assert!(this.tcx.sess.target.target.target_os == "macos");
34+
35+
match dlsym {
36+
Dlsym::getentropy => {
37+
let &[ptr, len] = check_arg_count(args)?;
38+
let ptr = this.read_scalar(ptr)?.not_undef()?;
39+
let len = this.read_scalar(len)?.to_machine_usize(this)?;
40+
this.gen_random(ptr, len)?;
41+
this.write_null(dest)?;
42+
}
43+
}
44+
45+
this.dump_place(*dest);
46+
this.go_to_block(ret);
47+
Ok(())
48+
}
49+
}

src/shims/posix/macos/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod foreign_items;
2+
pub mod dlsym;

src/shims/posix/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod foreign_items;
2+
pub mod dlsym;
23

34
mod fs;
45
mod sync;

0 commit comments

Comments
 (0)