pub struct ElfBuilder { /* private fields */ }Expand description
ELF file builder
Implementations§
Source§impl ElfBuilder
impl ElfBuilder
Sourcepub fn new_arm32() -> Self
pub fn new_arm32() -> Self
Create a new ELF builder for ARM32
Examples found in repository?
examples/compile_add.rs (line 65)
17fn main() -> Result<(), Box<dyn std::error::Error>> {
18 println!("=== Synth Minimal Demo: WASM -> ARM ELF ===\n");
19
20 // Step 1: Define WASM operations for add(a, b) function
21 // Equivalent to: (func (param $a i32) (param $b i32) (result i32)
22 // local.get $a
23 // local.get $b
24 // i32.add)
25 let wasm_ops = vec![
26 WasmOp::LocalGet(0), // Load param a
27 WasmOp::LocalGet(1), // Load param b
28 WasmOp::I32Add, // Add them
29 ];
30
31 println!("Step 1: WASM Operations");
32 println!(" Input: add(a, b) = a + b");
33 println!(" WASM ops: {:?}\n", wasm_ops);
34
35 // Step 2: Select ARM instructions
36 let db = RuleDatabase::with_standard_rules();
37 let mut selector = InstructionSelector::new(db.rules().to_vec());
38 let arm_instrs = selector.select(&wasm_ops)?;
39
40 println!("Step 2: ARM Instruction Selection");
41 println!(" Generated {} ARM instructions:", arm_instrs.len());
42 for (i, instr) in arm_instrs.iter().enumerate() {
43 println!(" {}: {:?}", i, instr.op);
44 }
45 println!();
46
47 // Step 3: Encode to ARM binary
48 let encoder = ArmEncoder::new_arm32();
49 let mut code = Vec::new();
50
51 for instr in &arm_instrs {
52 let encoded = encoder.encode(&instr.op)?;
53 code.extend_from_slice(&encoded);
54 }
55
56 println!("Step 3: ARM Binary Encoding");
57 println!(" Generated {} bytes of machine code", code.len());
58 print!(" Hex: ");
59 for byte in &code {
60 print!("{:02x} ", byte);
61 }
62 println!("\n");
63
64 // Step 4: Build ELF file
65 let mut elf_builder = ElfBuilder::new_arm32().with_entry(0x8000);
66
67 // Add .text section with code
68 let text_section = Section::new(".text", ElfSectionType::ProgBits)
69 .with_flags(SectionFlags::ALLOC | SectionFlags::EXEC)
70 .with_addr(0x8000)
71 .with_align(4)
72 .with_data(code.clone());
73
74 elf_builder.add_section(text_section);
75
76 // Add function symbol
77 let add_sym = Symbol::new("add")
78 .with_value(0x8000)
79 .with_size(code.len() as u32)
80 .with_binding(SymbolBinding::Global)
81 .with_type(SymbolType::Func)
82 .with_section(4);
83
84 elf_builder.add_symbol(add_sym);
85
86 // Build ELF
87 let elf_data = elf_builder.build()?;
88
89 println!("Step 4: ELF Generation");
90 println!(" ELF size: {} bytes", elf_data.len());
91 println!(" Entry point: 0x8000");
92
93 // Verify ELF header
94 assert_eq!(
95 &elf_data[0..4],
96 &[0x7f, b'E', b'L', b'F'],
97 "Invalid ELF magic"
98 );
99 println!(" ELF magic: valid");
100
101 // Step 5: Write to file
102 let output_path = "add.elf";
103 let mut file = File::create(output_path)?;
104 file.write_all(&elf_data)?;
105
106 println!("\nStep 5: Output");
107 println!(" Written to: {}", output_path);
108 println!("\n=== Compilation successful! ===");
109 println!("\nTo inspect: arm-none-eabi-objdump -d {}", output_path);
110
111 Ok(())
112}Sourcepub fn with_entry(self, entry: u32) -> Self
pub fn with_entry(self, entry: u32) -> Self
Set entry point
For ARM (Thumb) targets, bit 0 is automatically set to indicate Thumb mode. Cortex-M is Thumb-only, so function addresses in ELF must have bit 0 set.
Examples found in repository?
examples/compile_add.rs (line 65)
17fn main() -> Result<(), Box<dyn std::error::Error>> {
18 println!("=== Synth Minimal Demo: WASM -> ARM ELF ===\n");
19
20 // Step 1: Define WASM operations for add(a, b) function
21 // Equivalent to: (func (param $a i32) (param $b i32) (result i32)
22 // local.get $a
23 // local.get $b
24 // i32.add)
25 let wasm_ops = vec![
26 WasmOp::LocalGet(0), // Load param a
27 WasmOp::LocalGet(1), // Load param b
28 WasmOp::I32Add, // Add them
29 ];
30
31 println!("Step 1: WASM Operations");
32 println!(" Input: add(a, b) = a + b");
33 println!(" WASM ops: {:?}\n", wasm_ops);
34
35 // Step 2: Select ARM instructions
36 let db = RuleDatabase::with_standard_rules();
37 let mut selector = InstructionSelector::new(db.rules().to_vec());
38 let arm_instrs = selector.select(&wasm_ops)?;
39
40 println!("Step 2: ARM Instruction Selection");
41 println!(" Generated {} ARM instructions:", arm_instrs.len());
42 for (i, instr) in arm_instrs.iter().enumerate() {
43 println!(" {}: {:?}", i, instr.op);
44 }
45 println!();
46
47 // Step 3: Encode to ARM binary
48 let encoder = ArmEncoder::new_arm32();
49 let mut code = Vec::new();
50
51 for instr in &arm_instrs {
52 let encoded = encoder.encode(&instr.op)?;
53 code.extend_from_slice(&encoded);
54 }
55
56 println!("Step 3: ARM Binary Encoding");
57 println!(" Generated {} bytes of machine code", code.len());
58 print!(" Hex: ");
59 for byte in &code {
60 print!("{:02x} ", byte);
61 }
62 println!("\n");
63
64 // Step 4: Build ELF file
65 let mut elf_builder = ElfBuilder::new_arm32().with_entry(0x8000);
66
67 // Add .text section with code
68 let text_section = Section::new(".text", ElfSectionType::ProgBits)
69 .with_flags(SectionFlags::ALLOC | SectionFlags::EXEC)
70 .with_addr(0x8000)
71 .with_align(4)
72 .with_data(code.clone());
73
74 elf_builder.add_section(text_section);
75
76 // Add function symbol
77 let add_sym = Symbol::new("add")
78 .with_value(0x8000)
79 .with_size(code.len() as u32)
80 .with_binding(SymbolBinding::Global)
81 .with_type(SymbolType::Func)
82 .with_section(4);
83
84 elf_builder.add_symbol(add_sym);
85
86 // Build ELF
87 let elf_data = elf_builder.build()?;
88
89 println!("Step 4: ELF Generation");
90 println!(" ELF size: {} bytes", elf_data.len());
91 println!(" Entry point: 0x8000");
92
93 // Verify ELF header
94 assert_eq!(
95 &elf_data[0..4],
96 &[0x7f, b'E', b'L', b'F'],
97 "Invalid ELF magic"
98 );
99 println!(" ELF magic: valid");
100
101 // Step 5: Write to file
102 let output_path = "add.elf";
103 let mut file = File::create(output_path)?;
104 file.write_all(&elf_data)?;
105
106 println!("\nStep 5: Output");
107 println!(" Written to: {}", output_path);
108 println!("\n=== Compilation successful! ===");
109 println!("\nTo inspect: arm-none-eabi-objdump -d {}", output_path);
110
111 Ok(())
112}Sourcepub fn add_section(&mut self, section: Section)
pub fn add_section(&mut self, section: Section)
Add a section
Examples found in repository?
examples/compile_add.rs (line 74)
17fn main() -> Result<(), Box<dyn std::error::Error>> {
18 println!("=== Synth Minimal Demo: WASM -> ARM ELF ===\n");
19
20 // Step 1: Define WASM operations for add(a, b) function
21 // Equivalent to: (func (param $a i32) (param $b i32) (result i32)
22 // local.get $a
23 // local.get $b
24 // i32.add)
25 let wasm_ops = vec![
26 WasmOp::LocalGet(0), // Load param a
27 WasmOp::LocalGet(1), // Load param b
28 WasmOp::I32Add, // Add them
29 ];
30
31 println!("Step 1: WASM Operations");
32 println!(" Input: add(a, b) = a + b");
33 println!(" WASM ops: {:?}\n", wasm_ops);
34
35 // Step 2: Select ARM instructions
36 let db = RuleDatabase::with_standard_rules();
37 let mut selector = InstructionSelector::new(db.rules().to_vec());
38 let arm_instrs = selector.select(&wasm_ops)?;
39
40 println!("Step 2: ARM Instruction Selection");
41 println!(" Generated {} ARM instructions:", arm_instrs.len());
42 for (i, instr) in arm_instrs.iter().enumerate() {
43 println!(" {}: {:?}", i, instr.op);
44 }
45 println!();
46
47 // Step 3: Encode to ARM binary
48 let encoder = ArmEncoder::new_arm32();
49 let mut code = Vec::new();
50
51 for instr in &arm_instrs {
52 let encoded = encoder.encode(&instr.op)?;
53 code.extend_from_slice(&encoded);
54 }
55
56 println!("Step 3: ARM Binary Encoding");
57 println!(" Generated {} bytes of machine code", code.len());
58 print!(" Hex: ");
59 for byte in &code {
60 print!("{:02x} ", byte);
61 }
62 println!("\n");
63
64 // Step 4: Build ELF file
65 let mut elf_builder = ElfBuilder::new_arm32().with_entry(0x8000);
66
67 // Add .text section with code
68 let text_section = Section::new(".text", ElfSectionType::ProgBits)
69 .with_flags(SectionFlags::ALLOC | SectionFlags::EXEC)
70 .with_addr(0x8000)
71 .with_align(4)
72 .with_data(code.clone());
73
74 elf_builder.add_section(text_section);
75
76 // Add function symbol
77 let add_sym = Symbol::new("add")
78 .with_value(0x8000)
79 .with_size(code.len() as u32)
80 .with_binding(SymbolBinding::Global)
81 .with_type(SymbolType::Func)
82 .with_section(4);
83
84 elf_builder.add_symbol(add_sym);
85
86 // Build ELF
87 let elf_data = elf_builder.build()?;
88
89 println!("Step 4: ELF Generation");
90 println!(" ELF size: {} bytes", elf_data.len());
91 println!(" Entry point: 0x8000");
92
93 // Verify ELF header
94 assert_eq!(
95 &elf_data[0..4],
96 &[0x7f, b'E', b'L', b'F'],
97 "Invalid ELF magic"
98 );
99 println!(" ELF magic: valid");
100
101 // Step 5: Write to file
102 let output_path = "add.elf";
103 let mut file = File::create(output_path)?;
104 file.write_all(&elf_data)?;
105
106 println!("\nStep 5: Output");
107 println!(" Written to: {}", output_path);
108 println!("\n=== Compilation successful! ===");
109 println!("\nTo inspect: arm-none-eabi-objdump -d {}", output_path);
110
111 Ok(())
112}Sourcepub fn add_symbol(&mut self, symbol: Symbol)
pub fn add_symbol(&mut self, symbol: Symbol)
Add a symbol
Examples found in repository?
examples/compile_add.rs (line 84)
17fn main() -> Result<(), Box<dyn std::error::Error>> {
18 println!("=== Synth Minimal Demo: WASM -> ARM ELF ===\n");
19
20 // Step 1: Define WASM operations for add(a, b) function
21 // Equivalent to: (func (param $a i32) (param $b i32) (result i32)
22 // local.get $a
23 // local.get $b
24 // i32.add)
25 let wasm_ops = vec![
26 WasmOp::LocalGet(0), // Load param a
27 WasmOp::LocalGet(1), // Load param b
28 WasmOp::I32Add, // Add them
29 ];
30
31 println!("Step 1: WASM Operations");
32 println!(" Input: add(a, b) = a + b");
33 println!(" WASM ops: {:?}\n", wasm_ops);
34
35 // Step 2: Select ARM instructions
36 let db = RuleDatabase::with_standard_rules();
37 let mut selector = InstructionSelector::new(db.rules().to_vec());
38 let arm_instrs = selector.select(&wasm_ops)?;
39
40 println!("Step 2: ARM Instruction Selection");
41 println!(" Generated {} ARM instructions:", arm_instrs.len());
42 for (i, instr) in arm_instrs.iter().enumerate() {
43 println!(" {}: {:?}", i, instr.op);
44 }
45 println!();
46
47 // Step 3: Encode to ARM binary
48 let encoder = ArmEncoder::new_arm32();
49 let mut code = Vec::new();
50
51 for instr in &arm_instrs {
52 let encoded = encoder.encode(&instr.op)?;
53 code.extend_from_slice(&encoded);
54 }
55
56 println!("Step 3: ARM Binary Encoding");
57 println!(" Generated {} bytes of machine code", code.len());
58 print!(" Hex: ");
59 for byte in &code {
60 print!("{:02x} ", byte);
61 }
62 println!("\n");
63
64 // Step 4: Build ELF file
65 let mut elf_builder = ElfBuilder::new_arm32().with_entry(0x8000);
66
67 // Add .text section with code
68 let text_section = Section::new(".text", ElfSectionType::ProgBits)
69 .with_flags(SectionFlags::ALLOC | SectionFlags::EXEC)
70 .with_addr(0x8000)
71 .with_align(4)
72 .with_data(code.clone());
73
74 elf_builder.add_section(text_section);
75
76 // Add function symbol
77 let add_sym = Symbol::new("add")
78 .with_value(0x8000)
79 .with_size(code.len() as u32)
80 .with_binding(SymbolBinding::Global)
81 .with_type(SymbolType::Func)
82 .with_section(4);
83
84 elf_builder.add_symbol(add_sym);
85
86 // Build ELF
87 let elf_data = elf_builder.build()?;
88
89 println!("Step 4: ELF Generation");
90 println!(" ELF size: {} bytes", elf_data.len());
91 println!(" Entry point: 0x8000");
92
93 // Verify ELF header
94 assert_eq!(
95 &elf_data[0..4],
96 &[0x7f, b'E', b'L', b'F'],
97 "Invalid ELF magic"
98 );
99 println!(" ELF magic: valid");
100
101 // Step 5: Write to file
102 let output_path = "add.elf";
103 let mut file = File::create(output_path)?;
104 file.write_all(&elf_data)?;
105
106 println!("\nStep 5: Output");
107 println!(" Written to: {}", output_path);
108 println!("\n=== Compilation successful! ===");
109 println!("\nTo inspect: arm-none-eabi-objdump -d {}", output_path);
110
111 Ok(())
112}Sourcepub fn add_program_header(&mut self, ph: ProgramHeader)
pub fn add_program_header(&mut self, ph: ProgramHeader)
Add a program header (segment)
Sourcepub fn add_relocation(&mut self, reloc: Relocation)
pub fn add_relocation(&mut self, reloc: Relocation)
Add a relocation entry for the .text section
Sourcepub fn add_undefined_symbol(&mut self, name: &str) -> u32
pub fn add_undefined_symbol(&mut self, name: &str) -> u32
Add an undefined external symbol (e.g., __meld_dispatch_import) Returns the symbol index (1-based, accounting for null symbol)
Sourcepub fn build(&self) -> Result<Vec<u8>>
pub fn build(&self) -> Result<Vec<u8>>
Build the ELF file to bytes
Examples found in repository?
examples/compile_add.rs (line 87)
17fn main() -> Result<(), Box<dyn std::error::Error>> {
18 println!("=== Synth Minimal Demo: WASM -> ARM ELF ===\n");
19
20 // Step 1: Define WASM operations for add(a, b) function
21 // Equivalent to: (func (param $a i32) (param $b i32) (result i32)
22 // local.get $a
23 // local.get $b
24 // i32.add)
25 let wasm_ops = vec![
26 WasmOp::LocalGet(0), // Load param a
27 WasmOp::LocalGet(1), // Load param b
28 WasmOp::I32Add, // Add them
29 ];
30
31 println!("Step 1: WASM Operations");
32 println!(" Input: add(a, b) = a + b");
33 println!(" WASM ops: {:?}\n", wasm_ops);
34
35 // Step 2: Select ARM instructions
36 let db = RuleDatabase::with_standard_rules();
37 let mut selector = InstructionSelector::new(db.rules().to_vec());
38 let arm_instrs = selector.select(&wasm_ops)?;
39
40 println!("Step 2: ARM Instruction Selection");
41 println!(" Generated {} ARM instructions:", arm_instrs.len());
42 for (i, instr) in arm_instrs.iter().enumerate() {
43 println!(" {}: {:?}", i, instr.op);
44 }
45 println!();
46
47 // Step 3: Encode to ARM binary
48 let encoder = ArmEncoder::new_arm32();
49 let mut code = Vec::new();
50
51 for instr in &arm_instrs {
52 let encoded = encoder.encode(&instr.op)?;
53 code.extend_from_slice(&encoded);
54 }
55
56 println!("Step 3: ARM Binary Encoding");
57 println!(" Generated {} bytes of machine code", code.len());
58 print!(" Hex: ");
59 for byte in &code {
60 print!("{:02x} ", byte);
61 }
62 println!("\n");
63
64 // Step 4: Build ELF file
65 let mut elf_builder = ElfBuilder::new_arm32().with_entry(0x8000);
66
67 // Add .text section with code
68 let text_section = Section::new(".text", ElfSectionType::ProgBits)
69 .with_flags(SectionFlags::ALLOC | SectionFlags::EXEC)
70 .with_addr(0x8000)
71 .with_align(4)
72 .with_data(code.clone());
73
74 elf_builder.add_section(text_section);
75
76 // Add function symbol
77 let add_sym = Symbol::new("add")
78 .with_value(0x8000)
79 .with_size(code.len() as u32)
80 .with_binding(SymbolBinding::Global)
81 .with_type(SymbolType::Func)
82 .with_section(4);
83
84 elf_builder.add_symbol(add_sym);
85
86 // Build ELF
87 let elf_data = elf_builder.build()?;
88
89 println!("Step 4: ELF Generation");
90 println!(" ELF size: {} bytes", elf_data.len());
91 println!(" Entry point: 0x8000");
92
93 // Verify ELF header
94 assert_eq!(
95 &elf_data[0..4],
96 &[0x7f, b'E', b'L', b'F'],
97 "Invalid ELF magic"
98 );
99 println!(" ELF magic: valid");
100
101 // Step 5: Write to file
102 let output_path = "add.elf";
103 let mut file = File::create(output_path)?;
104 file.write_all(&elf_data)?;
105
106 println!("\nStep 5: Output");
107 println!(" Written to: {}", output_path);
108 println!("\n=== Compilation successful! ===");
109 println!("\nTo inspect: arm-none-eabi-objdump -d {}", output_path);
110
111 Ok(())
112}Auto Trait Implementations§
impl Freeze for ElfBuilder
impl RefUnwindSafe for ElfBuilder
impl Send for ElfBuilder
impl Sync for ElfBuilder
impl Unpin for ElfBuilder
impl UnsafeUnpin for ElfBuilder
impl UnwindSafe for ElfBuilder
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more