move loadable out of output

master
Ales Katona 4 years ago
parent 0b5f013323
commit f8acbd37f3
Signed by: almindor
GPG Key ID: 2F773149BF38B48F

@ -32,11 +32,11 @@ impl Loadable {
Ok(()) Ok(())
} }
pub fn sections_mut(&mut self) -> impl Iterator<Item = (&'static str, &mut SegmentSections)> { pub fn sections(&self) -> impl Iterator<Item = (&'static str, &SegmentSections)> {
let text = once(&mut self.text).map(|s| (".text", s)); let text = once(&self.text).map(|s| (".text", s));
let rodata = once(&mut self.rodata).map(|s| (".rodata", s)); let rodata = once(&self.rodata).map(|s| (".rodata", s));
let data = once(&mut self.data).map(|s| (".data", s)); let data = once(&self.data).map(|s| (".data", s));
let bss = once(&mut self.bss).map(|s| (".bss", s)); let bss = once(&self.bss).map(|s| (".bss", s));
text.chain(rodata).chain(data).chain(bss) text.chain(rodata).chain(data).chain(bss)
} }

@ -1,13 +1,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use super::{Relocatable, Section}; use super::{Loadable, Relocatable};
use crate::error::Error; use crate::error::Error;
pub trait Output<R> pub trait Output<R>
where where
R: Relocatable, R: Relocatable,
{ {
fn process_section(&mut self, section: Section) -> Result<(), Error>; fn finalize(self, objects: &[R], loadable: &Loadable) -> Result<PathBuf, Error>;
fn finalize(self, objects: &[R]) -> Result<PathBuf, Error>;
} }

@ -14,11 +14,17 @@ pub struct DataIndex {
impl DataIndex { impl DataIndex {
pub fn new(object_index: usize, section_index: usize) -> Self { pub fn new(object_index: usize, section_index: usize) -> Self {
DataIndex { object_index, section_index } DataIndex {
object_index,
section_index,
}
} }
pub fn for_object(object_index: usize) -> Self { pub fn for_object(object_index: usize) -> Self {
DataIndex { object_index, section_index: 0 } DataIndex {
object_index,
section_index: 0,
}
} }
} }

@ -34,10 +34,6 @@ impl ElfObject {
Ok(result) Ok(result)
} }
pub fn elf(&self) -> &ELF64 {
&self.elf
}
} }
impl Relocatable for ElfObject { impl Relocatable for ElfObject {
@ -63,7 +59,9 @@ impl Relocatable for ElfObject {
if match &s.contents { if match &s.contents {
Contents64::Raw(v) => Some(v), Contents64::Raw(v) => Some(v),
_ => None, _ => None,
}.is_some() { }
.is_some()
{
let si = SectionInfo { let si = SectionInfo {
file_size: s.header.sh_size, file_size: s.header.sh_size,
data_size: s.header.sh_size, data_size: s.header.sh_size,

@ -14,14 +14,16 @@ use elf_utilities::{
segment::{Phdr64, Segment64, Type as SeType, PF_R, PF_W, PF_X}, segment::{Phdr64, Segment64, Type as SeType, PF_R, PF_W, PF_X},
}; };
use crate::{common::{Loadable, Output, Section, SegmentType}, error::Error}; use crate::{
common::{Loadable, Output, SegmentType},
error::Error,
};
use super::ElfObject; use super::ElfObject;
pub struct ElfOutput { pub struct ElfOutput {
destination: PathBuf, destination: PathBuf,
file: ELF64, file: ELF64,
loadable: Loadable,
writer: BufWriter<File>, writer: BufWriter<File>,
} }
@ -44,18 +46,17 @@ impl ElfOutput {
let result = Self { let result = Self {
destination, destination,
file: elf, file: elf,
loadable: Loadable::default(),
writer, writer,
}; };
Ok(result) Ok(result)
} }
fn populate_sections(&mut self) -> Result<(), Error> { fn populate_sections(&mut self, loadable: &Loadable) -> Result<(), Error> {
let mut names = Vec::new(); let mut names = Vec::new();
let mut name_idx = 0usize; let mut name_idx = 0usize;
for (name, sections) in self.loadable.sections_mut() { for (name, sections) in loadable.sections() {
let mut data_size = 0; let mut data_size = 0;
for t in sections.iter() { for t in sections.iter() {
@ -121,40 +122,28 @@ impl ElfOutput {
*offset += page_size; *offset += page_size;
} }
fn populate_segments(&mut self) -> Result<u64, Error> { fn populate_segments(&mut self, loadable: &Loadable) -> Result<u64, Error> {
let mut offset = 0u64; let mut offset = 0u64;
// program header/segments // program header/segments
// contains .text + .rodata as one segment // contains .text + .rodata as one segment
self.populate_segment( self.populate_segment(&mut offset, loadable.program_size(), SegmentType::Text);
&mut offset,
self.loadable.program_size(),
SegmentType::Text,
);
// contains .data as one segment // contains .data as one segment
self.populate_segment( self.populate_segment(&mut offset, loadable.data_size(), SegmentType::Data);
&mut offset,
self.loadable.data_size(),
SegmentType::Data,
);
// contains .bss as one segment // contains .bss as one segment
self.populate_segment(&mut offset, self.loadable.bss_size(), SegmentType::Bss); self.populate_segment(&mut offset, loadable.bss_size(), SegmentType::Bss);
Ok(offset) Ok(offset)
} }
} }
impl Output<ElfObject> for ElfOutput { impl Output<ElfObject> for ElfOutput {
fn process_section(&mut self, section: Section) -> Result<(), Error> { fn finalize(mut self, objects: &[ElfObject], loadable: &Loadable) -> Result<PathBuf, Error> {
self.loadable.process_section(section)
}
fn finalize(mut self, objects: &[ElfObject]) -> Result<PathBuf, Error> {
const EHS: u64 = size_of::<Ehdr64>() as u64; const EHS: u64 = size_of::<Ehdr64>() as u64;
const PHS: u16 = size_of::<Phdr64>() as u16; const PHS: u16 = size_of::<Phdr64>() as u16;
const SHS: u16 = size_of::<Shdr64>() as u16; const SHS: u16 = size_of::<Shdr64>() as u16;
self.populate_sections()?; self.populate_sections(loadable)?;
let page_size = self.populate_segments()?; let page_size = self.populate_segments(loadable)?;
self.file.ehdr.e_shnum = self.file.sections.len() as u16; self.file.ehdr.e_shnum = self.file.sections.len() as u16;
self.file.ehdr.e_entry = 4096; // TODO self.file.ehdr.e_entry = 4096; // TODO
@ -191,13 +180,13 @@ impl Output<ElfObject> for ElfOutput {
offset += pad_to_next_page(&mut self.writer, offset)?; offset += pad_to_next_page(&mut self.writer, offset)?;
eprintln!("Prog start: {}", offset); eprintln!("Prog start: {}", offset);
// write section/segment data // write section/segment data
for bytes in self.loadable.program_bytes(objects) { for bytes in loadable.program_bytes(objects) {
offset += self.writer.write(bytes?)?; offset += self.writer.write(bytes?)?;
} }
offset += pad_to_next_page(&mut self.writer, offset)?; offset += pad_to_next_page(&mut self.writer, offset)?;
eprintln!("Data start: {}", offset); eprintln!("Data start: {}", offset);
for bytes in self.loadable.data_bytes(objects) { for bytes in loadable.data_bytes(objects) {
offset += self.writer.write(bytes?)?; offset += self.writer.write(bytes?)?;
} }

@ -4,7 +4,10 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use crate::{common::{DataIndex, Output, Relocatable}, error::Error}; use crate::{
common::{DataIndex, Loadable, Output, Relocatable},
error::Error,
};
pub struct Linker<R, O> pub struct Linker<R, O>
where where
@ -12,6 +15,7 @@ where
O: Output<R>, O: Output<R>,
{ {
relocatables: Vec<R>, relocatables: Vec<R>,
loadable: Loadable,
output: O, output: O,
} }
@ -23,13 +27,16 @@ where
pub fn new(output: O) -> Self { pub fn new(output: O) -> Self {
Self { Self {
relocatables: Vec::new(), relocatables: Vec::new(),
loadable: Loadable::default(),
output, output,
} }
} }
pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> { pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> {
self.relocatables self.relocatables.push(R::new(
.push(R::new(origin, DataIndex::for_object(self.relocatables.len()))?); origin,
DataIndex::for_object(self.relocatables.len()),
)?);
Ok(()) Ok(())
} }
@ -37,11 +44,11 @@ where
pub fn link(mut self) -> Result<PathBuf, Error> { pub fn link(mut self) -> Result<PathBuf, Error> {
for r in self.relocatables.iter() { for r in self.relocatables.iter() {
for s in r.sections() { for s in r.sections() {
self.output.process_section(s?)?; self.loadable.process_section(s?)?;
} }
} }
self.output.finalize(&self.relocatables) self.output.finalize(&self.relocatables, &self.loadable)
} }
pub fn object_path(origin: &Path) -> Result<PathBuf, Error> { pub fn object_path(origin: &Path) -> Result<PathBuf, Error> {

Loading…
Cancel
Save