macho_assembler/builder/
object_builder.rs1use crate::types::{CpuType, LoadCommand, MachoHeader, MachoProgram};
2use gaia_types::GaiaError;
3
4#[derive(Debug)]
8pub struct ObjectBuilder {
9 cpu_type: CpuType,
10 load_commands: Vec<LoadCommand>,
11 flags: u32,
12}
13
14impl ObjectBuilder {
15 pub fn new(cpu_type: CpuType) -> Self {
17 Self { cpu_type, load_commands: Vec::new(), flags: 0 }
18 }
19
20 pub fn add_load_command(mut self, command: LoadCommand) -> Self {
22 self.load_commands.push(command);
23 self
24 }
25
26 pub fn set_flags(mut self, flags: u32) -> Self {
28 self.flags = flags;
29 self
30 }
31
32 pub fn add_symtab(self, symoff: u32, nsyms: u32, stroff: u32, strsize: u32) -> Self {
34 let mut data = Vec::new();
35 data.extend_from_slice(&symoff.to_le_bytes());
36 data.extend_from_slice(&nsyms.to_le_bytes());
37 data.extend_from_slice(&stroff.to_le_bytes());
38 data.extend_from_slice(&strsize.to_le_bytes());
39
40 let command = LoadCommand {
41 cmd: 0x2, cmdsize: 24,
43 data,
44 };
45
46 self.add_load_command(command)
47 }
48
49 pub fn build(self) -> Result<MachoProgram, GaiaError> {
51 let sizeofcmds = self.load_commands.iter().map(|cmd| cmd.cmdsize).sum::<u32>();
52
53 let header = MachoHeader {
54 magic: match self.cpu_type {
55 CpuType::X86_64 | CpuType::Arm64 => 0xfeedfacf, _ => 0xfeedface, },
58 cpu_type: self.cpu_type as u32,
59 cpu_subtype: 0,
60 file_type: 1, ncmds: self.load_commands.len() as u32,
62 sizeofcmds,
63 flags: self.flags,
64 reserved: match self.cpu_type {
65 CpuType::X86_64 | CpuType::Arm64 => Some(0),
66 _ => None,
67 },
68 };
69
70 Ok(MachoProgram { header, load_commands: self.load_commands, segments: Vec::new(), sections: Vec::new() })
71 }
72}