From 2f9f5f0de17119f91dcea59fc9d0ecee7befd582 Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Thu, 21 Sep 2023 11:45:49 -0500 Subject: [PATCH 1/9] Rust edition - x86_64 --- .cargo/config.toml | 6 ++++ .gitignore | 1 + Cargo.lock | 7 ++++ Cargo.toml | 10 ++++++ rs-nap/Cargo.lock | 7 ++++ rs-nap/Cargo.toml | 8 +++++ rs-nap/src/main.rs | 61 +++++++++++++++++++++++++++++++++ rs-nap/src/support.rs | 7 ++++ rs-nap/src/support/noarch.rs | 65 ++++++++++++++++++++++++++++++++++++ rs-nap/src/support/x86_64.rs | 40 ++++++++++++++++++++++ rust-toolchain.toml | 4 +++ 11 files changed, 216 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 rs-nap/Cargo.lock create mode 100644 rs-nap/Cargo.toml create mode 100644 rs-nap/src/main.rs create mode 100644 rs-nap/src/support.rs create mode 100644 rs-nap/src/support/noarch.rs create mode 100644 rs-nap/src/support/x86_64.rs create mode 100644 rust-toolchain.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..819fac3 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[build] +rustflags = [ + "-Clink-args=-nostartfiles", + "-Clink-args=-Wl,-n,-N,--no-dynamic-linker,--build-id=none", + "-Crelocation-model=static" +] \ No newline at end of file diff --git a/.gitignore b/.gitignore index 553042b..c771476 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea out/ +target/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6ddf31f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "rs-nap" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..cfdc123 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[workspace] +resolver = "2" +members = ["rs-nap"] + +[profile.release] +strip = true +opt-level = "z" +codegen-units = 1 +panic = "abort" +lto = true diff --git a/rs-nap/Cargo.lock b/rs-nap/Cargo.lock new file mode 100644 index 0000000..6ddf31f --- /dev/null +++ b/rs-nap/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "rs-nap" +version = "0.1.0" diff --git a/rs-nap/Cargo.toml b/rs-nap/Cargo.toml new file mode 100644 index 0000000..dab6002 --- /dev/null +++ b/rs-nap/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rs-nap" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/rs-nap/src/main.rs b/rs-nap/src/main.rs new file mode 100644 index 0000000..a067d57 --- /dev/null +++ b/rs-nap/src/main.rs @@ -0,0 +1,61 @@ +#![no_std] +#![no_main] +#![feature(naked_functions)] + +mod support; +use support::*; +use core::arch::asm; +use core::slice::from_raw_parts as mkslice; + +#[no_mangle] +pub unsafe fn nap(args: &[*const u8]) { + let mut sleep_time:usize = 10; + + if args.len() < 2 { + sleep(sleep_time, false); + } else { + let (seconds,_) = from_radix_10(mkslice(args[1], strlen(args[1]))); + let mut good_input = seconds > 0 && seconds < 1000000000; + + if good_input { + sleep_time = seconds; + } else { + good_input = false; + } + + sleep(sleep_time, good_input); + } + + print_str(b"Done!\n"); + sys_exit(0); +} + +pub unsafe fn sleep(seconds: usize, good_input: bool) { + if good_input == false { + print_str(b"Bad input. "); + } + print_str(b"Sleeping for "); + print_num(seconds); + print_str(b" seconds...\n"); + sys_sleep(seconds) +} + +#[no_mangle] +#[naked] +pub unsafe extern "C" fn _start() { + #[cfg(all(target_arch="x86_64", target_os="linux"))] + asm!("mov rdi, rsp", "call get_args", options(noreturn)) +} + +#[no_mangle] +pub unsafe fn get_args(stack_top: *const u8) { + let argc = *(stack_top as *const u64); + let argv = stack_top.add(8) as *const *const u8; + let args = mkslice(argv, argc as usize); + nap(args) +} + +#[panic_handler] +unsafe fn my_panic(_info: &core::panic::PanicInfo) -> ! { + sys_exit(255) +} diff --git a/rs-nap/src/support.rs b/rs-nap/src/support.rs new file mode 100644 index 0000000..b19e8c2 --- /dev/null +++ b/rs-nap/src/support.rs @@ -0,0 +1,7 @@ +#[cfg_attr(all(target_arch="x86_64", target_os="linux"), path="support/x86_64.rs")] +mod support; +pub use support::*; + +#[path="support/noarch.rs"] +mod noarch; +pub use noarch::*; diff --git a/rs-nap/src/support/noarch.rs b/rs-nap/src/support/noarch.rs new file mode 100644 index 0000000..8f33330 --- /dev/null +++ b/rs-nap/src/support/noarch.rs @@ -0,0 +1,65 @@ +use crate::support::sys_write; + +pub unsafe fn strlen(mut s: *const u8) -> usize { + let mut count = 0; + while *s != b'\0' { + count += 1; + s = s.add(1); + } + count +} + +pub fn print_str(s: &[u8]) { + unsafe { + sys_write(s.as_ptr(), s.len()); + } +} + +pub fn print_num(n: usize) { + if n > 9 { + print_num(n / 10); + } + let c = b'0' + (n % 10) as u8; + print_str(&[c]); +} + +fn nth(n: u8) -> usize +{ + let mut i:usize = 0; + for _ in 0..n { + i = i + 1; + } + i +} + +pub fn ascii_to_digit(character: u8) -> Option { + match character { + b'0' => Some(nth(0)), + b'1' => Some(nth(1)), + b'2' => Some(nth(2)), + b'3' => Some(nth(3)), + b'4' => Some(nth(4)), + b'5' => Some(nth(5)), + b'6' => Some(nth(6)), + b'7' => Some(nth(7)), + b'8' => Some(nth(8)), + b'9' => Some(nth(9)), + _ => None, + } +} + +pub fn from_radix_10(text: &[u8]) -> (usize, usize) { + let mut index:usize = 0; + let mut number:usize = 0; + while index != text.len() { + if let Some(digit) = ascii_to_digit(text[index]) { + number *= nth(10); + number += digit; + index += 1; + } else { + break; + } + } + (number, index) +} + diff --git a/rs-nap/src/support/x86_64.rs b/rs-nap/src/support/x86_64.rs new file mode 100644 index 0000000..c77d87d --- /dev/null +++ b/rs-nap/src/support/x86_64.rs @@ -0,0 +1,40 @@ +use core::arch::asm; + +pub unsafe fn sys_exit(exit_code:usize) -> ! { + asm!("syscall", + in("rax") 60, + in("rdi") exit_code, + options(nostack, noreturn) + ) +} + +pub unsafe fn sys_write(buffer: *const u8, count: usize) { + asm!("syscall", + inout("rax") 1 => _, + in("rdi") 1, + in("rsi") buffer, + in("rdx") count, + lateout("rcx") _, + lateout("r11") _, + options(nostack) + ) +} + +#[repr(C)] +struct timespec { + pub tv_sec: isize, + pub tv_nsec: isize, +} + +pub unsafe fn sys_sleep(seconds: usize) { + let sleep_time = timespec { + tv_sec: seconds as isize, + tv_nsec: 0 + }; + + asm!("syscall", + in("rax") 35, + in("rdi") &sleep_time, + in("rsi") 0, + options(nostack)) +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..1ea7d64 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly" +components = [ "rustfmt", "clippy" ] +targets = [ "x86_64-unknown-linux-gnu" ] From 89b6d9fda4662262d8a07352a421b51ef7875038 Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Thu, 21 Sep 2023 16:47:28 -0500 Subject: [PATCH 2/9] aarch64 support - todo: fix write syscall --- .cargo/config.toml | 13 ++++++++-- rs-nap/README.md | 44 ++++++++++++++++++++++++++++++++ rs-nap/src/main.rs | 14 +++-------- rs-nap/src/support.rs | 1 + rs-nap/src/support/aarch64.rs | 47 +++++++++++++++++++++++++++++++++++ rs-nap/src/support/interop.rs | 5 ++++ rs-nap/src/support/x86_64.rs | 19 +++++++++----- rust-toolchain.toml | 5 +++- 8 files changed, 128 insertions(+), 20 deletions(-) create mode 100644 rs-nap/README.md create mode 100644 rs-nap/src/support/aarch64.rs create mode 100644 rs-nap/src/support/interop.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 819fac3..abf44e2 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,15 @@ -[build] +[target.x86_64-unknown-linux-gnu] +linker = "x86_64-linux-gnu-gcc" rustflags = [ "-Clink-args=-nostartfiles", "-Clink-args=-Wl,-n,-N,--no-dynamic-linker,--build-id=none", "-Crelocation-model=static" -] \ No newline at end of file +] + +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" +rustflags = [ + "-Clink-args=-nostartfiles", + "-Clink-args=-Wl,-n,-N,--no-dynamic-linker,--build-id=none", + "-Crelocation-model=static" +] diff --git a/rs-nap/README.md b/rs-nap/README.md new file mode 100644 index 0000000..9d0886c --- /dev/null +++ b/rs-nap/README.md @@ -0,0 +1,44 @@ +# Rust rewrite + +## Goals + +### Feature parity + +- [x] Maintain roughly the same binary size +- [x] Zero requirements other than the linux kernel +- [x] Increased readability over assembly +- [x] Shared code base for all architectures + +### Architecture support + +- [x] x86_64 implementation +- [x] aarch64 implementation + +## Run on a native processor + +```sh +# Build +cargo build --release +# Display file size +ls -lah ./target/release/rs-nap +# Run for 3 seconds +./target/release/rs-nap 3 +``` + +## Run on an emulated processor + +```sh +# Install cross compiler and emulation layer + +# Debian-based distros +sudo apt -y install gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu qemu-user-static +``` + +```sh +# Build +cargo build --target aarch64-unknown-linux-gnu --release +# Display file size +ls -lah target/aarch64-unknown-linux-gnu/release/rs-nap +# Run for 3 seconds +qemu-aarch64-static target/aarch64-unknown-linux-gnu/release/rs-nap 3 +``` diff --git a/rs-nap/src/main.rs b/rs-nap/src/main.rs index a067d57..08a34a8 100644 --- a/rs-nap/src/main.rs +++ b/rs-nap/src/main.rs @@ -4,11 +4,10 @@ mod support; use support::*; -use core::arch::asm; use core::slice::from_raw_parts as mkslice; #[no_mangle] -pub unsafe fn nap(args: &[*const u8]) { +pub unsafe fn nap(args: &[*const u8]) -> ! { let mut sleep_time:usize = 10; if args.len() < 2 { @@ -41,15 +40,8 @@ pub unsafe fn sleep(seconds: usize, good_input: bool) { } #[no_mangle] -#[naked] -pub unsafe extern "C" fn _start() { - #[cfg(all(target_arch="x86_64", target_os="linux"))] - asm!("mov rdi, rsp", "call get_args", options(noreturn)) -} - -#[no_mangle] -pub unsafe fn get_args(stack_top: *const u8) { - let argc = *(stack_top as *const u64); +unsafe fn get_args(stack_top: *const u8) { + let argc = *(stack_top as *const usize); let argv = stack_top.add(8) as *const *const u8; let args = mkslice(argv, argc as usize); nap(args) diff --git a/rs-nap/src/support.rs b/rs-nap/src/support.rs index b19e8c2..47e42b6 100644 --- a/rs-nap/src/support.rs +++ b/rs-nap/src/support.rs @@ -1,4 +1,5 @@ #[cfg_attr(all(target_arch="x86_64", target_os="linux"), path="support/x86_64.rs")] +#[cfg_attr(all(target_arch="aarch64", target_os="linux"), path="support/aarch64.rs")] mod support; pub use support::*; diff --git a/rs-nap/src/support/aarch64.rs b/rs-nap/src/support/aarch64.rs new file mode 100644 index 0000000..1a3d2d9 --- /dev/null +++ b/rs-nap/src/support/aarch64.rs @@ -0,0 +1,47 @@ +use core::arch::asm; +use core::slice::from_raw_parts as mkslice; + +mod interop; +use interop::timespec; + +#[no_mangle] +#[naked] +unsafe extern "C" fn _start() { + // Move the stack pointer before it gets clobbered + asm!("mov fp, sp", + "mov x0, fp", + "bl get_args", + options(noreturn)) +} + +pub unsafe fn sys_exit(exit_code:usize) -> ! { + asm!("svc 0", + in("x8") 93, + in("x0") exit_code, + options(nostack, noreturn) + ) +} + +pub unsafe fn sys_write(buffer: *const u8, count: usize) { + asm!("svc 0", "ret", + in("x8") 64, + inlateout("x0") 1 => _, + in("x1") buffer, + in("x2") count, + options(nostack, preserves_flags) + ) +} + +pub unsafe fn sys_sleep(seconds: usize) { + let sleep_time = timespec { + tv_sec: seconds as isize, + tv_nsec: 0 + }; + + asm!("svc 0", "ret", + inlateout("x0") &sleep_time => _, + in("x1") 0, + in("x8") 101, + options(nostack, preserves_flags) + ) +} diff --git a/rs-nap/src/support/interop.rs b/rs-nap/src/support/interop.rs new file mode 100644 index 0000000..02220fe --- /dev/null +++ b/rs-nap/src/support/interop.rs @@ -0,0 +1,5 @@ +#[repr(C)] +pub struct timespec { + pub tv_sec: isize, + pub tv_nsec: isize, +} diff --git a/rs-nap/src/support/x86_64.rs b/rs-nap/src/support/x86_64.rs index c77d87d..62e231a 100644 --- a/rs-nap/src/support/x86_64.rs +++ b/rs-nap/src/support/x86_64.rs @@ -1,4 +1,17 @@ use core::arch::asm; +use core::slice::from_raw_parts as mkslice; + +mod interop; +use interop::timespec; + +#[no_mangle] +#[naked] +unsafe extern "C" fn _start() { + // Move the stack pointer before it gets clobbered + asm!("mov rdi, rsp", + "call get_args", + options(noreturn)) +} pub unsafe fn sys_exit(exit_code:usize) -> ! { asm!("syscall", @@ -20,12 +33,6 @@ pub unsafe fn sys_write(buffer: *const u8, count: usize) { ) } -#[repr(C)] -struct timespec { - pub tv_sec: isize, - pub tv_nsec: isize, -} - pub unsafe fn sys_sleep(seconds: usize) { let sleep_time = timespec { tv_sec: seconds as isize, diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 1ea7d64..440fdae 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,7 @@ [toolchain] channel = "nightly" components = [ "rustfmt", "clippy" ] -targets = [ "x86_64-unknown-linux-gnu" ] +targets = [ + "x86_64-unknown-linux-gnu", + "aarch64-unknown-linux-gnu" +] From e1029a6100f6f623bd0104fe9bccc57bbc2f4cef Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Mon, 25 Sep 2023 11:09:40 -0500 Subject: [PATCH 3/9] simplification and arm64 working --- rs-nap/src/main.rs | 34 +++++++++++++++++----------------- rs-nap/src/support/aarch64.rs | 20 ++++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/rs-nap/src/main.rs b/rs-nap/src/main.rs index 08a34a8..967cc17 100644 --- a/rs-nap/src/main.rs +++ b/rs-nap/src/main.rs @@ -9,34 +9,34 @@ use core::slice::from_raw_parts as mkslice; #[no_mangle] pub unsafe fn nap(args: &[*const u8]) -> ! { let mut sleep_time:usize = 10; + let mut good_input:bool = false; - if args.len() < 2 { - sleep(sleep_time, false); - } else { - let (seconds,_) = from_radix_10(mkslice(args[1], strlen(args[1]))); - let mut good_input = seconds > 0 && seconds < 1000000000; - - if good_input { - sleep_time = seconds; - } else { - good_input = false; - } - - sleep(sleep_time, good_input); + if args.len() > 1 { + (sleep_time, good_input) = get_sleep_time(args[1]); } + sleep(sleep_time, good_input); + print_str(b"Done!\n"); - sys_exit(0); + sys_exit(0) } -pub unsafe fn sleep(seconds: usize, good_input: bool) { +pub unsafe fn sleep(mut sleep_time: usize, good_input: bool) { if good_input == false { + sleep_time = 10; print_str(b"Bad input. "); } + print_str(b"Sleeping for "); - print_num(seconds); + print_num(sleep_time); print_str(b" seconds...\n"); - sys_sleep(seconds) + + sys_sleep(sleep_time); +} + +unsafe fn get_sleep_time(arg: *const u8) -> (usize, bool) { + let (seconds,_) = from_radix_10(mkslice(arg, strlen(arg))); + (seconds, seconds > 0 && seconds < 1000000000) } #[no_mangle] diff --git a/rs-nap/src/support/aarch64.rs b/rs-nap/src/support/aarch64.rs index 1a3d2d9..b7ab2fb 100644 --- a/rs-nap/src/support/aarch64.rs +++ b/rs-nap/src/support/aarch64.rs @@ -1,5 +1,4 @@ use core::arch::asm; -use core::slice::from_raw_parts as mkslice; mod interop; use interop::timespec; @@ -16,19 +15,20 @@ unsafe extern "C" fn _start() { pub unsafe fn sys_exit(exit_code:usize) -> ! { asm!("svc 0", - in("x8") 93, + in("w8") 93, in("x0") exit_code, options(nostack, noreturn) ) } pub unsafe fn sys_write(buffer: *const u8, count: usize) { - asm!("svc 0", "ret", - in("x8") 64, - inlateout("x0") 1 => _, - in("x1") buffer, - in("x2") count, - options(nostack, preserves_flags) + asm!("mov x0, #1", + "mov x1, {buffer}", + "mov x2, {count}", + "mov x8, #64", + "svc #0", + buffer = in(reg) buffer, + count = in(reg) count ) } @@ -38,8 +38,8 @@ pub unsafe fn sys_sleep(seconds: usize) { tv_nsec: 0 }; - asm!("svc 0", "ret", - inlateout("x0") &sleep_time => _, + asm!("svc 0", + in("x0") &sleep_time, in("x1") 0, in("x8") 101, options(nostack, preserves_flags) From b32f24203c88127ae47296d1e12f96a4c92400a4 Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Mon, 25 Sep 2023 11:09:40 -0500 Subject: [PATCH 4/9] simplification and arm64 working --- rs-nap/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rs-nap/README.md b/rs-nap/README.md index 9d0886c..64681f5 100644 --- a/rs-nap/README.md +++ b/rs-nap/README.md @@ -14,6 +14,22 @@ - [x] x86_64 implementation - [x] aarch64 implementation +#### Architecture specific implementation notes + +For each new architecture: + +1. Add a file to the `support` subfolder which implements + - The startup code (`_start`) to get arguments from the stack + - and the following linux kernel service calls + - `sys_exit` to call `exit` + - `sys_write` to call `write` to stdout 1 + - and `sys_sleep` +2. Add a platform specific entry to `support.rs` in the form of a `cfg_attr` +3. Add a platform target to `.cargo/config.toml` +4. Add a toolchain target to `rust-toolchain.toml` +5. Update this `README.md` with the new platform build and run commands +6. Update any CI/CD (future) to build the binary for the target platform + ## Run on a native processor ```sh From 1ccb36c31e3c50e62680950eb44359c02b7f8b18 Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Mon, 25 Sep 2023 13:37:36 -0500 Subject: [PATCH 5/9] fix for register clobbering --- rs-nap/src/support/aarch64.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/rs-nap/src/support/aarch64.rs b/rs-nap/src/support/aarch64.rs index b7ab2fb..329c736 100644 --- a/rs-nap/src/support/aarch64.rs +++ b/rs-nap/src/support/aarch64.rs @@ -22,13 +22,17 @@ pub unsafe fn sys_exit(exit_code:usize) -> ! { } pub unsafe fn sys_write(buffer: *const u8, count: usize) { - asm!("mov x0, #1", - "mov x1, {buffer}", - "mov x2, {count}", - "mov x8, #64", - "svc #0", - buffer = in(reg) buffer, - count = in(reg) count + asm!( + "mov x0, #1", + "mov x1, {buffer}", + "mov x2, {count}", + "mov x8, #64", + "svc #0", + buffer = inout(reg) buffer => _, + count = inout(reg) count => _, + out("x0") _, + out("x8") _, + options(nostack) ) } From 4f518b4a2488a864aa64209e9a5957f04bff38a6 Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Mon, 25 Sep 2023 13:56:37 -0500 Subject: [PATCH 6/9] Clean up sys_write implementation --- rs-nap/src/support/aarch64.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/rs-nap/src/support/aarch64.rs b/rs-nap/src/support/aarch64.rs index 329c736..3efe150 100644 --- a/rs-nap/src/support/aarch64.rs +++ b/rs-nap/src/support/aarch64.rs @@ -22,16 +22,11 @@ pub unsafe fn sys_exit(exit_code:usize) -> ! { } pub unsafe fn sys_write(buffer: *const u8, count: usize) { - asm!( - "mov x0, #1", - "mov x1, {buffer}", - "mov x2, {count}", - "mov x8, #64", - "svc #0", - buffer = inout(reg) buffer => _, - count = inout(reg) count => _, - out("x0") _, - out("x8") _, + asm!("svc #0", + inout("x0") 1 => _, + inout("x1") buffer => _, + inout("x2") count => _, + inout("x8") 64 => _, options(nostack) ) } From 1d59284aabb1e782c4e1bbd052803f7f3e82f45c Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Wed, 18 Dec 2024 14:24:20 -0600 Subject: [PATCH 7/9] Update to latest Rust specs --- rs-nap/src/support/aarch64.rs | 11 ++++++----- rs-nap/src/support/x86_64.rs | 10 +++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/rs-nap/src/support/aarch64.rs b/rs-nap/src/support/aarch64.rs index 3efe150..d430bb1 100644 --- a/rs-nap/src/support/aarch64.rs +++ b/rs-nap/src/support/aarch64.rs @@ -1,4 +1,4 @@ -use core::arch::asm; +use core::arch::{asm,naked_asm}; mod interop; use interop::timespec; @@ -7,10 +7,11 @@ use interop::timespec; #[naked] unsafe extern "C" fn _start() { // Move the stack pointer before it gets clobbered - asm!("mov fp, sp", - "mov x0, fp", - "bl get_args", - options(noreturn)) + naked_asm!( + "mov fp, sp", + "mov x0, fp", + "bl get_args" + ) } pub unsafe fn sys_exit(exit_code:usize) -> ! { diff --git a/rs-nap/src/support/x86_64.rs b/rs-nap/src/support/x86_64.rs index 62e231a..beb0a64 100644 --- a/rs-nap/src/support/x86_64.rs +++ b/rs-nap/src/support/x86_64.rs @@ -1,5 +1,4 @@ -use core::arch::asm; -use core::slice::from_raw_parts as mkslice; +use core::arch::{asm,naked_asm}; mod interop; use interop::timespec; @@ -8,9 +7,10 @@ use interop::timespec; #[naked] unsafe extern "C" fn _start() { // Move the stack pointer before it gets clobbered - asm!("mov rdi, rsp", - "call get_args", - options(noreturn)) + naked_asm!( + "mov rdi, rsp", + "call get_args" + ) } pub unsafe fn sys_exit(exit_code:usize) -> ! { From 51a01d11728f7062214c7213734395ad7698cb2e Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Wed, 18 Dec 2024 14:24:42 -0600 Subject: [PATCH 8/9] Add rust output to GH action build --- .github/workflows/main.yml | 28 +++++++---------------- Makefile | 15 +++--------- run-tests.sh | 47 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 32 deletions(-) create mode 100755 run-tests.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e7f16a0..d73a4f5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,30 +12,18 @@ jobs: - name: Install dependencies run: | sudo apt-get update -y - sudo apt-get install -y make nasm binutils binutils-aarch64-linux-gnu + sudo apt-get install -y curl make nasm qemu-user-static \ + gcc-x86-64-linux-gnu binutils-x86-64-linux-gnu \ + gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu + curl https://sh.rustup.rs -sSf | sh -s -- -y - - name: Build via Makefile - run: make ci_build + - name: Build and Test + run: | + . "$HOME/.cargo/env" + make -s ci_tests - name: Public artifact uses: actions/upload-artifact@v1 with: name: Build Artifact path: out/ - - test: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout Repo - uses: actions/checkout@v2 - - - name: Install dependencies - run: | - sudo apt-get update -y - sudo apt-get install -y make nasm binutils binutils-aarch64-linux-gnu - sudo wget https://github.com/multiarch/qemu-user-static/releases/download/v7.1.0-2/qemu-aarch64-static -O /usr/sbin/qemu-aarch64-static - sudo chmod +x /usr/sbin/qemu-aarch64-static - - - name: Run Tests - run: make ci_tests diff --git a/Makefile b/Makefile index 5fd520f..5887c8c 100644 --- a/Makefile +++ b/Makefile @@ -9,21 +9,12 @@ ci_build: x86_64-linux-gnu-ld -m elf_x86_64 -z noseparate-code -z noexecstack --strip-all -o out/nap nap.o && rm nap.o aarch64-linux-gnu-as nap-aarch64.s -o nap-aarch64.o aarch64-linux-gnu-ld -z noseparate-code -z noexecstack --strip-all -o out/nap-aarch64 nap-aarch64.o && rm nap-aarch64.o + cargo build --release --target-dir target --target x86_64-unknown-linux-gnu && cp target/x86_64-unknown-linux-gnu/release/rs-nap out/rs-nap-x86_64 + cargo build --release --target-dir target --target aarch64-unknown-linux-gnu && cp target/aarch64-unknown-linux-gnu/release/rs-nap out/rs-nap-aarch64 ls -la out/ ci_tests: ci_build - if [ $$(arch) = "x86_64" ]; then \ - echo "[x86_64] Testing 1s nap"; \ - timeout 3s out/nap 1 2>&1 > /dev/null; \ - echo "[x86_64] Testing 10s default/bad input nap"; \ - timeout 12s out/nap bad_arg ; if [ $$? = "1" ]; then true; else false; fi; \ - else \ - echo "x86_64 testing not available on aarch64 platform"; \ - fi - echo "[aarch64] Testing 1s nap" - timeout 3s qemu-aarch64-static out/nap-aarch64 1 2>&1 > /dev/null - echo "[aarch64] Testing 10s default/bad input nap" - timeout 12s qemu-aarch64-static out/nap-aarch64 bad_arg ; if [ $$? = "1" ]; then true; else false; fi + @bash run-tests.sh tests: install if [ $$(arch) = "x86_64" ]; then \ diff --git a/run-tests.sh b/run-tests.sh new file mode 100755 index 0000000..812731f --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,47 @@ +#!/bin/bash +set -euo pipefail + +# Runs a qemu test for a given architecture +# Ideally all builds will use the method below +run_qemu() { + local arch=$1 + local seconds=$2 + local binary=$3 + local qemu="qemu-$arch-static" + if [[ $binary == *"rs-"* ]]; then + icon="🦀" + else + icon="🦬" + fi + + echo "$icon $arch - Testing ${seconds}s nap" + time timeout $(($seconds+1))s $qemu $binary $seconds &>/dev/null +} + +## NASM tests - likely problems in the code somewhere + +# NASM amd64 tests (does not work on aarch64 qemu) +if [ $(arch) == "x86_64" ]; then + echo "🦬 x86_64 - Testing 1s nap" + timeout 2s ./out/nap 1 &>/dev/null + echo "🦬 x86_64 - Testing 10s nap" + timeout 11s ./out/nap 10 &>/dev/null +fi + +# NASM arm64 tests (does not work on x86_64 qemu) +if [ $(arch) == "aarch64" ]; then + echo "🦬 aarch64 - Testing 1s nap" + timeout 2s ./out/nap-aarch64 1 &>/dev/null + echo "🦬 aarch64 - Testing 10s nap" + timeout 11s ./out/nap-aarch64 10 &>/dev/null +fi + +## Rust tests - rust works everywhere + +# Rust amd64 tests +run_qemu x86_64 1 ./out/rs-nap-x86_64 +run_qemu x86_64 10 ./out/rs-nap-x86_64 + +# Rust arm64 tests +run_qemu aarch64 1 ./out/rs-nap-aarch64 +run_qemu aarch64 10 ./out/rs-nap-aarch64 From 1a971956c3374cad1e359803e58015de833eb0a6 Mon Sep 17 00:00:00 2001 From: Jonathan DeMarks Date: Wed, 18 Dec 2024 14:26:21 -0600 Subject: [PATCH 9/9] Mandatory update to v4 upload artifact --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d73a4f5..8070a74 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,8 +22,8 @@ jobs: . "$HOME/.cargo/env" make -s ci_tests - - name: Public artifact - uses: actions/upload-artifact@v1 + - name: Publish artifact + uses: actions/upload-artifact@v4 with: name: Build Artifact path: out/