mirror of
https://github.com/Noratrieb/elven-forest.git
synced 2026-01-14 18:55:01 +01:00
write me
This commit is contained in:
parent
31fe171557
commit
6ae845a9b3
8 changed files with 448 additions and 82 deletions
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue