Skip to content

Instantly share code, notes, and snippets.

@sunfishcode
Last active October 10, 2024 18:13
Show Gist options
  • Save sunfishcode/a30b3420aedce2cb5a08985aebc0e7ea to your computer and use it in GitHub Desktop.
Save sunfishcode/a30b3420aedce2cb5a08985aebc0e7ea to your computer and use it in GitHub Desktop.
origin.patch
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