use alloc::{collections::VecDeque, string::String, vec::Vec};
use zerocopy::IntoBytes;
use crate::auxv::{AuxEntry, AuxType};
pub fn app_stack_region(args: &[String], envs: &[String], auxv: &[AuxEntry], sp: usize) -> Vec<u8> {
let mut data = VecDeque::new();
let mut push = |src: &[u8]| -> usize {
data.extend(src.iter().cloned());
data.rotate_right(src.len());
sp - data.len()
};
let random_str_pos = push("0123456789abcdef".as_bytes());
let envs_slice: Vec<_> = envs
.iter()
.map(|env| {
push(b"\0");
push(env.as_bytes())
})
.collect();
let argv_slice: Vec<_> = args
.iter()
.map(|arg| {
push(b"\0");
push(arg.as_bytes())
})
.collect();
let padding_null = "\0".repeat(8);
let sp = push(padding_null.as_bytes());
push(&b"\0".repeat(sp % 16));
if (envs.len() + args.len() + 3) & 1 != 0 {
push(padding_null.as_bytes());
}
let mut has_random = false;
let mut has_execfn = false;
for entry in auxv.iter() {
if entry.get_type() == AuxType::RANDOM {
has_random = true;
}
if entry.get_type() == AuxType::EXECFN {
has_execfn = true;
}
if has_random && has_execfn {
break;
}
}
push(auxv.as_bytes());
if !has_random {
push(AuxEntry::new(AuxType::RANDOM, random_str_pos).as_bytes());
}
if !has_execfn {
push(AuxEntry::new(AuxType::EXECFN, argv_slice[0]).as_bytes());
}
push(padding_null.as_bytes());
push(envs_slice.as_bytes());
push(padding_null.as_bytes());
push(argv_slice.as_bytes());
let sp = push(args.len().as_bytes());
assert!(sp % 16 == 0);
let mut result = Vec::with_capacity(data.len());
let (first, second) = data.as_slices();
result.extend_from_slice(first);
result.extend_from_slice(second);
result
}