use crate::types::{CpuType, LoadCommand, MachoHeader, MachoProgram, MachoType};
use gaia_types::GaiaError;
#[derive(Debug)]
pub struct ExecutableBuilder {
header: MachoHeader,
load_commands: Vec<LoadCommand>,
entry_point: Option<u64>,
}
impl ExecutableBuilder {
pub fn new(cpu_type: CpuType) -> Self {
let header = MachoHeader {
magic: match cpu_type {
CpuType::X86_64 | CpuType::Arm64 => 0xfeedfacf, _ => 0xfeedface, },
cpu_type: cpu_type as u32,
cpu_subtype: 0,
file_type: MachoType::Execute as u32,
ncmds: 0,
sizeofcmds: 0,
flags: 0,
reserved: match cpu_type {
CpuType::X86_64 | CpuType::Arm64 => Some(0),
_ => None,
},
};
Self { header, load_commands: Vec::new(), entry_point: None }
}
pub fn set_entry_point(&mut self, entry_point: u64) -> &mut Self {
self.entry_point = Some(entry_point);
self
}
pub fn add_load_command(&mut self, cmd: u32, data: Vec<u8>) -> &mut Self {
let cmdsize = 8 + data.len() as u32; let load_cmd = LoadCommand { cmd, cmdsize, data };
self.load_commands.push(load_cmd);
self.header.ncmds += 1;
self.header.sizeofcmds += cmdsize;
self
}
pub fn set_flags(&mut self, flags: u32) -> &mut Self {
self.header.flags = flags;
self
}
pub fn build(self) -> Result<MachoProgram, GaiaError> {
Ok(MachoProgram { header: self.header, load_commands: self.load_commands, segments: Vec::new(), sections: Vec::new() })
}
}
impl Default for ExecutableBuilder {
fn default() -> Self {
Self::new(CpuType::X86_64)
}
}