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(())
}
pub fn sections_mut(&mut self) -> impl Iterator<Item = (&'static str, &mut SegmentSections)> {
let text = once(&mut self.text).map(|s| (".text", s));
let rodata = once(&mut self.rodata).map(|s| (".rodata", s));
let data = once(&mut self.data).map(|s| (".data", s));
let bss = once(&mut self.bss).map(|s| (".bss", s));
pub fn sections(&self) -> impl Iterator<Item = (&'static str, &SegmentSections)> {
let text = once(&self.text).map(|s| (".text", s));
let rodata = once(&self.rodata).map(|s| (".rodata", s));
let data = once(&self.data).map(|s| (".data", s));
let bss = once(&self.bss).map(|s| (".bss", s));
text.chain(rodata).chain(data).chain(bss)
}

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

@ -14,11 +14,17 @@ pub struct DataIndex {
impl DataIndex {
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 {
DataIndex { object_index, section_index: 0 }
DataIndex {
object_index,
section_index: 0,
}
}
}

@ -34,10 +34,6 @@ impl ElfObject {
Ok(result)
}
pub fn elf(&self) -> &ELF64 {
&self.elf
}
}
impl Relocatable for ElfObject {
@ -63,7 +59,9 @@ impl Relocatable for ElfObject {
if match &s.contents {
Contents64::Raw(v) => Some(v),
_ => None,
}.is_some() {
}
.is_some()
{
let si = SectionInfo {
file_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},
};
use crate::{common::{Loadable, Output, Section, SegmentType}, error::Error};
use crate::{
common::{Loadable, Output, SegmentType},
error::Error,
};
use super::ElfObject;
pub struct ElfOutput {
destination: PathBuf,
file: ELF64,
loadable: Loadable,
writer: BufWriter<File>,
}
@ -44,18 +46,17 @@ impl ElfOutput {
let result = Self {
destination,
file: elf,
loadable: Loadable::default(),
writer,
};
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 name_idx = 0usize;
for (name, sections) in self.loadable.sections_mut() {
for (name, sections) in loadable.sections() {
let mut data_size = 0;
for t in sections.iter() {
@ -121,40 +122,28 @@ impl ElfOutput {
*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;
// program header/segments
// contains .text + .rodata as one segment
self.populate_segment(
&mut offset,
self.loadable.program_size(),
SegmentType::Text,
);
self.populate_segment(&mut offset, loadable.program_size(), SegmentType::Text);
// contains .data as one segment
self.populate_segment(
&mut offset,
self.loadable.data_size(),
SegmentType::Data,
);
self.populate_segment(&mut offset, loadable.data_size(), SegmentType::Data);
// 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)
}
}
impl Output<ElfObject> for ElfOutput {
fn process_section(&mut self, section: Section) -> Result<(), Error> {
self.loadable.process_section(section)
}
fn finalize(mut self, objects: &[ElfObject]) -> Result<PathBuf, Error> {
fn finalize(mut self, objects: &[ElfObject], loadable: &Loadable) -> Result<PathBuf, Error> {
const EHS: u64 = size_of::<Ehdr64>() as u64;
const PHS: u16 = size_of::<Phdr64>() as u16;
const SHS: u16 = size_of::<Shdr64>() as u16;
self.populate_sections()?;
let page_size = self.populate_segments()?;
self.populate_sections(loadable)?;
let page_size = self.populate_segments(loadable)?;
self.file.ehdr.e_shnum = self.file.sections.len() as u16;
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)?;
eprintln!("Prog start: {}", offset);
// 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 += pad_to_next_page(&mut self.writer, 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?)?;
}

@ -4,7 +4,10 @@ use std::{
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>
where
@ -12,6 +15,7 @@ where
O: Output<R>,
{
relocatables: Vec<R>,
loadable: Loadable,
output: O,
}
@ -23,13 +27,16 @@ where
pub fn new(output: O) -> Self {
Self {
relocatables: Vec::new(),
loadable: Loadable::default(),
output,
}
}
pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> {
self.relocatables
.push(R::new(origin, DataIndex::for_object(self.relocatables.len()))?);
self.relocatables.push(R::new(
origin,
DataIndex::for_object(self.relocatables.len()),
)?);
Ok(())
}
@ -37,11 +44,11 @@ where
pub fn link(mut self) -> Result<PathBuf, Error> {
for r in self.relocatables.iter() {
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> {

Loading…
Cancel
Save