From 16255e6036c74b3a8aa78272c15847951e2c0404 Mon Sep 17 00:00:00 2001 From: Ales Katona Date: Sun, 31 Jan 2021 13:19:21 -0800 Subject: [PATCH] store output section offsets --- src/common/loadable.rs | 81 ++++++++++++++++++++++++++------------- src/common/output.rs | 2 +- src/formats/elf/output.rs | 29 +++++++++++--- src/linker.rs | 2 +- 4 files changed, 79 insertions(+), 35 deletions(-) diff --git a/src/common/loadable.rs b/src/common/loadable.rs index bbdc3d6..dccca7c 100644 --- a/src/common/loadable.rs +++ b/src/common/loadable.rs @@ -13,22 +13,52 @@ pub enum SegmentType { Bss, } +pub struct SegmentSection { + si: SectionInfo, + output_offset: usize, +} + +impl SegmentSection { + // TODO: refactor this into newtype swap with compile-time checking + pub fn section_info(&mut self, output_offset: usize) -> Result<&SectionInfo, Error> { + if self.output_offset > 0 { + Err(Error::InvalidSectionIndex) // duplicate access?? + } else { + self.output_offset = output_offset; + Ok(&mut self.si) + } + } +} + +impl From for SegmentSection { + fn from(si: SectionInfo) -> Self { + Self { + si, + output_offset: 0, + } + } +} + #[derive(Default)] pub struct SegmentSections { - sections_info: Vec, + sections_info: Vec, data_size: u64, } impl SegmentSections { pub fn push(&mut self, si: SectionInfo) { self.data_size += si.data_size; - self.sections_info.push(si); + self.sections_info.push(si.into()); } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.sections_info.iter() } + pub fn iter_mut(&mut self) -> impl Iterator { + self.sections_info.iter_mut() + } + pub fn data_size(&self) -> u64 { self.data_size } @@ -97,33 +127,30 @@ impl Loadable { text.chain(rodata).chain(data).chain(bss) } - pub fn program_bytes<'l, R: Relocatable>( - &'l self, - objects: &'l [R], - ) -> impl Iterator> { - let text_iter = self.text.iter(); - let rodata_iter = self.rodata.iter(); + pub fn program_sections(&mut self) -> impl Iterator { + let text_iter = self.text.iter_mut(); + let rodata_iter = self.rodata.iter_mut(); - let data1 = text_iter.filter_map(move |si| match si.file_size { + let data1 = text_iter.filter_map(move |ss| match ss.si.file_size { 0 => None, - _ => Some(objects[si.object_index].bytes(si.offset, si.file_size)), + _ => Some(ss), }); - let data2 = rodata_iter.filter_map(move |si| match si.data_size { + let data2 = rodata_iter.filter_map(move |ss| match ss.si.data_size { 0 => None, - _ => Some(objects[si.object_index].bytes(si.offset, si.file_size)), + _ => Some(ss), }); data1.chain(data2) } - pub fn data_bytes<'l, R: Relocatable>( - &'l self, - objects: &'l [R], - ) -> impl Iterator> { - let iter = self.data.iter().filter_map(move |si| match si.file_size { - 0 => None, - _ => Some(objects[si.object_index].bytes(si.offset, si.file_size)), - }); + pub fn data_sections(&mut self) -> impl Iterator { + let iter = self + .data + .iter_mut() + .filter_map(move |ss| match ss.si.file_size { + 0 => None, + _ => Some(ss), + }); iter } @@ -134,8 +161,8 @@ impl Loadable { let rodata_iter = self.rodata.iter(); let mut result = 0u64; - for section in text_iter.chain(rodata_iter) { - result += section.data_size + for ss in text_iter.chain(rodata_iter) { + result += ss.si.data_size } result @@ -144,8 +171,8 @@ impl Loadable { // data pub fn data_size(&self) -> u64 { let mut result = 0u64; - for section in self.data.iter() { - result += section.data_size + for ss in self.data.iter() { + result += ss.si.data_size } result @@ -154,8 +181,8 @@ impl Loadable { // bss pub fn bss_size(&self) -> u64 { let mut result = 0u64; - for section in self.bss.iter() { - result += section.data_size + for ss in self.bss.iter() { + result += ss.si.data_size } result diff --git a/src/common/output.rs b/src/common/output.rs index af97107..4de868e 100644 --- a/src/common/output.rs +++ b/src/common/output.rs @@ -7,5 +7,5 @@ pub trait Output where R: Relocatable, { - fn finalize(self, objects: &[R], loadable: &Loadable) -> Result; + fn finalize(self, objects: &[R], loadable: &mut Loadable) -> Result; } diff --git a/src/formats/elf/output.rs b/src/formats/elf/output.rs index be8e9c7..e295cc7 100644 --- a/src/formats/elf/output.rs +++ b/src/formats/elf/output.rs @@ -7,7 +7,7 @@ use elf_utilities::{ }; use crate::{ - common::{expand_path, pad_to_next_page, Loadable, Output, SegmentType}, + common::{expand_path, pad_to_next_page, Loadable, Output, Relocatable, SegmentType}, error::Error, }; @@ -58,7 +58,11 @@ impl ElfOutput { } impl Output for ElfOutput { - fn finalize(mut self, objects: &[ElfObject], loadable: &Loadable) -> Result { + fn finalize( + mut self, + objects: &[ElfObject], + loadable: &mut Loadable, + ) -> Result { const EHS: u64 = size_of::() as u64; const PHS: u16 = size_of::() as u16; const SHS: u16 = size_of::() as u16; @@ -112,14 +116,27 @@ impl Output for ElfOutput { offset += pad_to_next_page(&mut self.writer, offset)?; eprintln!("Prog start: {}", offset); // write section/segment data - for bytes in loadable.program_bytes(objects) { - offset += self.writer.write(bytes?)?; + for ss in loadable.program_sections() { + let si = ss.section_info(offset)?; + let object = objects + .get(si.object_index) + .ok_or(Error::InvalidObjectIndex)?; + let bytes = object.bytes(si.offset, si.file_size)?; + offset += self.writer.write(bytes)?; } + // 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 loadable.data_bytes(objects) { - offset += self.writer.write(bytes?)?; + for ss in loadable.data_sections() { + let si = ss.section_info(offset)?; + let object = objects + .get(si.object_index) + .ok_or(Error::InvalidObjectIndex)?; + let bytes = object.bytes(si.offset, si.file_size)?; + offset += self.writer.write(bytes)?; } self.writer.flush()?; diff --git a/src/linker.rs b/src/linker.rs index 4f99957..d7f3efa 100644 --- a/src/linker.rs +++ b/src/linker.rs @@ -45,7 +45,7 @@ where self.process_symbols()?; self.loadable.set_start_offset(4096); // TODO: get from .start symbol location - self.output.finalize(&self.objects, &self.loadable) + self.output.finalize(&self.objects, &mut self.loadable) } fn process_symbols(&mut self) -> Result<(), Error> {