first file output
parent
0e1c83bbed
commit
54adb8559d
@ -1,24 +1,32 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::Section;
|
||||
use crate::error::Error;
|
||||
|
||||
pub trait Output {
|
||||
pub trait Output<'data> {
|
||||
fn allocate(&mut self, size: u64) -> Result<u64, Error>;
|
||||
|
||||
fn append_section(&mut self, section: &Section) -> Result<(), Error>;
|
||||
fn append_section(&mut self, section: Section<'data>) -> Result<(), Error>;
|
||||
|
||||
// fn prepare_symbol<V, S>(&mut self, symbol: impl Lazy<V, S>) -> Result<&mut Self, Error>;
|
||||
|
||||
fn finalize(self) -> Result<PathBuf, Error>;
|
||||
}
|
||||
|
||||
pub struct DummyOutput;
|
||||
|
||||
impl Output for DummyOutput {
|
||||
impl<'data> Output<'data> for DummyOutput {
|
||||
fn allocate(&mut self, size: u64) -> Result<u64, Error> {
|
||||
eprintln!("Allocating: {}", size);
|
||||
Ok(size)
|
||||
}
|
||||
|
||||
fn append_section(&mut self, section: &Section) -> Result<(), Error> {
|
||||
fn append_section(&mut self, section: Section<'data>) -> Result<(), Error> {
|
||||
eprintln!("Appending section: {}", section);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn finalize(self) -> Result<PathBuf, Error> {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
#[cfg(feature = "elf")]
|
||||
mod elf;
|
||||
#[cfg(feature = "xelf")]
|
||||
mod xelf;
|
||||
|
||||
#[cfg(feature = "elf")]
|
||||
pub use elf::*;
|
||||
#[cfg(feature = "xelf")]
|
||||
pub use xelf::*;
|
||||
|
@ -0,0 +1,128 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use elf_utilities::{
|
||||
file::{ELF64Dumper, ELF64},
|
||||
section::Section64,
|
||||
segment::{Segment64, Type},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
common::{Output, Section, SectionInfo},
|
||||
error::Error,
|
||||
};
|
||||
|
||||
use super::ElfObject;
|
||||
|
||||
pub struct ElfOutput<'data> {
|
||||
destination: PathBuf,
|
||||
dump: ELF64Dumper,
|
||||
text: Vec<SectionInfo<'data>>,
|
||||
data: Vec<SectionInfo<'data>>,
|
||||
bss: Vec<SectionInfo<'data>>,
|
||||
}
|
||||
|
||||
impl ElfOutput<'_> {
|
||||
pub fn new(destination: PathBuf) -> Self {
|
||||
use elf_utilities::header::{Class, Data, Machine, Type, Version, OSABI};
|
||||
|
||||
let mut elf = ELF64::default();
|
||||
elf.ehdr.set_elf_type(Type::Exec);
|
||||
elf.ehdr.set_class(Class::Bit64);
|
||||
elf.ehdr.set_machine(Machine::Intel386);
|
||||
elf.ehdr.set_object_version(Version::Current);
|
||||
elf.ehdr.set_file_version(Version::Current);
|
||||
elf.ehdr.set_osabi(OSABI::Linux);
|
||||
elf.ehdr.set_data(Data::LSB2);
|
||||
|
||||
Self {
|
||||
destination,
|
||||
dump: ELF64Dumper::new(elf),
|
||||
text: Vec::new(),
|
||||
data: Vec::new(),
|
||||
bss: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_object(object: &ElfObject, destination: PathBuf) -> Self {
|
||||
use elf_utilities::header::Type;
|
||||
|
||||
let other = object.elf();
|
||||
|
||||
let mut elf = ELF64::default();
|
||||
elf.ehdr = other.ehdr.clone();
|
||||
elf.ehdr.set_elf_type(Type::Exec);
|
||||
|
||||
Self {
|
||||
destination,
|
||||
dump: ELF64Dumper::new(elf),
|
||||
text: Vec::new(),
|
||||
data: Vec::new(),
|
||||
bss: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn populate_section_data(&mut self) -> Result<u64, Error> {
|
||||
use elf_utilities::section::{Contents64, Shdr64, Type};
|
||||
|
||||
let mut data = Vec::new();
|
||||
|
||||
for t in self.text.iter_mut() {
|
||||
if let Some(iter) = &mut t.data {
|
||||
data.extend(iter.as_mut());
|
||||
}
|
||||
}
|
||||
|
||||
let mut header = Shdr64::default();
|
||||
header.set_type(Type::ProgBits);
|
||||
header.sh_entsize = data.len() as u64;
|
||||
|
||||
let sec64 = Section64 {
|
||||
name: ".text".into(),
|
||||
header,
|
||||
contents: Contents64::Raw(data),
|
||||
};
|
||||
|
||||
self.dump.file.add_section(sec64);
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'data> Output<'data> for ElfOutput<'data> {
|
||||
fn allocate(&mut self, size: u64) -> Result<u64, Error> {
|
||||
Ok(size)
|
||||
}
|
||||
|
||||
fn append_section(&mut self, section: Section<'data>) -> Result<(), Error> {
|
||||
match section {
|
||||
Section::Text(si) => self.text.push(si),
|
||||
Section::Data(si) => self.data.push(si),
|
||||
Section::Bss(si) => self.bss.push(si),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn finalize(mut self) -> Result<PathBuf, Error> {
|
||||
use std::io::Error as IOError;
|
||||
use std::io::ErrorKind;
|
||||
|
||||
self.populate_section_data()?;
|
||||
let mut segment = Segment64::default();
|
||||
segment.header.set_type(Type::Load);
|
||||
self.dump.file.segments.push(segment);
|
||||
self.dump.file.finalize();
|
||||
|
||||
let str_path = self.destination.to_str().ok_or_else(|| {
|
||||
let ioe = IOError::new(ErrorKind::Other, "Path expansion fail");
|
||||
let boxed = Box::new(ioe);
|
||||
Error::IOError(boxed)
|
||||
})?;
|
||||
|
||||
self.dump
|
||||
.generate_elf_file(str_path, 0o755)
|
||||
.map_err(|e| Error::IOError(e))?;
|
||||
|
||||
Ok(self.destination)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue