elf_assembler/writer/
mod.rs

1//! ELF 文件写入器模块
2//!
3//! 此模块提供将 ELF 结构体写入二进制文件的功能。
4
5use crate::types::{ElfFile, ElfHeader64, ProgramHeader64, SectionHeader64};
6use byteorder::{LittleEndian, WriteBytesExt};
7use gaia_types::GaiaError;
8use std::io::{Seek, Write};
9
10/// ELF 文件生成器的通用接口
11#[derive(Debug)]
12pub struct ElfWriter<W> {
13    writer: W,
14}
15
16impl<W> ElfWriter<W> {
17    /// 创建一个新的 ELF 写入器
18    pub fn new(writer: W) -> Self {
19        Self { writer }
20    }
21
22    pub fn finish(self) -> W {
23        self.writer
24    }
25}
26
27impl<W: Write> ElfWriter<W> {
28    /// 将 ELF 文件写入字节数组
29    pub fn write_elf_file(&mut self, elf_file: &ElfFile) -> Result<(), GaiaError>
30    where
31        W: Seek,
32    {
33        // 写入 ELF 头
34        self.write_elf_header(&elf_file.header)?;
35
36        // 写入程序头表
37        for program_header in &elf_file.program_headers {
38            self.write_program_header(program_header)?;
39        }
40
41        // 对齐到页边界 (4KB)
42        self.align_to_boundary(0x1000)?;
43
44        // 写入数据
45        self.writer.write_all(&elf_file.data)?;
46
47        Ok(())
48    }
49
50    /// 写入 ELF 头(64位)
51    pub fn write_elf_header(&mut self, header: &ElfHeader64) -> Result<(), GaiaError> {
52        // 写入 ELF 标识符 (16 字节)
53        self.writer.write_all(&header.e_ident)?;
54
55        // 写入文件类型
56        self.writer.write_u16::<LittleEndian>(header.e_type)?;
57
58        // 写入机器架构
59        self.writer.write_u16::<LittleEndian>(header.e_machine)?;
60
61        // 写入版本
62        self.writer.write_u32::<LittleEndian>(header.e_version)?;
63
64        // 写入入口点地址
65        self.writer.write_u64::<LittleEndian>(header.e_entry)?;
66
67        // 写入程序头表偏移
68        self.writer.write_u64::<LittleEndian>(header.e_phoff)?;
69
70        // 写入节头表偏移
71        self.writer.write_u64::<LittleEndian>(header.e_shoff)?;
72
73        // 写入处理器特定标志
74        self.writer.write_u32::<LittleEndian>(header.e_flags)?;
75
76        // 写入 ELF 头大小
77        self.writer.write_u16::<LittleEndian>(header.e_ehsize)?;
78
79        // 写入程序头表项大小
80        self.writer.write_u16::<LittleEndian>(header.e_phentsize)?;
81
82        // 写入程序头表项数量
83        self.writer.write_u16::<LittleEndian>(header.e_phnum)?;
84
85        // 写入节头表项大小
86        self.writer.write_u16::<LittleEndian>(header.e_shentsize)?;
87
88        // 写入节头表项数量
89        self.writer.write_u16::<LittleEndian>(header.e_shnum)?;
90
91        // 写入字符串表索引
92        self.writer.write_u16::<LittleEndian>(header.e_shstrndx)?;
93
94        Ok(())
95    }
96
97    /// 写入程序头(64位)
98    pub fn write_program_header(&mut self, header: &ProgramHeader64) -> Result<(), GaiaError> {
99        // 写入段类型
100        self.writer.write_u32::<LittleEndian>(header.p_type)?;
101
102        // 写入段标志
103        self.writer.write_u32::<LittleEndian>(header.p_flags)?;
104
105        // 写入段在文件中的偏移
106        self.writer.write_u64::<LittleEndian>(header.p_offset)?;
107
108        // 写入段的虚拟地址
109        self.writer.write_u64::<LittleEndian>(header.p_vaddr)?;
110
111        // 写入段的物理地址
112        self.writer.write_u64::<LittleEndian>(header.p_paddr)?;
113
114        // 写入段在文件中的大小
115        self.writer.write_u64::<LittleEndian>(header.p_filesz)?;
116
117        // 写入段在内存中的大小
118        self.writer.write_u64::<LittleEndian>(header.p_memsz)?;
119
120        // 写入段对齐
121        self.writer.write_u64::<LittleEndian>(header.p_align)?;
122
123        Ok(())
124    }
125
126    /// 写入节头(64位)
127    pub fn write_section_header(&mut self, header: &SectionHeader64) -> Result<(), GaiaError> {
128        // 写入节名称索引
129        self.writer.write_u32::<LittleEndian>(header.sh_name)?;
130
131        // 写入节类型
132        self.writer.write_u32::<LittleEndian>(header.sh_type)?;
133
134        // 写入节标志
135        self.writer.write_u64::<LittleEndian>(header.sh_flags)?;
136
137        // 写入节的虚拟地址
138        self.writer.write_u64::<LittleEndian>(header.sh_addr)?;
139
140        // 写入节在文件中的偏移
141        self.writer.write_u64::<LittleEndian>(header.sh_offset)?;
142
143        // 写入节的大小
144        self.writer.write_u64::<LittleEndian>(header.sh_size)?;
145
146        // 写入节头表索引链接
147        self.writer.write_u32::<LittleEndian>(header.sh_link)?;
148
149        // 写入附加信息
150        self.writer.write_u32::<LittleEndian>(header.sh_info)?;
151
152        // 写入节对齐
153        self.writer.write_u64::<LittleEndian>(header.sh_addralign)?;
154
155        // 写入节项大小
156        self.writer.write_u64::<LittleEndian>(header.sh_entsize)?;
157
158        Ok(())
159    }
160
161    /// 对齐到指定边界
162    pub fn align_to_boundary(&mut self, boundary: u32) -> Result<(), GaiaError>
163    where
164        W: Seek,
165    {
166        let current_pos = self.writer.stream_position()?;
167        let alignment = boundary as u64;
168        let padding = (alignment - (current_pos % alignment)) % alignment;
169
170        for _ in 0..padding {
171            self.writer.write_u8(0)?;
172        }
173
174        Ok(())
175    }
176
177    /// 填充到指定偏移
178    pub fn pad_to_offset(&mut self, offset: u64) -> Result<(), GaiaError>
179    where
180        W: Seek,
181    {
182        let current_pos = self.writer.stream_position()?;
183        if current_pos < offset {
184            let padding = offset - current_pos;
185            for _ in 0..padding {
186                self.writer.write_u8(0)?;
187            }
188        }
189        Ok(())
190    }
191}
192
193/// ELF 文件构建器
194///
195/// 提供高级接口来构建 ELF 文件
196#[derive(Debug)]
197pub struct ElfBuilder {
198    elf_file: ElfFile,
199}
200
201impl ElfBuilder {
202    /// 创建新的 ELF 构建器
203    pub fn new() -> Self {
204        Self { elf_file: ElfFile::new() }
205    }
206
207    /// 设置入口点
208    pub fn set_entry_point(&mut self, entry: u64) -> &mut Self {
209        self.elf_file.set_entry_point(entry);
210        self
211    }
212
213    /// 添加代码段
214    pub fn add_code_segment(&mut self, code: Vec<u8>) -> &mut Self {
215        let code_size = code.len() as u64;
216        let code_offset = 0x1000; // 4KB 偏移
217        let code_vaddr = 0x401000; // 虚拟地址
218
219        // 创建程序头
220        let program_header = ProgramHeader64::new_load_segment(code_offset, code_vaddr, code_size);
221        self.elf_file.add_program_header(program_header);
222
223        // 设置数据
224        self.elf_file.data = code;
225
226        self
227    }
228
229    /// 构建 ELF 文件
230    pub fn build(self) -> ElfFile {
231        self.elf_file
232    }
233
234    /// 构建并写入到写入器
235    pub fn write_to<W: Write + Seek>(&self, writer: W) -> Result<W, GaiaError> {
236        let mut elf_writer = ElfWriter::new(writer);
237        elf_writer.write_elf_file(&self.elf_file)?;
238        Ok(elf_writer.finish())
239    }
240
241    /// 构建并转换为字节数组
242    pub fn to_bytes(&self) -> Vec<u8> {
243        self.elf_file.to_bytes()
244    }
245}
246
247impl Default for ElfBuilder {
248    fn default() -> Self {
249        Self::new()
250    }
251}