devela/sys/os/linux/process/entry.rs
1// devela::sys::os::linux::entry
2//
3//! Configures the global assembly for target-architecture-specific program entry points.
4//!
5//! This module defines the low-level assembly routines that serve as the initial
6//! execution point for the program. These routines are architecture-specific and handle:
7//! 1. Setting up the minimal execution environment
8//! 2. Transferring control to the Rust entry point
9//! 3. Properly exiting with the program's return status
10//!
11//! The implementations match the system's calling conventions and use architecture-specific
12//! syscall instructions for process termination.
13
14#[doc = crate::_tags!(linux code)]
15/// Defines the program entry point and main fn translation layer for Linux systems.
16#[doc = crate::_doc_meta!{location("sys/os/linux")}]
17///
18/// Handles architecture-specific entry point setup and Rust-to-C ABI translation.
19#[doc(hidden)]
20#[macro_export]
21macro_rules! linux_entry {
22 (
23 // The main() function will return LinuxResult, and get converted to LINUX_EXIT
24 linux_result) => {
25 $crate::linux_entry![main_body:
26 if let Err(e) = main() { e.to_exit_code() } else { $crate::LINUX_EXIT::OK }
27 ];
28 };
29 (
30 // $main_body: the body of the entry point function that receives the result of main()
31 main_body: $main_body:expr) => {
32 #[inline(never)]
33 #[unsafe(no_mangle)]
34 pub extern "C" fn __main() -> i32 { $main_body }
35 $crate::linux_entry!(_start: __main);
36 };
37 (
38 //
39 _start: $main:ident) => {
40 #[cfg(target_arch = "x86_64")]
41 $crate::global_asm!(
42 ".global _start",
43 ".hidden _start",
44 ".type _start,@function",
45 "_start:",
46 "call {main}",
47 "mov rdi, rax",
48 "mov rax, {EXIT}",
49 "syscall",
50 main = sym $main,
51 EXIT = const $crate::LINUX_SYS::EXIT,
52 );
53 #[cfg(target_arch = "x86")]
54 $crate::global_asm!(
55 ".global _start",
56 ".hidden _start",
57 ".type _start,@function",
58 "_start:",
59 "call {main}",
60 "mov ebx, eax",
61 "mov eax, {EXIT}",
62 "int 0x80",
63 main = sym $main,
64 EXIT = const $crate::LINUX_SYS::EXIT,
65 );
66 #[cfg(target_arch = "arm")]
67 $crate::global_asm!(
68 ".global _start",
69 ".hidden _start",
70 ".type _start,%function",
71 "_start:",
72 "bl {main}",
73 "mov r7, #{EXIT}",
74 "swi #0",
75 main = sym $main,
76 EXIT = const $crate::LINUX_SYS::EXIT,
77 );
78 #[cfg(target_arch = "aarch64")]
79 $crate::global_asm!(
80 ".global _start",
81 ".hidden _start",
82 ".type _start,%function",
83 "_start:",
84 "mov x29, #0", // clear frame pointer
85 "mov x30, #0", // clear link register
86 "and sp, sp, #~15", // align stack
87 "bl {main}",
88 "mov x8, #{EXIT}",
89 "svc #0",
90 main = sym $main,
91 EXIT = const $crate::LINUX_SYS::EXIT,
92 );
93 // NOTE: can't use `any_target_arch_riscv` because this is resolved in calling code
94 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
95 $crate::global_asm!(
96 ".global _start",
97 ".hidden _start",
98 ".type _start,@function",
99 "_start:",
100 "call {main}",
101 "li a7, {EXIT}",
102 "ecall",
103 main = sym $main,
104 EXIT = const $crate::LINUX_SYS::EXIT,
105 );
106 };
107}
108#[doc(inline)]
109pub use linux_entry;