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?
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?
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?
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?
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_indexed(&mut self, symbol: Symbol) -> u32
pub fn add_symbol_indexed(&mut self, symbol: Symbol) -> u32
Add a symbol and return its 1-based index in .symtab (index 0 is the
reserved null symbol). Use when a later relocation must reference this
symbol — e.g. the .text base symbol the DWARF .rel.debug_* records
resolve against (VCR-DBG-001).
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_section_relocations(
&mut self,
target_section: &str,
relocs: Vec<Relocation>,
)
pub fn add_section_relocations( &mut self, target_section: &str, relocs: Vec<Relocation>, )
Add a relocation table targeting a non-.text section by name (e.g.
.debug_line). Produces a separate .rel.<name> section whose sh_info
points at the named section. The section must already have been added via
[add_section]; if no matching section exists at build time the table is
silently dropped. Used by VCR-DBG-001 to relocate the DWARF .text
references so a host linker fixes them up alongside .text.
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?
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}