use std::{fmt::Display, path::PathBuf}; use crate::{ common::{DataIndex, Loadable, Output, Relocatable}, error::Error, }; pub struct Linker where R: Relocatable, O: Output, { relocatables: Vec, loadable: Loadable, output: O, } impl Linker where R: Relocatable, O: Output, { pub fn new(output: O) -> Self { Self { relocatables: Vec::new(), loadable: Loadable::default(), output, } } pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> { let r = R::new(origin, DataIndex::for_object(self.relocatables.len()))?; // TODO: parallelize? for s in r.sections() { self.loadable.process_section(s?)?; } self.relocatables.push(r); Ok(()) } pub fn link(mut self) -> Result { self.loadable.start_offset = Some(4096); // TODO: get from .start symbol location self.output.finalize(&self.relocatables, &self.loadable) } // pub fn object_path(origin: &Path) -> Result { // let mut dest = std::fs::canonicalize(origin)?; // if !dest.pop() { // let err = std::io::Error::new(ErrorKind::Other, "Destination path invalid"); // Err(Error::IOError(Box::new(err))) // } else { // dest.push("rld.out"); // Ok(dest) // } // } } impl Display for Linker where R: Relocatable, O: Output, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "===Relocatables===")?; for r in self.relocatables.iter() { write!(f, "{}", r)?; } Ok(()) } }