Skip to content
/ faerie Public

Magical ELF and Mach-o object file writer backend

License

Notifications You must be signed in to change notification settings

m4b/faerie

Folders and files

NameName
Last commit message
Last commit date

Latest commit

8ac6e28 Â· Apr 8, 2024
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

faerie Build Status Documentatation.

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:

ELF REL X86_64-little-endian @ 0x0:

e_phoff: 0x0 e_shoff: 0x2a2 e_flags: 0x0 e_ehsize: 64 e_phentsize: 56 e_phnum: 0 e_shentsize: 64 e_shnum: 9 e_shstrndx: 1

SectionHeaders(9):
  Idx   Name                      Type   Flags                  Offset   Addr   Size    Link         Entsize   Align  
  0                           SHT_NULL                          0x0      0x0    0x0                  0x0       0x0    
  1     .strtab             SHT_STRTAB                          0x8c     0x0    0xc6                 0x0       0x1    
  2     .symtab             SHT_SYMTAB                          0x152    0x0    0xf0    .strtab(1)   0x18      0x8    
  3     .rodata.str.1       SHT_PROGBITS   ALLOC MERGE STRINGS    0x40     0x0    0x10                 0x1       0x1    
  4     .text.deadbeef    SHT_PROGBITS   ALLOC EXECINSTR        0x50     0x0    0x14                 0x0       0x10   
  5     .text.main        SHT_PROGBITS   ALLOC EXECINSTR        0x64     0x0    0x28                 0x0       0x10   
  6     .reloc.main           SHT_RELA                          0x242    0x0    0x48    .symtab(2)   0x18      0x8    
  7     .reloc.deadbeef       SHT_RELA                          0x28a    0x0    0x18    .symtab(2)   0x18      0x8    
  8     .note.GNU-stack   SHT_PROGBITS                          0x0      0x0    0x0                  0x0       0x1    

Syms(10):
               Addr   Bind       Type        Symbol     Size    Section             Other  
                 0    LOCAL      NOTYPE                 0x0                         0x0    
                 0    LOCAL      FILE        test.o     0x0     ABS                 0x0    
                 0    LOCAL      SECTION                0x0     .rodata.str.1(3)      0x0    
                 0    LOCAL      SECTION                0x0     .text.deadbeef(4)   0x0    
                 0    LOCAL      SECTION                0x0     .text.main(5)       0x0    
                 0    LOCAL      OBJECT      str.1      0x10    .rodata.str.1(3)      0x0    
                 0    LOCAL      FUNC        deadbeef   0x14    .text.deadbeef(4)   0x0    
                 0    GLOBAL     FUNC        main       0x28    .text.main(5)       0x0    
                 0    GLOBAL     NOTYPE      DEADBEEF   0x0                         0x0    
                 0    GLOBAL     NOTYPE      printf     0x0                         0x0    

Shdr Relocations(4):
  .text.main(3)
              13 X86_64_PC32 .rodata.str.1
              1d X86_64_PLT32 printf+-4
               a X86_64_PLT32 .text.deadbeef+-4

  .text.deadbeef(1)
               7 X86_64_GOTPCREL DEADBEEF+-4

😎

About

Magical ELF and Mach-o object file writer backend

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages