Faerie
Magical ELF and Mach-o object file writer backend
Install / Use
/learn @m4b/FaerieREADME
faerie
.
Emit some object files, at your leisure:
use faerie::{ArtifactBuilder, ArtifactError, triple, Link, Decl};
use std::path::Path;
use std::fs::File;
pub fn main() -> Result<(), ArtifactError> {
let name = "test.o";
let file = File::create(Path::new(name))?;
let mut obj = ArtifactBuilder::new(triple!("x86_64-unknown-unknown-unknown-elf"))
.name(name.to_owned())
.finish();
// first we declare our symbolic references;
// it is a runtime error to define a symbol _without_ declaring it first
obj.declarations(
[
("deadbeef", Decl::function().into()),
("main", Decl::function().global().into()),
("str.1", Decl::cstring().into()),
("DEADBEEF", Decl::data_import().into()),
("printf", Decl::function_import().into()),
].iter().cloned()
)?;
// we now define our local functions and data
// 0000000000000000 <deadbeef>:
// 0: 55 push %rbp
// 1: 48 89 e5 mov %rsp,%rbp
// 4: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # b <deadbeef+0xb>
// 7: R_X86_64_GOTPCREL DEADBEEF-0x4
// b: 8b 08 mov (%rax),%ecx
// d: 83 c1 01 add $0x1,%ecx
// 10: 89 c8 mov %ecx,%eax
// 12: 5d pop %rbp
// 13: c3 retq
obj.define("deadbeef",
vec![0x55,
0x48, 0x89, 0xe5,
0x48, 0x8b, 0x05, 0x00, 0x00, 0x00, 0x00,
0x8b, 0x08,
0x83, 0xc1, 0x01,
0x89, 0xc8,
0x5d,
0xc3])?;
// main:
// 55 push %rbp
// 48 89 e5 mov %rsp,%rbp
// b8 00 00 00 00 mov $0x0,%eax
// e8 00 00 00 00 callq 0x0 <deadbeef>
// 89 c6 mov %eax,%esi
// 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # will be: deadbeef: 0x%x\n
// b8 00 00 00 00 mov $0x0,%eax
// e8 00 00 00 00 callq 0x3f <main+33> # printf
// b8 00 00 00 00 mov $0x0,%eax
// 5d pop %rbp
// c3 retq
obj.define("main",
vec![0x55,
0x48, 0x89, 0xe5,
0xb8, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x00, 0x00, 0x00, 0x00,
0x89, 0xc6,
0x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00,
0xb8, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x00, 0x00, 0x00, 0x00,
0xb8, 0x00, 0x00, 0x00, 0x00,
0x5d,
0xc3])?;
obj.define("str.1", b"deadbeef: 0x%x\n\0".to_vec())?;
// Next, we declare our relocations,
// which are _always_ relative to the `from` symbol
obj.link(Link { from: "main", to: "str.1", at: 19 })?;
obj.link(Link { from: "main", to: "printf", at: 29 })?;
obj.link(Link { from: "main", to: "deadbeef", at: 10 })?;
obj.link(Link { from: "deadbeef", to: "DEADBEEF", at: 7 })?;
// Finally, we write the object file
obj.write(file)?;
Ok(())
}
Will emit an object file like this:
<pre><font color="#D3D7CF">ELF </font><span style="background-color:#FCE94F"><font color="#555753">REL</font></span> <font color="#D3D7CF"><b>X86_64</b></font>-little-endian @ <font color="#CC0000">0x0</font>: e_phoff: <font color="#C4A000">0x0</font> e_shoff: <font color="#C4A000">0x2a2</font> e_flags: 0x0 e_ehsize: 64 e_phentsize: 56 e_phnum: 0 e_shentsize: 64 e_shnum: 9 e_shstrndx: 1 <font color="#D3D7CF">SectionHeaders(9)</font>: <b>Idx</b> <b>Name </b> <b> Type</b> <b>Flags </b> <b>Offset</b> <b>Addr</b> <b>Size </b> <b>Link </b> <b>Entsize</b> <b>Align</b> <span style="background-color:#D3D7CF"><font color="#2E3436">0 </font></span> <span style="background-color:#D3D7CF"><font color="#2E3436"> </font></span> SHT_NULL <font color="#C4A000">0x0 </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0x0 </b></font> 0x0 0x0 <span style="background-color:#2E3436"><font color="#D3D7CF">1 </font></span> <span style="background-color:#2E3436"><font color="#D3D7CF">.strtab </font></span> SHT_STRTAB <font color="#C4A000">0x8c </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0xc6 </b></font> 0x0 0x1 <span style="background-color:#D3D7CF"><font color="#2E3436">2 </font></span> <span style="background-color:#D3D7CF"><font color="#2E3436">.symtab </font></span> SHT_SYMTAB <font color="#C4A000">0x152 </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0xf0 </b></font> .strtab(1) 0x18 0x8 <span style="background-color:#2E3436"><font color="#D3D7CF">3 </font></span> <span style="background-color:#2E3436"><font color="#D3D7CF">.rodata.str.1 </font></span> SHT_PROGBITS <b>ALLOC MERGE STRINGS </b> <font color="#C4A000">0x40 </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0x10 </b></font> 0x1 0x1 <span style="background-color:#D3D7CF"><font color="#2E3436">4 </font></span> <span style="background-color:#D3D7CF"><font color="#2E3436">.text.deadbeef </font></span> SHT_PROGBITS <b>ALLOC EXECINSTR </b> <font color="#C4A000">0x50 </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0x14 </b></font> 0x0 0x10 <span style="background-color:#2E3436"><font color="#D3D7CF">5 </font></span> <span style="background-color:#2E3436"><font color="#D3D7CF">.text.main </font></span> SHT_PROGBITS <b>ALLOC EXECINSTR </b> <font color="#C4A000">0x64 </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0x28 </b></font> 0x0 0x10 <span style="background-color:#D3D7CF"><font color="#2E3436">6 </font></span> <span style="background-color:#D3D7CF"><font color="#2E3436">.reloc.main </font></span> SHT_RELA <font color="#C4A000">0x242 </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0x48 </b></font> .symtab(2) 0x18 0x8 <span style="background-color:#2E3436"><font color="#D3D7CF">7 </font></span> <span style="background-color:#2E3436"><font color="#D3D7CF">.reloc.deadbeef</font></span> SHT_RELA <font color="#C4A000">0x28a </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0x18 </b></font> .symtab(2) 0x18 0x8 <span style="background-color:#D3D7CF"><font color="#2E3436">8 </font></span> <span style="background-color:#D3D7CF"><font color="#2E3436">.note.GNU-stack</font></span> SHT_PROGBITS <font color="#C4A000">0x0 </font> <font color="#CC0000"><b>0x0 </b></font> <font color="#4E9A06"><b>0x0 </b></font> 0x0 0x1 <font color="#D3D7CF">Syms(10)</font>: <b> Addr</b> <b>Bind </b> <b>Type </b> <b>Symbol </b> <b>Size </b> <b>Section </b> <b>Other</b> <font color="#CC0000"> 0 </font> <span style="background-color:#34E2E2"><font color="#555753"><b>LOCAL </b></font></span> NOTYPE <font color="#4E9A06">0x0 </font> 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#34E2E2"><font color="#555753"><b>LOCAL </b></font></span> FILE <font color="#FCE94F"><b>test.o </b></font> <font color="#4E9A06">0x0 </font> <font color="#D3D7CF"><i>ABS </i></font> 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#34E2E2"><font color="#555753"><b>LOCAL </b></font></span> SECTION <font color="#4E9A06">0x0 </font> .rodata.str.1(3) 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#34E2E2"><font color="#555753"><b>LOCAL </b></font></span> SECTION <font color="#4E9A06">0x0 </font> .text.deadbeef(4) 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#34E2E2"><font color="#555753"><b>LOCAL </b></font></span> SECTION <font color="#4E9A06">0x0 </font> .text.main(5) 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#34E2E2"><font color="#555753"><b>LOCAL </b></font></span> <font color="#FCE94F"><b>OBJECT </b></font> <font color="#FCE94F"><b>str.1 </b></font> <font color="#4E9A06">0x10 </font> .rodata.str.1(3) 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#34E2E2"><font color="#555753"><b>LOCAL </b></font></span> <font color="#EF2929"><b>FUNC </b></font> <font color="#FCE94F"><b>deadbeef</b></font> <font color="#4E9A06">0x14 </font> .text.deadbeef(4) 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#EF2929"><font color="#555753"><b>GLOBAL </b></font></span> <font color="#EF2929"><b>FUNC </b></font> <font color="#FCE94F"><b>main </b></font> <font color="#4E9A06">0x28 </font> .text.main(5) 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#EF2929"><font color="#555753"><b>GLOBAL </b></font></span> NOTYPE <font color="#FCE94F"><b>DEADBEEF</b></font> <font color="#4E9A06">0x0 </font> 0x0 <font color="#CC0000"> 0 </font> <span style="background-color:#EF2929"><font color="#555753"><b>GLOBAL </b></font></span> NOTYPE <font color="#FCE94F"><b>printfRelated Skills
node-connect
342.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
342.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.7kCommit, push, and open a PR
