use std::{fmt::Display, path::PathBuf}; use crate::{ common::{Loadable, Output, Relocatable, SymbolIndex}, error::Error, }; pub struct Linker where R: Relocatable, O: Output, { objects: Vec, loadable: Loadable, output: O, } impl Linker where R: Relocatable, O: Output, { pub fn new(output: O) -> Self { Self { objects: Vec::new(), loadable: Loadable::default(), output, } } pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> { let r = R::new(origin, self.objects.len())?; // TODO: parallelize? for section in r.sections() { self.loadable.process_section(section?)?; } self.objects.push(r); Ok(()) } pub fn link(mut self) -> Result { self.process_symbols()?; self.loadable.set_start_offset(4096); // TODO: get from .start symbol location self.output.finalize(&self.objects, &self.loadable) } fn process_symbols(&mut self) -> Result<(), Error> { for r in &self.objects { let symbol_count = r.symbol_count(); for i in 0..symbol_count { let si = SymbolIndex { object_index: r.object_index(), symbol_index: i, }; self.loadable.process_symbol(si, &self.objects)?; } } Ok(()) } } 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.objects.iter() { write!(f, "{}", r)?; } Ok(()) } }