elf_assembler/writer/
mod.rs1use crate::types::{ElfFile, ElfHeader64, ProgramHeader64, SectionHeader64};
6use byteorder::{LittleEndian, WriteBytesExt};
7use gaia_types::GaiaError;
8use std::io::{Seek, Write};
9
10#[derive(Debug)]
12pub struct ElfWriter<W> {
13 writer: W,
14}
15
16impl<W> ElfWriter<W> {
17 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 pub fn write_elf_file(&mut self, elf_file: &ElfFile) -> Result<(), GaiaError>
30 where
31 W: Seek,
32 {
33 self.write_elf_header(&elf_file.header)?;
35
36 for program_header in &elf_file.program_headers {
38 self.write_program_header(program_header)?;
39 }
40
41 self.align_to_boundary(0x1000)?;
43
44 self.writer.write_all(&elf_file.data)?;
46
47 Ok(())
48 }
49
50 pub fn write_elf_header(&mut self, header: &ElfHeader64) -> Result<(), GaiaError> {
52 self.writer.write_all(&header.e_ident)?;
54
55 self.writer.write_u16::<LittleEndian>(header.e_type)?;
57
58 self.writer.write_u16::<LittleEndian>(header.e_machine)?;
60
61 self.writer.write_u32::<LittleEndian>(header.e_version)?;
63
64 self.writer.write_u64::<LittleEndian>(header.e_entry)?;
66
67 self.writer.write_u64::<LittleEndian>(header.e_phoff)?;
69
70 self.writer.write_u64::<LittleEndian>(header.e_shoff)?;
72
73 self.writer.write_u32::<LittleEndian>(header.e_flags)?;
75
76 self.writer.write_u16::<LittleEndian>(header.e_ehsize)?;
78
79 self.writer.write_u16::<LittleEndian>(header.e_phentsize)?;
81
82 self.writer.write_u16::<LittleEndian>(header.e_phnum)?;
84
85 self.writer.write_u16::<LittleEndian>(header.e_shentsize)?;
87
88 self.writer.write_u16::<LittleEndian>(header.e_shnum)?;
90
91 self.writer.write_u16::<LittleEndian>(header.e_shstrndx)?;
93
94 Ok(())
95 }
96
97 pub fn write_program_header(&mut self, header: &ProgramHeader64) -> Result<(), GaiaError> {
99 self.writer.write_u32::<LittleEndian>(header.p_type)?;
101
102 self.writer.write_u32::<LittleEndian>(header.p_flags)?;
104
105 self.writer.write_u64::<LittleEndian>(header.p_offset)?;
107
108 self.writer.write_u64::<LittleEndian>(header.p_vaddr)?;
110
111 self.writer.write_u64::<LittleEndian>(header.p_paddr)?;
113
114 self.writer.write_u64::<LittleEndian>(header.p_filesz)?;
116
117 self.writer.write_u64::<LittleEndian>(header.p_memsz)?;
119
120 self.writer.write_u64::<LittleEndian>(header.p_align)?;
122
123 Ok(())
124 }
125
126 pub fn write_section_header(&mut self, header: &SectionHeader64) -> Result<(), GaiaError> {
128 self.writer.write_u32::<LittleEndian>(header.sh_name)?;
130
131 self.writer.write_u32::<LittleEndian>(header.sh_type)?;
133
134 self.writer.write_u64::<LittleEndian>(header.sh_flags)?;
136
137 self.writer.write_u64::<LittleEndian>(header.sh_addr)?;
139
140 self.writer.write_u64::<LittleEndian>(header.sh_offset)?;
142
143 self.writer.write_u64::<LittleEndian>(header.sh_size)?;
145
146 self.writer.write_u32::<LittleEndian>(header.sh_link)?;
148
149 self.writer.write_u32::<LittleEndian>(header.sh_info)?;
151
152 self.writer.write_u64::<LittleEndian>(header.sh_addralign)?;
154
155 self.writer.write_u64::<LittleEndian>(header.sh_entsize)?;
157
158 Ok(())
159 }
160
161 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 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#[derive(Debug)]
197pub struct ElfBuilder {
198 elf_file: ElfFile,
199}
200
201impl ElfBuilder {
202 pub fn new() -> Self {
204 Self { elf_file: ElfFile::new() }
205 }
206
207 pub fn set_entry_point(&mut self, entry: u64) -> &mut Self {
209 self.elf_file.set_entry_point(entry);
210 self
211 }
212
213 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; let code_vaddr = 0x401000; let program_header = ProgramHeader64::new_load_segment(code_offset, code_vaddr, code_size);
221 self.elf_file.add_program_header(program_header);
222
223 self.elf_file.data = code;
225
226 self
227 }
228
229 pub fn build(self) -> ElfFile {
231 self.elf_file
232 }
233
234 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 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}