-
-
Save sunfishcode/a30b3420aedce2cb5a08985aebc0e7ea to your computer and use it in GitHub Desktop.
origin.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Cargo.toml b/Cargo.toml | |
index cf5d560..32b2ddf 100644 | |
--- a/Cargo.toml | |
+++ b/Cargo.toml | |
@@ -9,6 +9,16 @@ repository = "https://git.sr.ht/~zackw/root-scaffold" | |
license = "GPL-3.0-or-later" | |
keywords = ["linux", "initrd", "initramfs"] | |
+[dependencies.origin] | |
+version = "0.23.0" | |
+default-features = false | |
+features = [ | |
+ "origin-start", | |
+ "eh-personality-continue", | |
+ "panic-handler-trap", | |
+ "optimize_for_size" | |
+] | |
+ | |
[dependencies.rustix] | |
version = "0.38" | |
default-features = false | |
diff --git a/src/glue/entry.rs b/src/glue/entry.rs | |
index 7440f3f..1200bdc 100644 | |
--- a/src/glue/entry.rs | |
+++ b/src/glue/entry.rs | |
@@ -9,68 +9,30 @@ use crate::core::arch::global_asm; | |
use crate::alloc::vec::Vec; | |
use crate::core::ffi; | |
-use crate::core::mem::transmute; | |
-use crate::core::option::Option::Some; | |
-use crate::core::ptr; | |
use crate::rustix::param; | |
-use crate::rustix::runtime; | |
use crate::rustix::stdio; | |
-// This is the actual program entry point. It has to be written in | |
-// assembly language because the entry point is not invoked using the | |
-// normal calling convention. This could be a #[naked] function, if | |
-// that were a stable feature. Currently only implemented for x86-64. | |
-#[cfg(target_arch = "x86_64")] | |
-global_asm!( | |
- ".global _start", | |
- "_start:", | |
- | |
- // When control reaches this point, RSP is aligned to a multiple | |
- // of 16, is usable as a stack pointer, and points to the | |
- // information block. RDX is either null or a function pointer to | |
- // be called immediately before exiting. All other registers have | |
- // unspecified values. | |
- "mov rdi, rsp", // first arg to Rust 'start': the info block | |
- "mov rsi, rdx", // second arg to Rust 'start': possible atexit hook | |
- "xor rbp, rbp", // null frame pointer | |
- "push rbp", // null return address | |
- "jmp {start}", // I'd like to fall through to start but there's no way | |
- // to guarantee it's the next thing in the object file | |
- start = sym start, | |
-); | |
- | |
-#[cfg(not(target_arch = "x86_64"))] | |
-#[no_mangle] | |
-pub fn _start() -> ! { | |
- compile_error!("need an implementation of _start for this architecture"); | |
- loop {} | |
-} | |
- | |
-/// Called by the assembly code above. Must not return. | |
+/// Called by origin. | |
/// 'infoblock' points to the command line arguments and environment | |
-/// variables. 'atexit_hook' is "a function pointer that the application | |
-/// should register with atexit(3)"; it is most likely null. | |
-unsafe fn start(infoblock: &usize, atexit_hook: *const ()) -> ! { | |
- let status = { | |
- let (argv, envp) = parse_infoblock(infoblock); | |
- crate::main( | |
- argv.as_slice(), | |
- envp.as_slice(), | |
- stdio::stdin(), | |
- stdio::stdout(), | |
- stdio::stderr(), | |
- ) | |
- }; | |
+/// variables. | |
+#[no_mangle] | |
+unsafe fn origin_main( | |
+ argc: usize, | |
+ argv: *mut *mut u8, | |
+ envp: *mut *mut u8, | |
+) -> i32 { | |
+ let (argv, envp) = parse_infoblock(argc, argv, envp); | |
- // We don't bother implementing atexit() in full generality. | |
- // Just call the pointer if it's not null. | |
- if let Some(atexit_hook) = atexit_hook.as_ref() { | |
- let atexit_ptr: extern "C" fn() = transmute(atexit_hook); | |
- atexit_ptr(); | |
- } | |
+ let status = crate::main( | |
+ argv.as_slice(), | |
+ envp.as_slice(), | |
+ stdio::stdin(), | |
+ stdio::stdout(), | |
+ stdio::stderr(), | |
+ ); | |
- runtime::exit_group(status) | |
+ status | |
} | |
/// Convert the command line arguments and environment variables to | |
@@ -80,17 +42,16 @@ unsafe fn start(infoblock: &usize, atexit_hook: *const ()) -> ! { | |
/// | |
/// SAFETY: The information-block argument must actually be a process | |
/// information block as defined by the psABI. | |
-unsafe fn parse_infoblock(infoblock: &usize) -> (Vec<&[u8]>, Vec<&[u8]>) { | |
- let argc = *infoblock; | |
- let kernel_argv = | |
- ptr::from_ref(infoblock).add(1).cast::<*const ffi::c_char>(); | |
- let kernel_envv = kernel_argv.add(argc + 1); | |
- | |
+unsafe fn parse_infoblock( | |
+ argc: usize, | |
+ kernel_argv: *mut *mut u8, | |
+ kernel_envv: *mut *mut u8, | |
+) -> (Vec<&'static [u8]>, Vec<&'static [u8]>) { | |
// This call must happen before any other call into rustix; | |
// in particular, before the first use of the global allocator | |
// (which will invoke mmap via rustix) and before anything that | |
// might panic. | |
- param::init(kernel_envv.cast_mut().cast::<*mut u8>()); | |
+ param::init(kernel_envv.cast::<*mut u8>()); | |
let mut envc = 0; | |
while !(*kernel_envv.add(envc)).is_null() { | |
@@ -99,12 +60,12 @@ unsafe fn parse_infoblock(infoblock: &usize) -> (Vec<&[u8]>, Vec<&[u8]>) { | |
let mut argv = Vec::with_capacity(argc); | |
for arg in 0..argc { | |
- argv.push(ffi::CStr::from_ptr(*(kernel_argv.add(arg))).to_bytes()); | |
+ argv.push(ffi::CStr::from_ptr((*kernel_argv.add(arg)).cast()).to_bytes()); | |
} | |
let mut envv = Vec::with_capacity(envc); | |
for env in 0..envc { | |
- envv.push(ffi::CStr::from_ptr(*(kernel_envv.add(env))).to_bytes()); | |
+ envv.push(ffi::CStr::from_ptr((*kernel_envv.add(env)).cast()).to_bytes()); | |
} | |
(argv, envv) | |
diff --git a/src/glue/mem.rs b/src/glue/mem.rs | |
deleted file mode 100644 | |
index 5e625ab..0000000 | |
--- a/src/glue/mem.rs | |
+++ /dev/null | |
@@ -1,36 +0,0 @@ | |
-//! Low-level memory manipulation primitives. Only what is actually | |
-//! used. Basic byte-at-a-time loops cribbed from compiler-builtins; | |
-//! on x86-64 rustc 1.80 does a perfectly fine job of unrolling and | |
-//! vectorizing these without our help. | |
- | |
-use crate::core::ffi; | |
- | |
-#[no_mangle] | |
-pub unsafe extern "C" fn memcpy( | |
- dest: *mut u8, | |
- src: *const u8, | |
- n: usize, | |
-) -> *mut u8 { | |
- for i in 0..n { | |
- *dest.add(i) = *src.add(i); | |
- } | |
- dest | |
-} | |
- | |
-#[no_mangle] | |
-pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 { | |
- for i in 0..n { | |
- *s.add(i) = c as u8; | |
- } | |
- s | |
-} | |
- | |
-#[no_mangle] | |
-pub unsafe extern "C" fn strlen(mut s: *const ffi::c_char) -> usize { | |
- let mut n = 0; | |
- while *s != 0 { | |
- n += 1; | |
- s = s.add(1); | |
- } | |
- n | |
-} | |
diff --git a/src/glue/mod.rs b/src/glue/mod.rs | |
index 1fba2a1..b0f9b46 100644 | |
--- a/src/glue/mod.rs | |
+++ b/src/glue/mod.rs | |
@@ -1,12 +1,6 @@ | |
//! Rust language glue required because we are [no_std] and [no_main] | |
//! and *not* using an '<arch>-unknown-linux-none' target nor a | |
//! nightly toolchain. | |
-//! | |
-//! Much of this logic was cribbed from the `origin` crate | |
-//! (<https://github.com/sunfishcode/origin>) which I would have | |
-//! _liked_ to just use, but it requires nightly Rust. | |
mod alloc; | |
mod entry; | |
-mod mem; | |
-mod panic; | |
diff --git a/src/glue/panic.rs b/src/glue/panic.rs | |
deleted file mode 100644 | |
index 8b98ce7..0000000 | |
--- a/src/glue/panic.rs | |
+++ /dev/null | |
@@ -1,48 +0,0 @@ | |
-//! Panic handling glue. No unwinding is attempted. I honestly don't | |
-//! understand why most of this is necessary given that the crate is | |
-//! compiled with panic=abort. | |
- | |
-use crate::core::arch::asm; | |
-use crate::core::panic; | |
-use crate::rustix::process; | |
- | |
-/// Roughly POSIX-compliant implementation of C abort(). | |
-pub(crate) fn abort() -> ! { | |
- let _ = process::kill_current_process_group(process::Signal::Abort); | |
- | |
- // If we get here, the initial kill failed. POSIX would have us | |
- // unmask SIGABRT, reset its disposition, then try again. | |
- // However, rustix does not currently provide usable wrappers for | |
- // sigprocmask and sigaction, and honestly it feels like excessive | |
- // cleverness given that nobody's installing signal handlers in | |
- // this program in the first place. Still, *some* kind of a | |
- // backstop seems appropriate. I'd use core::intrinsics::abort | |
- // here but you can't do that with stable rustc, so this is one of | |
- // (currently) two places where we are stuck inserting some | |
- // assembly language. | |
- loop { | |
- unsafe { | |
- #[cfg(target_arch = "x86_64")] | |
- asm!("ud2"); | |
- #[cfg(not(target_arch = "x86_64"))] | |
- compile_error!("need a trap instruction for this architecture"); | |
- } | |
- } | |
-} | |
- | |
-/// Panic handler. You would *think* it would be unnecessary to | |
-/// define this function in a crate that is compiled with panic=abort, | |
-/// but you would be wrong. | |
-#[panic_handler] | |
-fn panic(_info: &panic::PanicInfo<'_>) -> ! { | |
- abort(); | |
-} | |
- | |
-/// Exception-handling personality routine. Same complaint as above. | |
-/// Also, I *should* be able to declare this as #[lang = "eh_personality"] | |
-/// instead of shoving it into the link with #[no_mangle] and baling wire, | |
-/// but, say it with me, you can't do that with stable rustc. | |
-#[no_mangle] | |
-pub unsafe extern "C" fn rust_eh_personality() { | |
- abort(); | |
-} | |
diff --git a/src/main.rs b/src/main.rs | |
index 25d594e..de69dc8 100644 | |
--- a/src/main.rs | |
+++ b/src/main.rs | |
@@ -10,6 +10,7 @@ | |
extern crate alloc; | |
extern crate core; | |
extern crate lock_api; | |
+extern crate origin; | |
extern crate rustix; | |
extern crate talc; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment