This commit is contained in:
nora 2023-02-12 22:30:14 +01:00
parent 31fe171557
commit 6ae845a9b3
8 changed files with 448 additions and 82 deletions

View file

@ -3,9 +3,17 @@ extern crate tracing;
use anyhow::{bail, Context, Result};
use clap::Parser;
use elven_parser::defs::Elf;
use elven_parser::{
consts::{self as c, ShType, SHT_PROGBITS},
read::{ElfIdent, ElfReader, Offset},
write::{self, ElfWriter, Entry, Section},
};
use memmap2::Mmap;
use std::{fs::File, path::PathBuf};
use std::{
fs,
io::{BufWriter, Write},
path::PathBuf,
};
#[derive(Debug, Clone, Parser)]
pub struct Opts {
@ -17,7 +25,8 @@ pub fn run(opts: Opts) -> Result<()> {
.objs
.iter()
.map(|path| {
let file = File::open(path).with_context(|| format!("opening {}", path.display()))?;
let file =
fs::File::open(path).with_context(|| format!("opening {}", path.display()))?;
unsafe {
Mmap::map(&file).with_context(|| format!("memory mapping {}", path.display()))
}
@ -38,11 +47,73 @@ pub fn run(opts: Opts) -> Result<()> {
.iter()
.zip(&opts.objs)
.map(|(mmap, path)| {
Elf::new(mmap).with_context(|| format!("parsing ELF file {}", path.display()))
ElfReader::new(mmap).with_context(|| format!("parsing ELF file {}", path.display()))
})
.collect::<Result<Vec<_>, anyhow::Error>>()?;
let main_elf = elfs[0];
let elf = elfs[0];
let text_sh = elf.section_header_by_name(b".text")?;
let text_content = elf.section_content(text_sh)?;
let _start_sym = elf.symbol_by_name(b"_start")?;
let section = _start_sym.shndx;
let entry = Entry {
section,
rel_offset: Offset(_start_sym.value.0),
};
write_output(text_content, entry)?;
Ok(())
}
fn write_output(text: &[u8], entry: Entry) -> Result<()> {
let ident = ElfIdent {
magic: *c::ELFMAG,
class: c::Class(c::ELFCLASS64),
data: c::Data(c::ELFDATA2LSB),
version: 1,
osabi: c::OsAbi(c::ELFOSABI_SYSV),
abiversion: 0,
_pad: [0; 7],
};
let header = write::Header {
ident,
r#type: c::Type(c::ET_DYN),
machine: c::Machine(c::EM_X86_64),
};
let mut write = ElfWriter::new(header);
let text_name = write.add_sh_string(b".text");
write.add_section(Section {
name: text_name,
r#type: ShType(SHT_PROGBITS),
flags: 0,
fixed_entsize: None,
content: text.to_vec(),
});
write.set_entry(entry);
let output = write.write().context("writing output file")?;
let mut output_file = fs::File::create("a.out").context("creating ./a.out")?;
BufWriter::new(&mut output_file).write_all(&output)?;
#[allow(unused_mut)]
let mut permissions = output_file.metadata()?.permissions();
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mode = permissions.mode();
permissions.set_mode(mode | 0o111);
};
output_file.set_permissions(permissions)?;
Ok(())
}