feat(guest): replace musl with picolibc#831
feat(guest): replace musl with picolibc#831andreiltd wants to merge 2 commits intohyperlight-dev:mainfrom
Conversation
617d834 to
3f8ffcf
Compare
eaf1d54 to
b18a374
Compare
| ) | ||
| .unwrap_or_default(); | ||
|
|
||
| let n = bytes.len(); |
There was a problem hiding this comment.
Do we want to assert n <= count?
A wrongly implemented HostRead could cause a buffer overflow
| } | ||
|
|
||
| let slice = unsafe { core::slice::from_raw_parts(buf as *const u8, count) }; | ||
| let s = core::str::from_utf8(slice).unwrap_or("<invalid utf8>"); |
There was a problem hiding this comment.
question: what do you think of using String::from_utf8_lossy instead? we are doing s.to_string() anyway.
There was a problem hiding this comment.
Sure! As long as from_utf8_lossy doesn't allocate if string is valid utf-8 which I believe is the case?
There was a problem hiding this comment.
It returns a Cow, so, that's correct, but you will need to allocate a string to send it to the host function anyway... so... ¯\_(ツ)_/¯
| [features] | ||
| default = ["libc", "printf"] | ||
| libc = [] # compile musl libc | ||
| printf = [ "libc" ] # compile printf |
There was a problem hiding this comment.
opinion: I would just put everything under the same libc feature
There was a problem hiding this comment.
Sure, I guess any code from libc if not referenced will be DCE anyway 🤷
| pub extern "C" fn write(fd: c_int, buf: *const c_void, count: usize) -> isize { | ||
| // Only stdout (fd=1) and stderr (fd=2) | ||
| if fd != 1 && fd != 2 { | ||
| return count as isize; |
There was a problem hiding this comment.
question: shuoldn't this return -1, or some other indication of error? and set errno?
There was a problem hiding this comment.
Right, I think that in order to support this properly we would need to generate the bindings to libc headers and use that to reference errno, EBADF etc. But then, it might be better to just have picolibc-sys crate. Anyway I agree we should report an error here somehow.
| pub extern "C" fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize { | ||
| // Only stdin (fd=0) and only if HostRead is defined | ||
| if fd != 0 || !CAPS.host_read() { | ||
| return 0; |
There was a problem hiding this comment.
question: should the case of fd != 0 return -1 and set errno instead?
|
will help with #282 |
499c59d to
2ae0a3a
Compare
2ae0a3a to
d3826af
Compare
d2043ac to
2bd1ff4
Compare
9f5c6c1 to
a59c7ce
Compare
|
Is this still on the table ? |
|
Yes but need approval on licensing before being able to move forward: cncf/foundation#1117 |
65634a7 to
980cb20
Compare
| @@ -1,2 +1,3 @@ | |||
| [build] | |||
| target = "x86_64-unknown-none" | |||
| rustflags = ["-Zdirect-access-external-data"] | |||
There was a problem hiding this comment.
Where does this come from?
There was a problem hiding this comment.
IIRC rustc generated unsupported reallocations without this flag
There was a problem hiding this comment.
This is a nightly flag, right?
Also, this will not apply to comsumers of hyperlight-guest-bin, right?
There was a problem hiding this comment.
I think it's worth to recheck and try to remove it.
There was a problem hiding this comment.
Everything seems to work without the flag, I remove it for now 🤷♂️
c24ce45 to
d9fb9e5
Compare
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
e4caabe to
7b99307
Compare
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
7b99307 to
fb1549f
Compare
|
|
||
| let code = r#"long long x = 0; int main() { return 0; }"#; | ||
| let has = if detect_cc_feature(code)? { 1 } else { 0 }; | ||
| writeln!(file, "#define __IO_LONG_LONG {has}")?; |
There was a problem hiding this comment.
this gets writeln!(file, "#undef __IO_LONG_LONG")?; // minimal format alittle while later (178). Do we need this here?
There was a problem hiding this comment.
did we write this file? is there attribution that is needed?
There was a problem hiding this comment.
If this is really necessary, I think @jprendes just wrote a Rust implementation for this in hyperlight-js. maybe we could use it?
| (void)__tz; | ||
|
|
||
| _current_time(current_time); | ||
| tv->tv_sec = current_time[0]; |
There was a problem hiding this comment.
do we need to check for null here?
| case CLOCK_REALTIME: | ||
| case CLOCK_MONOTONIC: | ||
| _current_time(current_time); | ||
| tp->tv_sec = current_time[0]; |
| Some(vec![ParameterValue::ULong(count as u64)]), | ||
| ReturnType::VecBytes, | ||
| ) { | ||
| Ok(bytes) => { | ||
| let n = bytes.len(); | ||
| unsafe { | ||
| core::ptr::copy_nonoverlapping(bytes.as_ptr(), buf as *mut u8, n); |
There was a problem hiding this comment.
should not rely on the host provided length. nonoverlapping could write past the buffer lenghth. We are in the guest here so it would just cause corruption but might be tough to track down I think
| return -1; | ||
| } | ||
|
|
||
| let slice = unsafe { core::slice::from_raw_parts(buf as *const u8, count) }; |
There was a problem hiding this comment.
do we need a null check on the buf here? https://doc.rust-lang.org/core/slice/fn.from_raw_parts.html#safety
data must be non-null and aligned even for zero-length slices
| obstacle to adoption, that text has been removed. | ||
| Note: The picolibc submodule uses sparse checkout to exclude | ||
| GPL/AGPL-licensed test and script files that are not needed for | ||
| building. Only BSD/MIT/permissive-licensed source files are included. |
There was a problem hiding this comment.
Just wanted to surface this. We should include it in the PR description I think
dblnz
left a comment
There was a problem hiding this comment.
Great work, Tomasz!! This is one hell of a diff and I like it 😆
There was a problem hiding this comment.
If this is really necessary, I think @jprendes just wrote a Rust implementation for this in hyperlight-js. maybe we could use it?
| pub mod paging; | ||
|
|
||
| #[cfg(feature = "libc")] | ||
| mod host_bridge; |
There was a problem hiding this comment.
Is there a place we document or mention the functions needed to be implemented by the host for the guest to have libc work?
I am referring to HostRead and the others from host_bridge.rs
| "# | ||
| ); | ||
|
|
||
| let has = if detect_cc_feature(&code)? { 1 } else { 0 }; |
There was a problem hiding this comment.
These here are quite a lot of invocations of clang. Do you think this can be done in a single call? Something like printing an integer for each builtin and then parsing the output to identify which is supported.
| .flag("-fno-stack-protector") | ||
| .flag("-fstack-clash-protection") | ||
| .flag("-mstack-probe-size=4096") | ||
| // We don't use a different stack for all interrupts, so there |
There was a problem hiding this comment.
I think we have a different stack for the Exceptions.
There was a problem hiding this comment.
How do you see the process of updating to a new picolibc version?
Checkout the new version, verify copyright headers, check the checked out files against the ones in this file, update this file in case files were removed or added?
There was a problem hiding this comment.
Maybe it's worth mentioning in the readme, to have some instructions
|
|
||
| ensure-cargo-hyperlight: | ||
| command -v cargo-hyperlight >/dev/null 2>&1 || cargo install --locked cargo-hyperlight | ||
| cargo install --locked --force --git https://github.com/hyperlight-dev/cargo-hyperlight --branch picolibc cargo-hyperlight |
There was a problem hiding this comment.
This changes to the "official version of the tool" before merging this PR, right?
No description provided.