macho_assembler/builder/
object_builder.rs

1use crate::types::{MachoProgram, MachoHeader, LoadCommand, CpuType};
2use gaia_types::GaiaError;
3
4/// Mach-O 目标文件构建器
5///
6/// 提供高级接口来构建 Mach-O 目标文件
7#[derive(Debug)]
8pub struct ObjectBuilder {
9    cpu_type: CpuType,
10    load_commands: Vec<LoadCommand>,
11    flags: u32,
12}
13
14impl ObjectBuilder {
15    /// 创建一个新的目标文件构建器
16    pub fn new(cpu_type: CpuType) -> Self {
17        Self {
18            cpu_type,
19            load_commands: Vec::new(),
20            flags: 0,
21        }
22    }
23
24    /// 添加加载命令
25    pub fn add_load_command(mut self, command: LoadCommand) -> Self {
26        self.load_commands.push(command);
27        self
28    }
29
30    /// 设置标志位
31    pub fn set_flags(mut self, flags: u32) -> Self {
32        self.flags = flags;
33        self
34    }
35
36    /// 添加符号表命令
37    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, // LC_SYMTAB
46            cmdsize: 24,
47            data,
48        };
49
50        self.add_load_command(command)
51    }
52
53    /// 构建 MachoProgram
54    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, // MH_MAGIC_64
62                _ => 0xfeedface, // MH_MAGIC
63            },
64            cpu_type: self.cpu_type as u32,
65            cpu_subtype: 0,
66            file_type: 1, // MH_OBJECT
67            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}