kernel_elf_parser/user_stack.rs
1//! Initialize the user stack for the application
2//!
3//! The structure of the user stack is described in the following figure:
4//! position content size (bytes) + comment
5//! ------------------------------------------------------------------------
6//! stack pointer -> [ argc = number of args ] 8
7//! [ argv[0] (pointer) ] 8 (program name)
8//! [ argv[1] (pointer) ] 8
9//! [ argv[..] (pointer) ] 8 * x
10//! [ argv[n - 1] (pointer) ] 8
11//! [ argv[n] (pointer) ] 8 (= NULL)
12//! [ envp[0] (pointer) ] 8
13//! [ envp[1] (pointer) ] 8
14//! [ envp[..] (pointer) ] 8
15//! [ envp[term] (pointer) ] 8 (= NULL)
16//! [ auxv[0] (Elf32_auxv_t) ] 16
17//! [ auxv[1] (Elf32_auxv_t) ] 16
18//! [ auxv[..] (Elf32_auxv_t) ] 16
19//! [ auxv[term] (Elf32_auxv_t) ] 16 (= AT_NULL vector)
20//! [ padding ] 0 - 16
21//! [ argument ASCIIZ strings ] >= 0
22//! [ environment ASCIIZ str. ] >= 0
23//!
24//! (0xbffffff8) [ end marker ] 8 (= NULL)
25//!
26//! (0xc0000000) < bottom of stack > 0 (virtual)
27//!
28//! More details can be found in the link: <https://articles.manugarg.com/aboutelfauxiliaryvectors.html>
29
30extern crate alloc;
31
32use alloc::{string::String, vec::Vec};
33use memory_addr::VirtAddr;
34
35use crate::auxv::{AuxvEntry, AuxvType};
36
37struct UserStack {
38 sp: usize,
39}
40
41impl UserStack {
42 pub fn new(sp: usize) -> Self {
43 Self { sp }
44 }
45 fn push(&mut self, src: &[u8], stack_data: &mut Vec<u8>) {
46 self.sp -= src.len();
47 // let mut target_data = src.to_vec();
48 // target_data.append(stack_data);
49 // *stack_data = target_data;
50 stack_data.splice(0..0, src.iter().cloned());
51 }
52 pub fn push_usize_slice(&mut self, src: &[usize], stack_data: &mut Vec<u8>) {
53 for val in src.iter().rev() {
54 let bytes = val.to_le_bytes();
55 self.push(&bytes, stack_data);
56 }
57 }
58 pub fn push_str(&mut self, str: &str, stack_data: &mut Vec<u8>) -> usize {
59 self.push(b"\0", stack_data);
60
61 self.push(str.as_bytes(), stack_data);
62 self.sp
63 }
64 pub fn get_sp(&self) -> usize {
65 self.sp
66 }
67}
68
69fn init_stack(args: &[String], envs: &[String], auxv: &mut [AuxvEntry], sp: usize) -> Vec<u8> {
70 let mut data = Vec::new();
71 let mut stack = UserStack::new(sp);
72 // define a random string with 16 bytes
73 stack.push("0123456789abcdef".as_bytes(), &mut data);
74 let random_str_pos = stack.get_sp();
75 // Push arguments and environment variables
76 let envs_slice: Vec<_> = envs
77 .iter()
78 .map(|env| stack.push_str(env, &mut data))
79 .collect();
80 let argv_slice: Vec<_> = args
81 .iter()
82 .map(|arg| stack.push_str(arg, &mut data))
83 .collect();
84 let padding_null = "\0".repeat(8);
85 stack.push(padding_null.as_bytes(), &mut data);
86
87 stack.push("\0".repeat(stack.get_sp() % 16).as_bytes(), &mut data);
88 assert!(stack.get_sp() % 16 == 0);
89 // Push auxiliary vectors
90 for auxv_entry in auxv.iter_mut() {
91 if auxv_entry.get_type() == AuxvType::RANDOM {
92 *auxv_entry.value_mut_ref() = random_str_pos;
93 }
94 if auxv_entry.get_type() == AuxvType::EXECFN {
95 *auxv_entry.value_mut_ref() = argv_slice[0];
96 }
97 }
98 stack.push_usize_slice(
99 unsafe {
100 core::slice::from_raw_parts(
101 auxv.as_ptr() as *const usize,
102 core::mem::size_of_val(auxv) / core::mem::size_of::<usize>(),
103 )
104 },
105 &mut data,
106 );
107
108 // Push the argv and envp pointers
109 stack.push(padding_null.as_bytes(), &mut data);
110 stack.push_usize_slice(envs_slice.as_slice(), &mut data);
111 stack.push(padding_null.as_bytes(), &mut data);
112 stack.push_usize_slice(argv_slice.as_slice(), &mut data);
113 // Push argc
114 stack.push_usize_slice(&[args.len()], &mut data);
115 data
116}
117
118/// Generate initial stack frame for user stack
119///
120/// # Arguments
121///
122/// * `args` - Arguments of the application
123/// * `envs` - Environment variables of the application
124/// * `auxv` - Auxiliary vectors of the application
125/// * `stack_base` - Lowest address of the stack
126/// * `stack_size` - Size of the stack.
127///
128/// # Return
129///
130/// * [`Vec<u8>`] - Initial stack frame of the application
131///
132/// # Notes
133///
134/// The detailed format is described in <https://articles.manugarg.com/aboutelfauxiliaryvectors.html>
135pub fn app_stack_region(
136 args: &[String],
137 envs: &[String],
138 auxv: &mut [AuxvEntry],
139 stack_base: VirtAddr,
140 stack_size: usize,
141) -> Vec<u8> {
142 let ustack_bottom = stack_base;
143 let ustack_top = ustack_bottom + stack_size;
144 init_stack(args, envs, auxv, ustack_top.into())
145}