refactoring

master
Ales Katona 4 years ago
parent 8d7f01c86e
commit 21096384d8
Signed by: almindor
GPG Key ID: 2F773149BF38B48F

@ -3,9 +3,11 @@ mod relocatable;
mod section; mod section;
mod storage; mod storage;
mod symbol; mod symbol;
mod output;
pub use lazy::*; pub use lazy::*;
pub use relocatable::*; pub use relocatable::*;
pub use section::*; pub use section::*;
pub use storage::*; pub use storage::*;
pub use symbol::*; pub use symbol::*;
pub use output::*;

@ -0,0 +1,24 @@
use crate::error::Error;
use super::Section;
pub trait Output {
fn allocate(&mut self, size: u64) -> Result<u64, Error>;
fn append_section(&mut self, section: &Section) -> Result<(), Error>;
// fn prepare_symbol<V, S>(&mut self, symbol: impl Lazy<V, S>) -> Result<&mut Self, Error>;
}
pub struct DummyOutput;
impl Output 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> {
eprintln!("Appending section: {}", section);
Ok(())
}
}

@ -1,72 +1,20 @@
use std::{
fmt::Display,
path::{Path, PathBuf},
};
use crate::common::{Lazy, Relocatable, Storage, Symbol}; use crate::common::{Lazy, Symbol};
use crate::linker::LinkState; use crate::linker::Linker;
use crate::{common::BSI, error::Error}; use crate::error::Error;
use xmas_elf::header::Type as ElfType;
use xmas_elf::ElfFile; use xmas_elf::ElfFile;
mod object;
mod section; mod section;
mod section_iter; mod section_iter;
use section_iter::SectionIter; use section_iter::SectionIter;
pub use object::ElfObject;
pub struct ElfObject<'data> { impl Linker<'_> {
origin: PathBuf, // shortcut to avoid turbofish
elf: ElfFile<'data>, pub fn elf() -> Self {
} Self::new(Vec::new())
impl<'data> ElfObject<'data> {
pub fn new(storage: &'data mut Storage) -> Result<Self, Error> {
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
}
} }
} }
@ -80,13 +28,3 @@ impl<'data> Lazy<&'data str, ElfFile<'data>> for Symbol<'data> {
self.str_ref.is_some() 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(())
}

@ -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<Self, Error> {
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(())
}

@ -1,22 +1,38 @@
use std::fmt::Display; use std::fmt::Display;
use crate::{common::Relocatable, error::Error}; use crate::{common::{Output, Relocatable}, error::Error};
pub struct LinkState<'data> { pub struct Linker<'data> {
pub relocatables: Vec<Box<dyn Relocatable + 'data>>, relocatables: Vec<Box<dyn Relocatable + 'data>>,
}
impl<'data> Linker<'data> {
pub fn new(relocatables: Vec<Box<dyn Relocatable + 'data>>) -> Self {
Self {
relocatables,
}
} }
impl<'data> LinkState<'data> {
pub fn add_relocatable( pub fn add_relocatable(
&mut self, &mut self,
relocatable: Box<dyn Relocatable + 'data>, relocatable: Box<dyn Relocatable + 'data>,
) -> Result<(), Error> { ) {
self.relocatables.push(relocatable); self.relocatables.push(relocatable);
}
Ok(()) pub fn link(&self, output: &mut dyn Output) -> Result<u64, Error> {
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<u64, Error> { fn total_size(&self) -> Result<u64, Error> {
let mut result = 0u64; let mut result = 0u64;
for o in self.relocatables.iter() { 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 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "===Relocatables===")?; writeln!(f, "===Relocatables===")?;
for r in &self.relocatables { for r in self.relocatables.iter() {
write!(f, "{}", r)?; write!(f, "{}", r)?;
} }

@ -3,9 +3,9 @@ mod error;
mod formats; mod formats;
mod linker; mod linker;
use common::Storage; use common::{Storage, DummyOutput};
use formats::ElfObject; use formats::ElfObject;
use linker::LinkState; use linker::Linker;
fn main() { fn main() {
let mut args = std::env::args().peekable(); let mut args = std::env::args().peekable();
@ -14,7 +14,8 @@ fn main() {
args.next().unwrap(); args.next().unwrap();
let mut contents: Vec<Storage> = Vec::new(); let mut contents: Vec<Storage> = Vec::new();
let mut linker = LinkState::new(); let mut linker = Linker::elf();
let mut output = DummyOutput;
while args.peek().is_some() { while args.peek().is_some() {
let fpath = args.next().expect("Unexpected peek-a-boo"); let fpath = args.next().expect("Unexpected peek-a-boo");
@ -23,12 +24,9 @@ fn main() {
} }
for storage in contents.iter_mut() { for storage in contents.iter_mut() {
let relocatable = ElfObject::new(storage).unwrap(); let relocatable = ElfObject::new(storage).expect("Parsing ELF");
linker.add_relocatable(Box::new(relocatable)).unwrap(); linker.add_relocatable(Box::new(relocatable));
} }
let total_size = linker.total_size().expect("Size to be known"); linker.link(&mut output).expect("Linking");
println!("to allocate: {}", total_size);
println!("all: \n{}", linker);
} }

Loading…
Cancel
Save