diff --git a/src/common/output.rs b/src/common/output.rs index 3dd12a8..b3efc8c 100644 --- a/src/common/output.rs +++ b/src/common/output.rs @@ -9,7 +9,7 @@ where { fn process_section(&mut self, section: Section) -> Result<(), Error>; - fn finalize(self, objects: &Vec) -> Result; + fn finalize(self, objects: &[R]) -> Result; } pub struct DummyOutput; @@ -23,7 +23,7 @@ where Ok(()) } - fn finalize(self, objects: &Vec) -> Result { + fn finalize(self, _objects: &[R]) -> Result { todo!(); } } diff --git a/src/common/relocatable.rs b/src/common/relocatable.rs index e520856..0d8e7e3 100644 --- a/src/common/relocatable.rs +++ b/src/common/relocatable.rs @@ -1,5 +1,5 @@ use std::path::Path; -use std::{convert::TryFrom, fmt::Display, path::PathBuf}; +use std::{fmt::Display, path::PathBuf}; use crate::error::Error; @@ -8,12 +8,15 @@ use super::Section; pub type BSI<'iter, I> = Box, Error>> + 'iter>; /// Contains all the needed getters to construct a final /// mushed and relocated executable from an object file -pub trait Relocatable: Display + TryFrom { +pub trait Relocatable: Display + Sized { + // + TryFrom { type Index; // index into the data, e.g. usize + fn new(origin: PathBuf, object_index: usize) -> Result; + fn origin(&self) -> &Path; // not same as section's path since this one's supposed to be cannonical - fn sections<'iter>(self: &'iter Self) -> BSI<'iter, Self::Index>; + fn sections(&self) -> BSI; fn section_data(&self, section_index: Self::Index) -> Result<&[u8], Error>; } diff --git a/src/common/section.rs b/src/common/section.rs index 9943e45..c47a5ad 100644 --- a/src/common/section.rs +++ b/src/common/section.rs @@ -19,24 +19,6 @@ pub enum Section { Bss(SectionInfo), } -impl Section { - pub fn file_size(&self) -> Result { - match self { - Section::Text(s) => Ok(s.file_size), - Section::Data(s, _) => Ok(s.file_size), - Section::Bss(s) => Ok(s.file_size), - } - } - - pub fn data_size(&self) -> Result { - match self { - Section::Text(s) => Ok(s.data_size), - Section::Data(s, _) => Ok(s.data_size), - Section::Bss(s) => Ok(s.data_size), - } - } -} - impl<'data, I> TryFrom<(&str, SectionInfo)> for Section { type Error = Error; diff --git a/src/error.rs b/src/error.rs index bb96a56..4ba7b2e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -35,7 +35,7 @@ impl From for Error { } impl From for Error { - fn from(err: std::num::TryFromIntError) -> Self { + fn from(_: std::num::TryFromIntError) -> Self { Self::TryFromIntError } } diff --git a/src/formats/elf/object.rs b/src/formats/elf/object.rs index 2436fb0..759dbaf 100644 --- a/src/formats/elf/object.rs +++ b/src/formats/elf/object.rs @@ -9,12 +9,13 @@ use crate::{common::BSI, error::Error}; use elf_utilities::{file::ELF64, parser::read_elf64}; pub struct ElfObject { + object_index: usize, origin: PathBuf, elf: ELF64, } impl ElfObject { - pub fn new(origin: PathBuf) -> Result { + pub fn new(origin: PathBuf, object_index: usize) -> Result { let str_origin = origin .as_path() .to_str() @@ -25,7 +26,11 @@ impl ElfObject { }; is_relocatable(&elf)?; - let result = ElfObject { origin, elf }; + let result = ElfObject { + object_index, + origin, + elf, + }; Ok(result) } @@ -38,53 +43,57 @@ impl ElfObject { impl Relocatable for ElfObject { type Index = (usize, usize); // object index, section index + fn new(origin: PathBuf, object_index: usize) -> Result { + ElfObject::new(origin, object_index) + } + fn origin(&self) -> &Path { &self.origin } - fn sections<'iter>(self: &'iter Self) -> BSI<'iter, (usize, usize)> { + fn sections(&self) -> BSI<(usize, usize)> { use elf_utilities::section::{Contents64, Type}; - let iter = - self.elf - .sections - .iter() - .enumerate() - .filter_map(|(i, s)| match s.header.get_type() { - Type::ProgBits => { - if s.header.sh_size > 0 { - if let Some(di) = match &s.contents { - Contents64::Raw(v) => Some(v), - _ => None, - } { - let si = SectionInfo { - file_size: s.header.sh_size, - data_size: s.header.sh_size, - data_index: Some((0, i)), // TODO - offset: s.header.sh_offset, - }; - let s_name: &str = &s.name; - - match Section::try_from((s_name, si)) { - Ok(s) => Some(Ok(s)), - Err(Error::InvalidSectionName) => None, // skip - Err(err) => Some(Err(err)), - } - } else { - Some(Err(Error::InvalidSectionData)) + let iter = self + .elf + .sections + .iter() + .enumerate() + .filter_map(move |(i, s)| match s.header.get_type() { + Type::ProgBits => { + if s.header.sh_size > 0 { + if match &s.contents { + Contents64::Raw(v) => Some(v), + _ => None, + }.is_some() { + let si = SectionInfo { + file_size: s.header.sh_size, + data_size: s.header.sh_size, + data_index: Some((self.object_index, i)), + offset: s.header.sh_offset, + }; + let s_name: &str = &s.name; + + match Section::try_from((s_name, si)) { + Ok(s) => Some(Ok(s)), + Err(Error::InvalidSectionName) => None, // skip + Err(err) => Some(Err(err)), } } else { - None + Some(Err(Error::InvalidSectionData)) } + } else { + None } - Type::NoBits => Some(Ok(Section::Bss(SectionInfo { - file_size: 0, - data_size: s.header.sh_size, - data_index: None, - offset: s.header.sh_offset, - }))), - _ => None, - }); + } + Type::NoBits => Some(Ok(Section::Bss(SectionInfo { + file_size: 0, + data_size: s.header.sh_size, + data_index: None, + offset: s.header.sh_offset, + }))), + _ => None, + }); Box::new(iter) } @@ -118,13 +127,13 @@ impl Display for ElfObject { } } -impl TryFrom for ElfObject { - type Error = Error; +// impl TryFrom for ElfObject { +// type Error = Error; - fn try_from(path: PathBuf) -> Result { - Self::new(path) - } -} +// fn try_from(path: PathBuf) -> Result { +// Self::new(path) +// } +// } fn is_relocatable(elf: &ELF64) -> Result<(), Error> { use elf_utilities::header::Type; diff --git a/src/formats/elf/output.rs b/src/formats/elf/output.rs index c478728..d75ee24 100644 --- a/src/formats/elf/output.rs +++ b/src/formats/elf/output.rs @@ -25,7 +25,7 @@ use super::ElfObject; pub struct ElfOutput { destination: PathBuf, file: ELF64, - input_data: SegmentView, + segment_view: SegmentView, writer: BufWriter, } @@ -48,23 +48,7 @@ impl ElfOutput { let result = Self { destination, file: elf, - input_data: SegmentView::default(), - writer, - }; - - Ok(result) - } - - pub fn from_object(object: &ElfObject, destination: PathBuf) -> Result { - let other = object.elf(); - - let str_path = expand_path(&destination)?; - let writer = file_writer(str_path, 0o755)?; - - let result = Self { - destination, - file: elf_bin_from_object(other), - input_data: SegmentView::default(), + segment_view: SegmentView::default(), writer, }; @@ -75,7 +59,7 @@ impl ElfOutput { let mut names = Vec::new(); let mut name_idx = 0usize; - for (name, sections) in self.input_data.sections_mut() { + for (name, sections) in self.segment_view.sections_mut() { let mut data_size = 0; for t in sections.iter() { @@ -147,13 +131,17 @@ impl ElfOutput { // contains .text + .rodata as one segment self.populate_segment( &mut offset, - self.input_data.program_size(), + self.segment_view.program_size(), SegmentType::Text, ); // contains .data as one segment - self.populate_segment(&mut offset, self.input_data.data_size(), SegmentType::Data); + self.populate_segment( + &mut offset, + self.segment_view.data_size(), + SegmentType::Data, + ); // contains .bss as one segment - self.populate_segment(&mut offset, self.input_data.bss_size(), SegmentType::Bss); + self.populate_segment(&mut offset, self.segment_view.bss_size(), SegmentType::Bss); Ok(offset) } @@ -161,10 +149,10 @@ impl ElfOutput { impl Output for ElfOutput { fn process_section(&mut self, section: Section<(usize, usize)>) -> Result<(), Error> { - self.input_data.append_section(section) + self.segment_view.append_section(section) } - fn finalize(mut self, objects: &Vec) -> Result { + fn finalize(mut self, objects: &[ElfObject]) -> Result { const EHS: u64 = size_of::() as u64; const PHS: u16 = size_of::() as u16; const SHS: u16 = size_of::() as u16; @@ -207,13 +195,13 @@ impl Output for ElfOutput { offset += pad_to_next_page(&mut self.writer, offset)?; eprintln!("Prog start: {}", offset); // write section/segment data - for bytes in self.input_data.program_bytes(objects) { + for bytes in self.segment_view.program_bytes(objects) { offset += self.writer.write(bytes?)?; } offset += pad_to_next_page(&mut self.writer, offset)?; eprintln!("Data start: {}", offset); - for bytes in self.input_data.data_bytes(objects) { + for bytes in self.segment_view.data_bytes(objects) { offset += self.writer.write(bytes?)?; } @@ -236,20 +224,6 @@ fn file_writer(output_filename: &str, permission: u32) -> Result Ok(BufWriter::new(file)) } -// init new ELF64 from an object file meant as executable output -fn elf_bin_from_object(other: &ELF64) -> ELF64 { - use elf_utilities::header::Type; - - let mut elf = ELF64::default(); - elf.ehdr.set_elf_type(Type::Exec); - elf.ehdr.e_ehsize = other.ehdr.e_ehsize; - elf.ehdr.e_version = other.ehdr.e_version; - elf.ehdr.e_ident = other.ehdr.e_ident; - elf.ehdr.e_machine = other.ehdr.e_machine; - - elf -} - fn make_section_header(name_idx: usize, stype: ShType, size: u64) -> Shdr64 { let mut h = Shdr64::default(); h.set_type(stype); diff --git a/src/formats/elf/segment.rs b/src/formats/elf/segment.rs index 32b021a..cbb8c18 100644 --- a/src/formats/elf/segment.rs +++ b/src/formats/elf/segment.rs @@ -34,9 +34,7 @@ impl<'data> SegmentView { Ok(()) } - pub fn sections_mut( - &mut self, - ) -> impl Iterator { + pub fn sections_mut(&mut self) -> impl Iterator { let text = once(&mut self.text).map(|s| (".text", s)); let rodata = once(&mut self.rodata).map(|s| (".rodata", s)); let data = once(&mut self.data).map(|s| (".data", s)); @@ -47,7 +45,7 @@ impl<'data> SegmentView { pub fn program_bytes<'l>( &'l self, - objects: &'l Vec, + objects: &'l [ElfObject], ) -> impl Iterator> { let text_iter = self.text.iter(); let rodata_iter = self.rodata.iter(); @@ -61,21 +59,17 @@ impl<'data> SegmentView { Some(di) => Some(objects[di.0].section_data(di)), }); - let iter = data1.chain(data2); - - iter + data1.chain(data2) } pub fn data_bytes<'l>( &'l self, - objects: &'l Vec, + objects: &'l [ElfObject], ) -> impl Iterator> { - let iter = self.data - .iter() - .filter_map(move |si| match si.data_index { - None => None, - Some(di) => Some(objects[di.0].section_data(di)), - }); + let iter = self.data.iter().filter_map(move |si| match si.data_index { + None => None, + Some(di) => Some(objects[di.0].section_data(di)), + }); iter } diff --git a/src/linker.rs b/src/linker.rs index 7638c9e..e367742 100644 --- a/src/linker.rs +++ b/src/linker.rs @@ -30,8 +30,9 @@ where } } - pub fn add_relocatable(&mut self, path: PathBuf) -> Result<(), Error> { - self.relocatables.push(R::try_from(path)?); + pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> { + self.relocatables + .push(R::new(origin, self.relocatables.len())?); Ok(()) } diff --git a/src/main.rs b/src/main.rs index 9de01cf..929f7c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ fn main() { let destination = PathBuf::from("/home/ales/Programovanie/rust/linker/assets/rld.out"); // TODO let mut linker = Linker::elf(destination).expect("Linker init"); - while let Some(path) = args.next() { + for path in args { let path = PathBuf::from(path); linker.add_relocatable(path).expect("Data input");