-
Notifications
You must be signed in to change notification settings - Fork 355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
freebsd add *stat calls interception support #3181
Conversation
1ca8391
to
28adab5
Compare
src/shims/unix/fs.rs
Outdated
this.assert_target_os("macos", "stat"); | ||
|
||
if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { | ||
throw_unsup_format!("macos_fbsd_stat not meant for os {}", this.tcx.sess.target.os); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't throw a nice error, it should panic. There's a bug in Miri when this happens.
68ae0f7
to
97446f8
Compare
@rustbot review |
src/shims/unix/fs.rs
Outdated
this.assert_target_os("macos", "lstat"); | ||
|
||
if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { | ||
panic!("macos_fbsd_lstat not meant for os {}", this.tcx.sess.target.os); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a verb missing in this sentence.
panic!("macos_fbsd_lstat not meant for os {}", this.tcx.sess.target.os); | |
panic!("`macos_fbsd_lstat` should not be called on {}", this.tcx.sess.target.os); |
(Do this everywhere you have the new panic.)
src/shims/unix/fs.rs
Outdated
} | ||
|
||
// FIXME?: oddily it seems to pick up the old libc crate's freebsd11 definition instead of freebsd13, should be 6 | ||
let name_offset = if this.tcx.sess.target.os == "macos" { 5 } else { 4 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why you mention libc here, this is a hard-coded offset, how should that pick up anything...?
Also, did that offset change between different versions of freebsd?!? How are we supposed to handle that, not knowing which version the program is built for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait, the name is just confusing. This is not an offset! It is a field index.
This should pick up the version of libc that comes with the standard library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
after freebsd 11 dirent had been updated with the missing field (d_off) in same order than Linux (while making it cache friendly) pushing further d_name down the road.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And so the Rust libc crate then got that update as well at time point? Which libc crate version is that?
This file here should be defining which libc is picked up by Miri here. It's the latest version currently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in fact freebsd is one of the few oses in the libc's crate which maintains several os releases versions e.g. freebsd 11 up to 14 having their own definitions when there are changes. So for our example there is dirent
definition for freebsd 11 and later releases in same crate if that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite follow, can you point me at the code for that in the libc crate? Which type does one get when asking for libc::dirent
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
freebsd 11 and later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I think I found it... here. The libc build script runs some code to determine the FreeBSD version. When the FreeBSD standard library is built on a different OS (like e.g. when Miri CI tests the freebsd target on a Linux host), that will fail, and it defaults to freebsd11. But if you are using Miri on a freebsd host, it will use the host freebsd version.
Gosh, what a nightmare.^^ This is impossible to test properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay so what this means for Miri is we have to support all versions of freebsd since we can't know what the build script picks. But we can only test one of them. Amazing. Maybe long-term we want to work with the libc crate to overwrite the version detection inside Miri, though maybe that has other issues.
For this PR, it means:
- definitely use
project_field_named
to get the name_place, that part should be easy - for writing all the other fields, do a dynamic check whether the
d_off
field is present. We can't test "is this freebsd or not" since the type is different for different versions of freebsd, we need to check the presence of this field. You will need to add a new helper function that checks whether a field of a given name exists.
src/shims/unix/fs.rs
Outdated
@@ -1424,7 +1433,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | |||
// } | |||
|
|||
let entry_place = this.deref_pointer_as(entry_op, this.libc_ty_layout("dirent"))?; | |||
let name_place = this.project_field(&entry_place, 5)?; | |||
let name_place = this.project_field(&entry_place, name_offset)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use project_field_named, that should avoid this index hard-coding.
@@ -1,4 +1,5 @@ | |||
//@ignore-target-windows: File handling is not implemented yet | |||
//@ignore-target-freebsd |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what goes wrong when this runs on freebsd? please add a FIXME
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no I just forgot to enable it again..
tests/pass/shims/fs.rs
Outdated
use std::collections::HashMap; | ||
#[cfg(not(target_os = "freebsd"))] | ||
use std::ffi::OsString; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move these imports to inside test_directory
rather than having such global cfg
tests/pass/shims/fs.rs
Outdated
@@ -296,6 +300,7 @@ fn test_canonicalize() { | |||
remove_dir_all(&dir_path).unwrap(); | |||
} | |||
|
|||
#[cfg(not(target_os = "freebsd"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#[cfg(not(target_os = "freebsd"))] | |
#[cfg(not(target_os = "freebsd"))] // FIXME freebsd does not support readdir yet |
Can you add a 32bit freebsd target to CI? With this exposure of previously 64bit-only code to 32bit targets, we definitely need that test coverage. |
a04ac72
to
ffa8f29
Compare
tests/pass/shims/fs.rs
Outdated
@@ -296,7 +309,11 @@ fn test_canonicalize() { | |||
remove_dir_all(&dir_path).unwrap(); | |||
} | |||
|
|||
#[cfg(not(target_os = "freebsd"))] // FIXME: freebsd does not support readdir yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm I just saw you implemented readdir. Why does this test fail?
You need to make sure that every single function that you add for freebsd is actually called by some test, on 32bit and 64bit. This is the standard we expect for all our targets. Don't just disable tests, that's now how one develops reliable software. @rustbot review |
Eh I meant @rustbot author.^^ Btw I am looking into why the existing libc-fs test is already failing on FreeBSD. Is it possible that |
Yes, that does seem to be the case on all BSDs. Oh wow. |
I decided to help with the 32bit issue since it's a bit tricky to debug. #3190 makes the existing tests pass on 32bit FreeBSD, so once that lands please rebase your PR and then you only have to worry about the new functions -- and you can use the same approach for reading |
☔ The latest upstream changes (presumably #3190) made this pull request unmergeable. Please resolve the merge conflicts. |
29c1344
to
653bcbe
Compare
@rustbot review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're getting there I think. :)
src/helpers.rs
Outdated
@@ -225,6 +225,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | |||
bug!("No field named {} in type {}", name, base.layout().ty); | |||
} | |||
|
|||
/// Search if Project (which must be a struct or union type) contains the `name` field. | |||
fn project_field_has_field<P: Projectable<'tcx, Provenance>>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn project_field_has_field<P: Projectable<'tcx, Provenance>>( | |
fn projectable_has_field<P: Projectable<'tcx, Provenance>>( |
src/shims/unix/fs.rs
Outdated
} else { | ||
// freebsd 12 and onwards had added the d_off field | ||
if this.project_field_has_field(&entry_place, "d_off") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please collapse this into } else if {
tests/pass/shims/fs.rs
Outdated
@@ -123,7 +120,9 @@ fn test_file_create_new() { | |||
remove_file(&path).unwrap(); | |||
} | |||
|
|||
#[cfg(not(all(target_os = "freebsd", target_pointer_width = "32")))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's still something wrong here, why is this disabled on 32bit?
I said it multiple times: please don't just disable tests when they fail! Sometimes it is okay to cfg-out a particular test on a particular target, but that always needs a comment explaining why it is done. And here I would expect the test should pass on freebsd so when it fails that needs investigation, not cfg
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot to reenable this one (especially there is no cfg upon test_seek above), no need to assume bad intentions ..
tests/pass/shims/fs.rs
Outdated
@@ -64,6 +59,7 @@ fn test_path_conversion() { | |||
} | |||
|
|||
fn test_file() { | |||
use std::io::{IsTerminal, Read}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems unnecessary to do this for functions that are always enabled? This is only needed for cfg-gated functions.
653bcbe
to
6dc0f6c
Compare
@rustbot review |
@saethlin I think I ve done all was asked can you have a look at it pls ? |
Sorry for the long delay! |
☀️ Test successful - checks-actions |
No description provided.