Skip to main content

macho_assembler/builder/
object_builder.rs

1use crate::types::{CpuType, LoadCommand, MachoHeader, MachoProgram};
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 { cpu_type, load_commands: Vec::new(), flags: 0 }
18    }
19
20    /// 添加加载命令
21    pub fn add_load_command(mut self, command: LoadCommand) -> Self {
22        self.load_commands.push(command);
23        self
24    }
25
26    /// 设置标志位
27    pub fn set_flags(mut self, flags: u32) -> Self {
28        self.flags = flags;
29        self
30    }
31
32    /// 添加符号表命令
33    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, // LC_SYMTAB
42            cmdsize: 24,
43            data,
44        };
45
46        self.add_load_command(command)
47    }
48
49    /// 构建 MachoProgram
50    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, // MH_MAGIC_64
56                _ => 0xfeedface,                                // MH_MAGIC
57            },
58            cpu_type: self.cpu_type as u32,
59            cpu_subtype: 0,
60            file_type: 1, // MH_OBJECT
61            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}