From 21096384d8cd8a7048632a9acf2ad627763dafe5 Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Wed, 23 Dec 2020 21:28:50 -0800 Subject: [PATCH] refactoring --- src/common.rs | 2 + src/common/output.rs | 24 ++++++++++++ src/formats/elf.rs | 80 +++++---------------------------------- src/formats/elf/object.rs | 69 +++++++++++++++++++++++++++++++++ src/linker.rs | 34 ++++++++++++----- src/main.rs | 16 ++++---- 6 files changed, 136 insertions(+), 89 deletions(-) create mode 100644 src/common/output.rs create mode 100644 src/formats/elf/object.rs diff --git a/src/common.rs b/src/common.rs index 995d3be..0cba7ca 100644 --- a/src/common.rs +++ b/src/common.rs @@ -3,9 +3,11 @@ mod relocatable; mod section; mod storage; mod symbol; +mod output; pub use lazy::*; pub use relocatable::*; pub use section::*; pub use storage::*; pub use symbol::*; +pub use output::*; \ No newline at end of file diff --git a/src/common/output.rs b/src/common/output.rs new file mode 100644 index 0000000..0be740a --- /dev/null +++ b/src/common/output.rs @@ -0,0 +1,24 @@ +use crate::error::Error; +use super::Section; + +pub trait Output { + fn allocate(&mut self, size: u64) -> Result; + + fn append_section(&mut self, section: &Section) -> Result<(), Error>; + + // fn prepare_symbol(&mut self, symbol: impl Lazy) -> Result<&mut Self, Error>; +} + +pub struct DummyOutput; + +impl Output for DummyOutput { + fn allocate(&mut self, size: u64) -> Result { + eprintln!("Allocating: {}", size); + Ok(size) + } + + fn append_section(&mut self, section: &Section) -> Result<(), Error> { + eprintln!("Appending section: {}", section); + Ok(()) + } +} \ No newline at end of file diff --git a/src/formats/elf.rs b/src/formats/elf.rs index 2768228..6f46303 100644 --- a/src/formats/elf.rs +++ b/src/formats/elf.rs @@ -1,72 +1,20 @@ -use std::{ - fmt::Display, - path::{Path, PathBuf}, -}; -use crate::common::{Lazy, Relocatable, Storage, Symbol}; -use crate::linker::LinkState; -use crate::{common::BSI, error::Error}; -use xmas_elf::header::Type as ElfType; +use crate::common::{Lazy, Symbol}; +use crate::linker::Linker; +use crate::error::Error; use xmas_elf::ElfFile; +mod object; mod section; mod section_iter; use section_iter::SectionIter; +pub use object::ElfObject; -pub struct ElfObject<'data> { - origin: PathBuf, - elf: ElfFile<'data>, -} - -impl<'data> ElfObject<'data> { - pub fn new(storage: &'data mut Storage) -> Result { - let origin = storage.origin()?; - let elf = ElfFile::new(storage.bytes()?).map_err(|_| Error::InvalidObjectType(0))?; - - is_relocatable(&elf)?; - let result = ElfObject { origin, elf }; - - Ok(result) - } -} - -impl Relocatable for ElfObject<'_> { - fn origin(&self) -> &Path { - &self.origin - } - - fn sections(&self) -> BSI<'_> { - Box::new(SectionIter { - elf: &self.elf, - iter: self.elf.section_iter(), - }) - } -} - -impl Display for ElfObject<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "==={:?}===\n>Symbols:\n{}\n>Sections:\n", - self.origin().file_name().unwrap(), - "TODO" - )?; - - for section in self.sections() { - let u = section.unwrap(); - write!(f, "{}", u)?; - } - - Ok(()) - } -} - -impl LinkState<'_> { - pub fn new() -> Self { - LinkState { - relocatables: Vec::new(), // it's a trait thing - } +impl Linker<'_> { + // shortcut to avoid turbofish + pub fn elf() -> Self { + Self::new(Vec::new()) } } @@ -80,13 +28,3 @@ impl<'data> Lazy<&'data str, ElfFile<'data>> for Symbol<'data> { self.str_ref.is_some() } } - -fn is_relocatable(elf: &ElfFile) -> Result<(), Error> { - let raw_type = elf.header.pt2.type_(); - let elf_type: ElfType = raw_type.as_type(); - if elf_type != ElfType::Relocatable { - return Err(Error::InvalidObjectType(raw_type.0.into())); - } - - Ok(()) -} diff --git a/src/formats/elf/object.rs b/src/formats/elf/object.rs new file mode 100644 index 0000000..f88aada --- /dev/null +++ b/src/formats/elf/object.rs @@ -0,0 +1,69 @@ +use std::{ + fmt::Display, + path::{Path, PathBuf}, +}; + +use crate::common::{Relocatable, Storage}; +use crate::{common::BSI, error::Error}; +use xmas_elf::header::Type as ElfType; +use xmas_elf::ElfFile; + +use super::SectionIter; + +pub struct ElfObject<'data> { + origin: PathBuf, + elf: ElfFile<'data>, +} + +impl<'data> ElfObject<'data> { + pub fn new(storage: &'data mut Storage) -> Result { + let origin = storage.origin()?; + let elf = ElfFile::new(storage.bytes()?).map_err(|_| Error::InvalidObjectType(0))?; + + is_relocatable(&elf)?; + let result = ElfObject { origin, elf }; + + Ok(result) + } +} + +impl Relocatable for ElfObject<'_> { + fn origin(&self) -> &Path { + &self.origin + } + + fn sections(&self) -> BSI<'_> { + Box::new(SectionIter { + elf: &self.elf, + iter: self.elf.section_iter(), + }) + } +} + +impl Display for ElfObject<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "==={:?}===\n>Symbols:\n{}\n>Sections:\n", + self.origin().file_name().unwrap(), + "TODO" + )?; + + for section in self.sections() { + let u = section.unwrap(); + write!(f, "{}", u)?; + } + + Ok(()) + } +} + +fn is_relocatable(elf: &ElfFile) -> Result<(), Error> { + let raw_type = elf.header.pt2.type_(); + let elf_type: ElfType = raw_type.as_type(); + if elf_type != ElfType::Relocatable { + return Err(Error::InvalidObjectType(raw_type.0.into())); + } + + Ok(()) +} diff --git a/src/linker.rs b/src/linker.rs index d4f80a0..bac47e7 100644 --- a/src/linker.rs +++ b/src/linker.rs @@ -1,22 +1,38 @@ use std::fmt::Display; -use crate::{common::Relocatable, error::Error}; +use crate::{common::{Output, Relocatable}, error::Error}; -pub struct LinkState<'data> { - pub relocatables: Vec>, +pub struct Linker<'data> { + relocatables: Vec>, } -impl<'data> LinkState<'data> { +impl<'data> Linker<'data> { + pub fn new(relocatables: Vec>) -> Self { + Self { + relocatables, + } + } + pub fn add_relocatable( &mut self, relocatable: Box, - ) -> Result<(), Error> { + ) { self.relocatables.push(relocatable); + } - Ok(()) + pub fn link(&self, output: &mut dyn Output) -> Result { + let allocated = output.allocate(self.total_size()?)?; + + for r in self.relocatables.iter() { + for s in r.sections() { + output.append_section(&s?)?; + } + } + + Ok(allocated) } - pub fn total_size(&self) -> Result { + fn total_size(&self) -> Result { let mut result = 0u64; for o in self.relocatables.iter() { @@ -29,11 +45,11 @@ impl<'data> LinkState<'data> { } } -impl Display for LinkState<'_> { +impl Display for Linker<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "===Relocatables===")?; - for r in &self.relocatables { + for r in self.relocatables.iter() { write!(f, "{}", r)?; } diff --git a/src/main.rs b/src/main.rs index 9e20f84..0c6e762 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,9 +3,9 @@ mod error; mod formats; mod linker; -use common::Storage; +use common::{Storage, DummyOutput}; use formats::ElfObject; -use linker::LinkState; +use linker::Linker; fn main() { let mut args = std::env::args().peekable(); @@ -14,7 +14,8 @@ fn main() { args.next().unwrap(); let mut contents: Vec = Vec::new(); - let mut linker = LinkState::new(); + let mut linker = Linker::elf(); + let mut output = DummyOutput; while args.peek().is_some() { let fpath = args.next().expect("Unexpected peek-a-boo"); @@ -23,12 +24,9 @@ fn main() { } for storage in contents.iter_mut() { - let relocatable = ElfObject::new(storage).unwrap(); - linker.add_relocatable(Box::new(relocatable)).unwrap(); + let relocatable = ElfObject::new(storage).expect("Parsing ELF"); + linker.add_relocatable(Box::new(relocatable)); } - let total_size = linker.total_size().expect("Size to be known"); - println!("to allocate: {}", total_size); - - println!("all: \n{}", linker); + linker.link(&mut output).expect("Linking"); }