macho_assembler/builder/
object_builder.rs1use crate::types::{MachoProgram, MachoHeader, LoadCommand, CpuType};
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 {
18 cpu_type,
19 load_commands: Vec::new(),
20 flags: 0,
21 }
22 }
23
24 pub fn add_load_command(mut self, command: LoadCommand) -> Self {
26 self.load_commands.push(command);
27 self
28 }
29
30 pub fn set_flags(mut self, flags: u32) -> Self {
32 self.flags = flags;
33 self
34 }
35
36 pub fn add_symtab(self, symoff: u32, nsyms: u32, stroff: u32, strsize: u32) -> Self {
38 let mut data = Vec::new();
39 data.extend_from_slice(&symoff.to_le_bytes());
40 data.extend_from_slice(&nsyms.to_le_bytes());
41 data.extend_from_slice(&stroff.to_le_bytes());
42 data.extend_from_slice(&strsize.to_le_bytes());
43
44 let command = LoadCommand {
45 cmd: 0x2, cmdsize: 24,
47 data,
48 };
49
50 self.add_load_command(command)
51 }
52
53 pub fn build(self) -> Result<MachoProgram, GaiaError> {
55 let sizeofcmds = self.load_commands.iter()
56 .map(|cmd| cmd.cmdsize)
57 .sum::<u32>();
58
59 let header = MachoHeader {
60 magic: match self.cpu_type {
61 CpuType::X86_64 | CpuType::Arm64 => 0xfeedfacf, _ => 0xfeedface, },
64 cpu_type: self.cpu_type as u32,
65 cpu_subtype: 0,
66 file_type: 1, ncmds: self.load_commands.len() as u32,
68 sizeofcmds,
69 flags: self.flags,
70 reserved: match self.cpu_type {
71 CpuType::X86_64 | CpuType::Arm64 => Some(0),
72 _ => None,
73 },
74 };
75
76 Ok(MachoProgram {
77 header,
78 load_commands: self.load_commands,
79 segments: Vec::new(),
80 sections: Vec::new(),
81 })
82 }
83}