Auto merge of #2140 - V0ldek:page_size, r=RalfJung

Update GetSystemInfo to work with `page_size` (#2136)

- Change logic in GetSystemInfo shim to take into account the two possible layouts of `SYSTEM_INFO`, the first-field-is-union used by [winapi::um::sysinfoapi::SYSTEM_INFO](https://docs.rs/winapi/latest/winapi/um/sysinfoapi/struct.SYSTEM_INFO.html), and first-two-fields-are-inlined-union used by [num_cpus](5f1b033320/src/lib.rs (L206)).
- Fill out the `dwPageSize` field with the `PAGE_SIZE` constant of `4096`.

Closes #2136
This commit is contained in:
bors 2022-05-22 05:59:39 +00:00
commit b5fc544ae8
10 changed files with 116 additions and 17 deletions

View file

@ -178,9 +178,11 @@ pub struct AllocExtra {
pub struct PrimitiveLayouts<'tcx> {
pub unit: TyAndLayout<'tcx>,
pub i8: TyAndLayout<'tcx>,
pub i16: TyAndLayout<'tcx>,
pub i32: TyAndLayout<'tcx>,
pub isize: TyAndLayout<'tcx>,
pub u8: TyAndLayout<'tcx>,
pub u16: TyAndLayout<'tcx>,
pub u32: TyAndLayout<'tcx>,
pub usize: TyAndLayout<'tcx>,
pub bool: TyAndLayout<'tcx>,
@ -194,9 +196,11 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
Ok(Self {
unit: layout_cx.layout_of(tcx.mk_unit())?,
i8: layout_cx.layout_of(tcx.types.i8)?,
i16: layout_cx.layout_of(tcx.types.i16)?,
i32: layout_cx.layout_of(tcx.types.i32)?,
isize: layout_cx.layout_of(tcx.types.isize)?,
u8: layout_cx.layout_of(tcx.types.u8)?,
u16: layout_cx.layout_of(tcx.types.u16)?,
u32: layout_cx.layout_of(tcx.types.u32)?,
usize: layout_cx.layout_of(tcx.types.usize)?,
bool: layout_cx.layout_of(tcx.types.bool)?,

View file

@ -8,6 +8,7 @@ use rustc_target::spec::abi::Abi;
use crate::*;
use shims::foreign_items::EmulateByNameResult;
use shims::windows::sync::EvalContextExt as _;
use smallvec::SmallVec;
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
@ -119,10 +120,56 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
system_info.ptr,
iter::repeat(0u8).take(system_info.layout.size.bytes() as usize),
)?;
// Set selected fields.
let word_layout = this.machine.layouts.u16;
let dword_layout = this.machine.layouts.u32;
let usize_layout = this.machine.layouts.usize;
// Using `mplace_field` is error-prone, see: https://github.com/rust-lang/miri/issues/2136.
// Pointer fields have different sizes on different targets.
// To avoid all these issue we calculate the offsets ourselves.
let field_sizes = [
word_layout.size, // 0, wProcessorArchitecture : WORD
word_layout.size, // 1, wReserved : WORD
dword_layout.size, // 2, dwPageSize : DWORD
usize_layout.size, // 3, lpMinimumApplicationAddress : LPVOID
usize_layout.size, // 4, lpMaximumApplicationAddress : LPVOID
usize_layout.size, // 5, dwActiveProcessorMask : DWORD_PTR
dword_layout.size, // 6, dwNumberOfProcessors : DWORD
dword_layout.size, // 7, dwProcessorType : DWORD
dword_layout.size, // 8, dwAllocationGranularity : DWORD
word_layout.size, // 9, wProcessorLevel : WORD
word_layout.size, // 10, wProcessorRevision : WORD
];
let field_offsets: SmallVec<[Size; 11]> = field_sizes
.iter()
.copied()
.scan(Size::ZERO, |a, x| {
let res = Some(*a);
*a += x;
res
})
.collect();
// Set page size.
let page_size = system_info.offset(
field_offsets[2],
MemPlaceMeta::None,
dword_layout,
&this.tcx,
)?;
this.write_scalar(
Scalar::from_int(PAGE_SIZE, dword_layout.size),
&page_size.into(),
)?;
// Set number of processors.
let dword_size = Size::from_bytes(4);
let num_cpus = this.mplace_field(&system_info, 6)?;
this.write_scalar(Scalar::from_int(NUM_CPUS, dword_size), &num_cpus.into())?;
let num_cpus = system_info.offset(
field_offsets[6],
MemPlaceMeta::None,
dword_layout,
&this.tcx,
)?;
this.write_scalar(Scalar::from_int(NUM_CPUS, dword_layout.size), &num_cpus.into())?;
}
// Thread-local storage

View file

@ -22,6 +22,7 @@ dependencies = [
"issue_1705",
"issue_1760",
"issue_rust_86261",
"page_size",
"rand",
"serde_derive",
]
@ -123,6 +124,16 @@ dependencies = [
"libc",
]
[[package]]
name = "page_size"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "ppv-lite86"
version = "0.2.10"
@ -233,3 +244,25 @@ name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -22,6 +22,7 @@ rand = { version = "0.8", features = ["small_rng"] }
getrandom_1 = { package = "getrandom", version = "0.1" }
getrandom_2 = { package = "getrandom", version = "0.2" }
serde_derive = "1.0" # not actually used, but exercises some unique code path (`--extern` .so file)
page_size = "0.4.1"
[lib]
test = false # test that this is respected (will show in the output)

View file

@ -5,7 +5,7 @@ test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
imported main
running 7 tests
..i....
test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
running 8 tests
..i.....
test result: ok. 7 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out

View file

@ -5,9 +5,9 @@ test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
imported main
running 7 tests
..i....
test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
running 8 tests
..i.....
test result: ok. 7 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
running 4 tests

View file

@ -8,5 +8,5 @@ imported main
running 1 test
test simple1 ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 6 filtered out
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 7 filtered out

View file

@ -8,7 +8,7 @@ imported main
running 1 test
test simple1 ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 6 filtered out
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 7 filtered out
running 0 tests

View file

@ -1,12 +1,13 @@
running 7 tests
running 8 tests
test cargo_env ... ok
test do_panic - should panic ... ok
test does_not_work_on_miri ... ignored
test entropy_rng ... ok
test fail_index_check - should panic ... ok
test page_size ... ok
test simple1 ... ok
test simple2 ... ok
test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
test result: ok. 7 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out

View file

@ -1,4 +1,4 @@
use rand::{SeedableRng, Rng, rngs::SmallRng};
use rand::{rngs::SmallRng, Rng, SeedableRng};
// Having more than 1 test does seem to make a difference
// (i.e., this calls ptr::swap which having just one test does not).
@ -49,14 +49,27 @@ fn cargo_env() {
}
#[test]
#[should_panic(expected="Explicit panic")]
fn do_panic() { // In large, friendly letters :)
#[should_panic(expected = "Explicit panic")]
fn do_panic() // In large, friendly letters :)
{
panic!("Explicit panic from test!");
}
#[test]
#[allow(unconditional_panic)]
#[should_panic(expected="the len is 0 but the index is 42")]
#[should_panic(expected = "the len is 0 but the index is 42")]
fn fail_index_check() {
[][42]
}
#[test]
fn page_size() {
let page_size = page_size::get();
// In particular, this checks that it is not 0.
assert!(
page_size.next_power_of_two() == page_size,
"page size not a power of two: {}",
page_size
);
}