Merge pull request #4135 from RalfJung/unsup-targets
Add FreeBSD maintainer; test all of Solarish
This commit is contained in:
commit
8db1e9a2ed
7 changed files with 185 additions and 166 deletions
|
|
@ -217,8 +217,8 @@ degree documented below):
|
|||
- For every other target with OS `linux`, `macos`, or `windows`, Miri should generally work, but we
|
||||
make no promises and we don't run tests for such targets.
|
||||
- We have unofficial support (not maintained by the Miri team itself) for some further operating systems.
|
||||
- `solaris` / `illumos`: maintained by @devnexen. Supports `std::{env, thread, sync}`, but not `std::fs`.
|
||||
- `freebsd`: **maintainer wanted**. Supports `std::env` and parts of `std::{thread, fs}`, but not `std::sync`.
|
||||
- `solaris` / `illumos`: maintained by @devnexen. Supports the entire test suite.
|
||||
- `freebsd`: maintained by @YohDeadfall. Supports `std::env` and parts of `std::{thread, fs}`, but not `std::sync`.
|
||||
- `android`: **maintainer wanted**. Support very incomplete, but a basic "hello world" works.
|
||||
- `wasi`: **maintainer wanted**. Support very incomplete, not even standard output works, but an empty `main` function works.
|
||||
- For targets on other operating systems, Miri might fail before even reaching the `main` function.
|
||||
|
|
|
|||
|
|
@ -147,13 +147,14 @@ case $HOST_TARGET in
|
|||
# Extra tier 2
|
||||
TEST_TARGET=arm-unknown-linux-gnueabi run_tests
|
||||
TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice
|
||||
# Not officially supported tier 2
|
||||
TEST_TARGET=x86_64-unknown-illumos run_tests
|
||||
TEST_TARGET=x86_64-pc-solaris run_tests
|
||||
# Partially supported targets (tier 2)
|
||||
BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator
|
||||
UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
|
||||
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
|
||||
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe
|
||||
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs
|
||||
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs
|
||||
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd
|
||||
TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm
|
||||
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
|
||||
|
|
|
|||
|
|
@ -109,56 +109,54 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
let this = self.eval_context_mut();
|
||||
|
||||
// See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
|
||||
#[rustfmt::skip]
|
||||
match link_name.as_str() {
|
||||
// Environment related shims
|
||||
"getenv" => {
|
||||
let [name] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.getenv(name)?;
|
||||
this.write_pointer(result, dest)?;
|
||||
}
|
||||
"unsetenv" => {
|
||||
let [name] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.unsetenv(name)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"setenv" => {
|
||||
let [name, value, overwrite] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [name, value, overwrite] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.read_scalar(overwrite)?.to_i32()?;
|
||||
let result = this.setenv(name, value)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"getcwd" => {
|
||||
let [buf, size] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [buf, size] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.getcwd(buf, size)?;
|
||||
this.write_pointer(result, dest)?;
|
||||
}
|
||||
"chdir" => {
|
||||
let [path] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [path] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.chdir(path)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"getpid" => {
|
||||
let [] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.getpid()?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"sysconf" => {
|
||||
let [val] =
|
||||
this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let [val] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.sysconf(val)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
// File descriptors
|
||||
"read" => {
|
||||
let [fd, buf, count] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, buf, count] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let count = this.read_target_usize(count)?;
|
||||
this.read(fd, buf, count, None, dest)?;
|
||||
}
|
||||
"write" => {
|
||||
let [fd, buf, n] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, buf, n] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let count = this.read_target_usize(n)?;
|
||||
|
|
@ -166,7 +164,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write(fd, buf, count, None, dest)?;
|
||||
}
|
||||
"pread" => {
|
||||
let [fd, buf, count, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let count = this.read_target_usize(count)?;
|
||||
|
|
@ -174,7 +172,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.read(fd, buf, count, Some(offset), dest)?;
|
||||
}
|
||||
"pwrite" => {
|
||||
let [fd, buf, n, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let count = this.read_target_usize(n)?;
|
||||
|
|
@ -183,49 +181,51 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write(fd, buf, count, Some(offset), dest)?;
|
||||
}
|
||||
"pread64" => {
|
||||
let [fd, buf, count, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let count = this.read_target_usize(count)?;
|
||||
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
|
||||
let offset =
|
||||
this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
|
||||
this.read(fd, buf, count, Some(offset), dest)?;
|
||||
}
|
||||
"pwrite64" => {
|
||||
let [fd, buf, n, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let count = this.read_target_usize(n)?;
|
||||
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
|
||||
let offset =
|
||||
this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
|
||||
trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
|
||||
this.write(fd, buf, count, Some(offset), dest)?;
|
||||
}
|
||||
"close" => {
|
||||
let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.close(fd)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"fcntl" => {
|
||||
// `fcntl` is variadic. The argument count is checked based on the first argument
|
||||
// in `this.fcntl()`, so we do not use `check_shim` here.
|
||||
this.check_abi_and_shim_symbol_clash(abi, Conv::C , link_name)?;
|
||||
this.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?;
|
||||
let result = this.fcntl(args)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"dup" => {
|
||||
let [old_fd] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [old_fd] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let old_fd = this.read_scalar(old_fd)?.to_i32()?;
|
||||
let new_fd = this.dup(old_fd)?;
|
||||
this.write_scalar(new_fd, dest)?;
|
||||
}
|
||||
"dup2" => {
|
||||
let [old_fd, new_fd] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [old_fd, new_fd] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let old_fd = this.read_scalar(old_fd)?.to_i32()?;
|
||||
let new_fd = this.read_scalar(new_fd)?.to_i32()?;
|
||||
let result = this.dup2(old_fd, new_fd)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"flock" => {
|
||||
let [fd, op] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, op] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let op = this.read_scalar(op)?.to_i32()?;
|
||||
let result = this.flock(fd, op)?;
|
||||
|
|
@ -234,48 +234,49 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// File and file system access
|
||||
"open" | "open64" => {
|
||||
// `open` is variadic, the third argument is only present when the second argument has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set
|
||||
this.check_abi_and_shim_symbol_clash(abi, Conv::C , link_name)?;
|
||||
// `open` is variadic, the third argument is only present when the second argument
|
||||
// has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set
|
||||
this.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?;
|
||||
let result = this.open(args)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"unlink" => {
|
||||
let [path] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [path] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.unlink(path)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"symlink" => {
|
||||
let [target, linkpath] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [target, linkpath] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.symlink(target, linkpath)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"rename" => {
|
||||
let [oldpath, newpath] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [oldpath, newpath] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.rename(oldpath, newpath)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"mkdir" => {
|
||||
let [path, mode] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [path, mode] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.mkdir(path, mode)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"rmdir" => {
|
||||
let [path] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [path] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.rmdir(path)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"opendir" => {
|
||||
let [name] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.opendir(name)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"closedir" => {
|
||||
let [dirp] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [dirp] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.closedir(dirp)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"lseek64" => {
|
||||
let [fd, offset, whence] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let offset = this.read_scalar(offset)?.to_i64()?;
|
||||
let whence = this.read_scalar(whence)?.to_i32()?;
|
||||
|
|
@ -283,7 +284,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"lseek" => {
|
||||
let [fd, offset, whence] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
|
||||
let whence = this.read_scalar(whence)?.to_i32()?;
|
||||
|
|
@ -291,39 +292,36 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"ftruncate64" => {
|
||||
let [fd, length] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let length = this.read_scalar(length)?.to_i64()?;
|
||||
let result = this.ftruncate64(fd, length.into())?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"ftruncate" => {
|
||||
let [fd, length] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let fd = this.read_scalar(fd)?.to_i32()?;
|
||||
let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?;
|
||||
let result = this.ftruncate64(fd, length)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"fsync" => {
|
||||
let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.fsync(fd)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"fdatasync" => {
|
||||
let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.fdatasync(fd)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"readlink" => {
|
||||
let [pathname, buf, bufsize] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [pathname, buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.readlink(pathname, buf, bufsize)?;
|
||||
this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
|
||||
}
|
||||
"posix_fadvise" => {
|
||||
let [fd, offset, len, advice] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd, offset, len, advice] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.read_scalar(fd)?.to_i32()?;
|
||||
this.read_target_isize(offset)?;
|
||||
this.read_target_isize(len)?;
|
||||
|
|
@ -332,12 +330,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_null(dest)?;
|
||||
}
|
||||
"realpath" => {
|
||||
let [path, resolved_path] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [path, resolved_path] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.realpath(path, resolved_path)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"mkstemp" => {
|
||||
let [template] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [template] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.mkstemp(template)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
|
@ -345,63 +343,59 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// Unnamed sockets and pipes
|
||||
"socketpair" => {
|
||||
let [domain, type_, protocol, sv] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.socketpair(domain, type_, protocol, sv)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pipe" => {
|
||||
let [pipefd] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [pipefd] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pipe2(pipefd, /*flags*/ None)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pipe2" => {
|
||||
// Currently this function does not exist on all Unixes, e.g. on macOS.
|
||||
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "solaris" | "illumos") {
|
||||
throw_unsup_format!(
|
||||
"`pipe2` is not supported on {}",
|
||||
this.tcx.sess.target.os
|
||||
);
|
||||
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "solaris" | "illumos")
|
||||
{
|
||||
throw_unsup_format!("`pipe2` is not supported on {}", this.tcx.sess.target.os);
|
||||
}
|
||||
let [pipefd, flags] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [pipefd, flags] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pipe2(pipefd, Some(flags))?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Time
|
||||
"gettimeofday" => {
|
||||
let [tv, tz] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [tv, tz] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.gettimeofday(tv, tz)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"localtime_r" => {
|
||||
let [timep, result_op] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [timep, result_op] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.localtime_r(timep, result_op)?;
|
||||
this.write_pointer(result, dest)?;
|
||||
}
|
||||
"clock_gettime" => {
|
||||
let [clk_id, tp] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [clk_id, tp] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.clock_gettime(clk_id, tp)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Allocation
|
||||
"posix_memalign" => {
|
||||
let [memptr, align, size] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [memptr, align, size] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.posix_memalign(memptr, align, size)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
"mmap" => {
|
||||
let [addr, length, prot, flags, fd, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [addr, length, prot, flags, fd, offset] =
|
||||
this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
|
||||
let ptr = this.mmap(addr, length, prot, flags, fd, offset)?;
|
||||
this.write_scalar(ptr, dest)?;
|
||||
}
|
||||
"munmap" => {
|
||||
let [addr, length] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [addr, length] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.munmap(addr, length)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
|
@ -414,8 +408,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.tcx.sess.target.os
|
||||
);
|
||||
}
|
||||
let [ptr, nmemb, size] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [ptr, nmemb, size] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let nmemb = this.read_target_usize(nmemb)?;
|
||||
let size = this.read_target_usize(size)?;
|
||||
|
|
@ -438,19 +431,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
"aligned_alloc" => {
|
||||
// This is a C11 function, we assume all Unixes have it.
|
||||
// (MSVC explicitly does not support this.)
|
||||
let [align, size] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [align, size] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let res = this.aligned_alloc(align, size)?;
|
||||
this.write_pointer(res, dest)?;
|
||||
}
|
||||
|
||||
// Dynamic symbol loading
|
||||
"dlsym" => {
|
||||
let [handle, symbol] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [handle, symbol] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.read_target_usize(handle)?;
|
||||
let symbol = this.read_pointer(symbol)?;
|
||||
let name = this.read_c_str(symbol)?;
|
||||
if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name, &this.tcx.sess.target.os) {
|
||||
if let Ok(name) = str::from_utf8(name)
|
||||
&& is_dyn_sym(name, &this.tcx.sess.target.os)
|
||||
{
|
||||
let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name)));
|
||||
this.write_pointer(ptr, dest)?;
|
||||
} else {
|
||||
|
|
@ -460,7 +454,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Thread-local storage
|
||||
"pthread_key_create" => {
|
||||
let [key, dtor] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [key, dtor] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?;
|
||||
let dtor = this.read_pointer(dtor)?;
|
||||
|
||||
|
|
@ -488,21 +482,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_key_delete" => {
|
||||
let [key] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [key] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
|
||||
this.machine.tls.delete_tls_key(key)?;
|
||||
// Return success (0)
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_getspecific" => {
|
||||
let [key] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [key] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
|
||||
let active_thread = this.active_thread();
|
||||
let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
|
||||
this.write_scalar(ptr, dest)?;
|
||||
}
|
||||
"pthread_setspecific" => {
|
||||
let [key, new_ptr] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [key, new_ptr] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
|
||||
let active_thread = this.active_thread();
|
||||
let new_data = this.read_scalar(new_ptr)?;
|
||||
|
|
@ -514,151 +508,149 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Synchronization primitives
|
||||
"pthread_mutexattr_init" => {
|
||||
let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_mutexattr_init(attr)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_mutexattr_settype" => {
|
||||
let [attr, kind] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [attr, kind] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pthread_mutexattr_settype(attr, kind)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pthread_mutexattr_destroy" => {
|
||||
let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_mutexattr_destroy(attr)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_mutex_init" => {
|
||||
let [mutex, attr] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [mutex, attr] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_mutex_init(mutex, attr)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_mutex_lock" => {
|
||||
let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_mutex_lock(mutex, dest)?;
|
||||
}
|
||||
"pthread_mutex_trylock" => {
|
||||
let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pthread_mutex_trylock(mutex)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pthread_mutex_unlock" => {
|
||||
let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pthread_mutex_unlock(mutex)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pthread_mutex_destroy" => {
|
||||
let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_mutex_destroy(mutex)?;
|
||||
this.write_int(0, dest)?;
|
||||
}
|
||||
"pthread_rwlock_rdlock" => {
|
||||
let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_rwlock_rdlock(rwlock, dest)?;
|
||||
}
|
||||
"pthread_rwlock_tryrdlock" => {
|
||||
let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pthread_rwlock_tryrdlock(rwlock)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pthread_rwlock_wrlock" => {
|
||||
let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_rwlock_wrlock(rwlock, dest)?;
|
||||
}
|
||||
"pthread_rwlock_trywrlock" => {
|
||||
let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pthread_rwlock_trywrlock(rwlock)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pthread_rwlock_unlock" => {
|
||||
let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_rwlock_unlock(rwlock)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_rwlock_destroy" => {
|
||||
let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_rwlock_destroy(rwlock)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_condattr_init" => {
|
||||
let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_condattr_init(attr)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_condattr_setclock" => {
|
||||
let [attr, clock_id] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [attr, clock_id] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.pthread_condattr_setclock(attr, clock_id)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pthread_condattr_getclock" => {
|
||||
let [attr, clock_id] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [attr, clock_id] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_condattr_getclock(attr, clock_id)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_condattr_destroy" => {
|
||||
let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_condattr_destroy(attr)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_cond_init" => {
|
||||
let [cond, attr] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [cond, attr] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_cond_init(cond, attr)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_cond_signal" => {
|
||||
let [cond] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [cond] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_cond_signal(cond)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_cond_broadcast" => {
|
||||
let [cond] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [cond] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_cond_broadcast(cond)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_cond_wait" => {
|
||||
let [cond, mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [cond, mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_cond_wait(cond, mutex, dest)?;
|
||||
}
|
||||
"pthread_cond_timedwait" => {
|
||||
let [cond, mutex, abstime] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [cond, mutex, abstime] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_cond_timedwait(cond, mutex, abstime, dest)?;
|
||||
}
|
||||
"pthread_cond_destroy" => {
|
||||
let [cond] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [cond] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_cond_destroy(cond)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
|
||||
// Threading
|
||||
"pthread_create" => {
|
||||
let [thread, attr, start, arg] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [thread, attr, start, arg] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.pthread_create(thread, attr, start, arg)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"pthread_join" => {
|
||||
let [thread, retval] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [thread, retval] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let res = this.pthread_join(thread, retval)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"pthread_detach" => {
|
||||
let [thread] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [thread] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let res = this.pthread_detach(thread)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"pthread_self" => {
|
||||
let [] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let res = this.pthread_self()?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"sched_yield" => {
|
||||
let [] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.sched_yield()?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"nanosleep" => {
|
||||
let [req, rem] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [req, rem] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.nanosleep(req, rem)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
|
@ -671,8 +663,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
let [pid, cpusetsize, mask] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [pid, cpusetsize, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let pid = this.read_scalar(pid)?.to_u32()?;
|
||||
let cpusetsize = this.read_target_usize(cpusetsize)?;
|
||||
let mask = this.read_pointer(mask)?;
|
||||
|
|
@ -680,7 +671,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// TODO: when https://github.com/rust-lang/miri/issues/3730 is fixed this should use its notion of tid/pid
|
||||
let thread_id = match pid {
|
||||
0 => this.active_thread(),
|
||||
_ => throw_unsup_format!("`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread)"),
|
||||
_ =>
|
||||
throw_unsup_format!(
|
||||
"`sched_getaffinity` is only supported with a pid of 0 (indicating the current thread)"
|
||||
),
|
||||
};
|
||||
|
||||
// The mask is stored in chunks, and the size must be a whole number of chunks.
|
||||
|
|
@ -694,7 +688,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
} else if let Some(cpuset) = this.machine.thread_cpu_affinity.get(&thread_id) {
|
||||
let cpuset = cpuset.clone();
|
||||
// we only copy whole chunks of size_of::<c_ulong>()
|
||||
let byte_count = Ord::min(cpuset.as_slice().len(), cpusetsize.try_into().unwrap());
|
||||
let byte_count =
|
||||
Ord::min(cpuset.as_slice().len(), cpusetsize.try_into().unwrap());
|
||||
this.write_bytes_ptr(mask, cpuset.as_slice()[..byte_count].iter().copied())?;
|
||||
this.write_null(dest)?;
|
||||
} else {
|
||||
|
|
@ -711,8 +706,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
let [pid, cpusetsize, mask] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [pid, cpusetsize, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let pid = this.read_scalar(pid)?.to_u32()?;
|
||||
let cpusetsize = this.read_target_usize(cpusetsize)?;
|
||||
let mask = this.read_pointer(mask)?;
|
||||
|
|
@ -720,7 +714,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// TODO: when https://github.com/rust-lang/miri/issues/3730 is fixed this should use its notion of tid/pid
|
||||
let thread_id = match pid {
|
||||
0 => this.active_thread(),
|
||||
_ => throw_unsup_format!("`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread)"),
|
||||
_ =>
|
||||
throw_unsup_format!(
|
||||
"`sched_setaffinity` is only supported with a pid of 0 (indicating the current thread)"
|
||||
),
|
||||
};
|
||||
|
||||
if this.ptr_is_null(mask)? {
|
||||
|
|
@ -729,7 +726,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// NOTE: cpusetsize might be smaller than `CpuAffinityMask::CPU_MASK_BYTES`.
|
||||
// Any unspecified bytes are treated as zero here (none of the CPUs are configured).
|
||||
// This is not exactly documented, so we assume that this is the behavior in practice.
|
||||
let bits_slice = this.read_bytes_ptr_strip_provenance(mask, Size::from_bytes(cpusetsize))?;
|
||||
let bits_slice =
|
||||
this.read_bytes_ptr_strip_provenance(mask, Size::from_bytes(cpusetsize))?;
|
||||
// This ignores the bytes beyond `CpuAffinityMask::CPU_MASK_BYTES`
|
||||
let bits_array: [u8; CpuAffinityMask::CPU_MASK_BYTES] =
|
||||
std::array::from_fn(|i| bits_slice.get(i).copied().unwrap_or(0));
|
||||
|
|
@ -748,12 +746,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Miscellaneous
|
||||
"isatty" => {
|
||||
let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.isatty(fd)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"pthread_atfork" => {
|
||||
let [prepare, parent, child] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [prepare, parent, child] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.read_pointer(prepare)?;
|
||||
this.read_pointer(parent)?;
|
||||
this.read_pointer(child)?;
|
||||
|
|
@ -763,15 +761,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
"getentropy" => {
|
||||
// This function is non-standard but exists with the same signature and behavior on
|
||||
// Linux, macOS, FreeBSD and Solaris/Illumos.
|
||||
if !matches!(&*this.tcx.sess.target.os, "linux" | "macos" | "freebsd" | "illumos" | "solaris" | "android") {
|
||||
if !matches!(
|
||||
&*this.tcx.sess.target.os,
|
||||
"linux" | "macos" | "freebsd" | "illumos" | "solaris" | "android"
|
||||
) {
|
||||
throw_unsup_format!(
|
||||
"`getentropy` is not supported on {}",
|
||||
this.tcx.sess.target.os
|
||||
);
|
||||
}
|
||||
|
||||
let [buf, bufsize] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let buf = this.read_pointer(buf)?;
|
||||
let bufsize = this.read_target_usize(bufsize)?;
|
||||
|
||||
|
|
@ -789,8 +789,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
|
||||
"strerror_r" => {
|
||||
let [errnum, buf, buflen] =
|
||||
this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let [errnum, buf, buflen] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.strerror_r(errnum, buf, buflen)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
|
@ -798,14 +797,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
"getrandom" => {
|
||||
// This function is non-standard but exists with the same signature and behavior on
|
||||
// Linux, FreeBSD and Solaris/Illumos.
|
||||
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris" | "android") {
|
||||
if !matches!(
|
||||
&*this.tcx.sess.target.os,
|
||||
"linux" | "freebsd" | "illumos" | "solaris" | "android"
|
||||
) {
|
||||
throw_unsup_format!(
|
||||
"`getrandom` is not supported on {}",
|
||||
this.tcx.sess.target.os
|
||||
);
|
||||
}
|
||||
let [ptr, len, flags] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [ptr, len, flags] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_target_usize(len)?;
|
||||
let _flags = this.read_scalar(flags)?.to_i32()?;
|
||||
|
|
@ -822,7 +823,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.tcx.sess.target.os
|
||||
);
|
||||
}
|
||||
let [ptr, len] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [ptr, len] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_target_usize(len)?;
|
||||
this.gen_random(ptr, len)?;
|
||||
|
|
@ -841,7 +842,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// For arm32 they did something custom, but similar enough that the same
|
||||
// `_Unwind_RaiseException` impl in miri should work:
|
||||
// https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst
|
||||
if !matches!(&*this.tcx.sess.target.os, "linux" | "freebsd" | "illumos" | "solaris" | "android" | "macos") {
|
||||
if !matches!(
|
||||
&*this.tcx.sess.target.os,
|
||||
"linux" | "freebsd" | "illumos" | "solaris" | "android" | "macos"
|
||||
) {
|
||||
throw_unsup_format!(
|
||||
"`_Unwind_RaiseException` is not supported on {}",
|
||||
this.tcx.sess.target.os
|
||||
|
|
@ -853,43 +857,42 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
return interp_ok(EmulateItemResult::NeedsUnwind);
|
||||
}
|
||||
"getuid" => {
|
||||
let [] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
// For now, just pretend we always have this fixed UID.
|
||||
this.write_int(UID, dest)?;
|
||||
}
|
||||
|
||||
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
|
||||
// These shims are enabled only when the caller is in the standard library.
|
||||
"pthread_attr_getguardsize"
|
||||
if this.frame_in_std() => {
|
||||
let [_attr, guard_size] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
"pthread_attr_getguardsize" if this.frame_in_std() => {
|
||||
let [_attr, guard_size] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let guard_size = this.deref_pointer(guard_size)?;
|
||||
let guard_size_layout = this.libc_ty_layout("size_t");
|
||||
this.write_scalar(Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size)?;
|
||||
this.write_scalar(
|
||||
Scalar::from_uint(this.machine.page_size, guard_size_layout.size),
|
||||
&guard_size,
|
||||
)?;
|
||||
|
||||
// Return success (`0`).
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
|
||||
| "pthread_attr_init"
|
||||
| "pthread_attr_destroy"
|
||||
if this.frame_in_std() => {
|
||||
let [_] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
"pthread_attr_init" | "pthread_attr_destroy" if this.frame_in_std() => {
|
||||
let [_] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
| "pthread_attr_setstacksize"
|
||||
if this.frame_in_std() => {
|
||||
let [_, _] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
"pthread_attr_setstacksize" if this.frame_in_std() => {
|
||||
let [_, _] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
|
||||
"pthread_attr_getstack"
|
||||
if this.frame_in_std() => {
|
||||
"pthread_attr_getstack" if this.frame_in_std() => {
|
||||
// We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here.
|
||||
// Hence we can mostly ignore the input `attr_place`.
|
||||
let [attr_place, addr_place, size_place] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
let _attr_place = this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?;
|
||||
this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let _attr_place =
|
||||
this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?;
|
||||
let addr_place = this.deref_pointer(addr_place)?;
|
||||
let size_place = this.deref_pointer(size_place)?;
|
||||
|
||||
|
|
@ -906,24 +909,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_null(dest)?;
|
||||
}
|
||||
|
||||
| "signal"
|
||||
| "sigaltstack"
|
||||
if this.frame_in_std() => {
|
||||
let [_, _] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
"signal" | "sigaltstack" if this.frame_in_std() => {
|
||||
let [_, _] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
| "sigaction"
|
||||
| "mprotect"
|
||||
if this.frame_in_std() => {
|
||||
let [_, _, _] = this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
"sigaction" | "mprotect" if this.frame_in_std() => {
|
||||
let [_, _, _] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
|
||||
"getpwuid_r" | "__posix_getpwuid_r"
|
||||
if this.frame_in_std() => {
|
||||
"getpwuid_r" | "__posix_getpwuid_r" if this.frame_in_std() => {
|
||||
// getpwuid_r is the standard name, __posix_getpwuid_r is used on solarish
|
||||
let [uid, pwd, buf, buflen, result] =
|
||||
this.check_shim(abi, Conv::C , link_name, args)?;
|
||||
this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
this.check_no_isolation("`getpwuid_r`")?;
|
||||
|
||||
let uid = this.read_scalar(uid)?.to_u32()?;
|
||||
|
|
@ -961,11 +959,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
_ => {
|
||||
let target_os = &*this.tcx.sess.target.os;
|
||||
return match target_os {
|
||||
"android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"solaris" | "illumos" => solarish::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest),
|
||||
"android" =>
|
||||
android::EvalContextExt::emulate_foreign_item_inner(
|
||||
this, link_name, abi, args, dest,
|
||||
),
|
||||
"freebsd" =>
|
||||
freebsd::EvalContextExt::emulate_foreign_item_inner(
|
||||
this, link_name, abi, args, dest,
|
||||
),
|
||||
"linux" =>
|
||||
linux::EvalContextExt::emulate_foreign_item_inner(
|
||||
this, link_name, abi, args, dest,
|
||||
),
|
||||
"macos" =>
|
||||
macos::EvalContextExt::emulate_foreign_item_inner(
|
||||
this, link_name, abi, args, dest,
|
||||
),
|
||||
"solaris" | "illumos" =>
|
||||
solarish::EvalContextExt::emulate_foreign_item_inner(
|
||||
this, link_name, abi, args, dest,
|
||||
),
|
||||
_ => interp_ok(EmulateItemResult::NotSupported),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Sockets and pipes
|
||||
"__xnet_socketpair" => {
|
||||
let [domain, type_, protocol, sv] =
|
||||
this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
let result = this.socketpair(domain, type_, protocol, sv)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Miscellaneous
|
||||
"___errno" => {
|
||||
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//@ignore-target: windows # only very limited libc on Windows
|
||||
//@ignore-target: apple # `sched_setaffinity` is not supported on macOS
|
||||
//@only-target: linux # these are Linux-specific APIs
|
||||
//@compile-flags: -Zmiri-disable-isolation -Zmiri-num-cpus=4
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
//@ignore-target: windows # No `memrchr` on Windows
|
||||
//@ignore-target: apple # No `memrchr` on some apple targets
|
||||
//@only-target: linux # `memrchr` is a GNU extension
|
||||
|
||||
use std::ptr;
|
||||
|
||||
// null is explicitly called out as UB in the C docs.
|
||||
// null is explicitly called out as UB in the C docs for `memchr`.
|
||||
fn main() {
|
||||
unsafe {
|
||||
libc::memrchr(ptr::null(), 0, 0); //~ERROR: null pointer
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//@ignore-target: windows # only very limited libc on Windows
|
||||
//@ignore-target: apple # `sched_{g, s}etaffinity` are not supported on macOS
|
||||
//@only-target: linux # these are Linux-specific APIs
|
||||
//@compile-flags: -Zmiri-disable-isolation -Zmiri-num-cpus=4
|
||||
#![feature(io_error_more)]
|
||||
#![feature(pointer_is_aligned_to)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue