master
Ales Katona 4 years ago
parent 5f432c6eea
commit f5ae47bf42
Signed by: almindor
GPG Key ID: 2F773149BF38B48F

@ -4,7 +4,17 @@ use std::{
fmt::{Display, Formatter}, fmt::{Display, Formatter},
}; };
pub type SectionDataIterator<'data> = Box<dyn Iterator<Item = u8> + 'data>; pub trait CBI<'data, T>: Iterator<Item = T> {
fn clone_to_box(&self) -> Box<dyn CBI<'data, T> + 'data>;
}
impl<'data, T, X: 'data + Iterator<Item = T> + Clone> CBI<'data, T> for X {
fn clone_to_box(&self) -> Box<dyn CBI<'data, T> + 'data> {
Box::new(self.clone())
}
}
pub type SectionDataIterator<'data> = Box<dyn CBI<'data, u8> + 'data>;
pub struct SectionInfo<'data> { pub struct SectionInfo<'data> {
pub size: u64, pub size: u64,
@ -12,12 +22,26 @@ pub struct SectionInfo<'data> {
pub offset: u64, pub offset: u64,
} }
#[derive(Clone)]
pub enum Section<'data> { pub enum Section<'data> {
Text(SectionInfo<'data>), Text(SectionInfo<'data>),
Data(SectionInfo<'data>, bool), // readonly bool Data(SectionInfo<'data>, bool), // readonly bool
Bss(SectionInfo<'data>), Bss(SectionInfo<'data>),
} }
impl<'data> Clone for SectionInfo<'data> {
fn clone(&self) -> Self {
Self {
size: self.size,
data: match self.data.as_ref() {
Some(iter) => Some(iter.clone_to_box()),
None => None,
},
offset: self.offset,
}
}
}
impl Section<'_> { impl Section<'_> {
pub fn size(&self) -> Result<u64, Error> { pub fn size(&self) -> Result<u64, Error> {
match self { match self {

@ -10,6 +10,7 @@ pub enum Error {
InvalidSectionName, InvalidSectionName,
InvalidSectionData, InvalidSectionData,
ParseError(Box<dyn std::error::Error>), ParseError(Box<dyn std::error::Error>),
TryFromIntError, //
LinkingError(Trace), LinkingError(Trace),
} }
@ -33,6 +34,12 @@ impl From<std::io::Error> for Error {
} }
} }
impl From<std::num::TryFromIntError> for Error {
fn from(err: std::num::TryFromIntError) -> Self {
Self::TryFromIntError
}
}
impl Display for Error { impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "TODO!") write!(f, "TODO!")

@ -1,4 +1,11 @@
use std::{fs::File, io::BufWriter, io::Write, mem::size_of, path::{Path, PathBuf}}; use std::{
convert::TryInto,
fs::File,
io::BufWriter,
io::{Seek, SeekFrom, Write},
mem::size_of,
path::{Path, PathBuf},
};
use elf_utilities::{ use elf_utilities::{
file::ELF64, file::ELF64,
@ -56,7 +63,7 @@ impl<'data> ElfOutput<'data> {
let mut name_idx = 0usize; let mut name_idx = 0usize;
let mut result = 0u64; let mut result = 0u64;
for (name, sections) in self.segment_data.iter_mut() { for (name, sections) in self.segment_data.sections_mut() {
let mut data = Vec::new(); let mut data = Vec::new();
for t in sections.iter_mut() { for t in sections.iter_mut() {
@ -94,9 +101,9 @@ impl<'data> ElfOutput<'data> {
Ok(result) Ok(result)
} }
fn populate_segment(&mut self, offset: &mut u64, size: u64, which: SegmentType) -> u64 { fn populate_segment(&mut self, offset: &mut u64, size: u64, which: SegmentType) {
if size == 0 { if size == 0 {
return 0; return;
} }
let mut segment = Segment64 { let mut segment = Segment64 {
@ -120,32 +127,28 @@ impl<'data> ElfOutput<'data> {
self.file.ehdr.e_phnum += 1; self.file.ehdr.e_phnum += 1;
self.file.ehdr.e_phentsize = size_of::<Phdr64>() as u16; self.file.ehdr.e_phentsize = size_of::<Phdr64>() as u16;
*offset += size; *offset += next_page(size);
size
} }
fn populate_segments(&mut self) -> Result<u64, Error> { fn populate_segments(&mut self) -> Result<u64, Error> {
let mut offset = 0u64; let mut offset = 0u64;
let mut result = 0u64;
// program header/segments // program header/segments
// contains .text + .rodata as one segment // contains .text + .rodata as one segment
result += self.populate_segment( self.populate_segment(
&mut offset, &mut offset,
self.segment_data.program_size(), self.segment_data.program_size(),
SegmentType::Text, SegmentType::Text,
); );
// contains .data as one segment // contains .data as one segment
result += self.populate_segment( self.populate_segment(
&mut offset, &mut offset,
self.segment_data.data_size(), self.segment_data.data_size(),
SegmentType::Data, SegmentType::Data,
); );
// contains .bss as one segment // contains .bss as one segment
result +=
self.populate_segment(&mut offset, self.segment_data.bss_size(), SegmentType::Bss); self.populate_segment(&mut offset, self.segment_data.bss_size(), SegmentType::Bss);
Ok(result) Ok(offset)
} }
} }
@ -160,18 +163,18 @@ impl<'data> Output<'data> for ElfOutput<'data> {
fn finalize(mut self) -> Result<PathBuf, Error> { fn finalize(mut self) -> Result<PathBuf, Error> {
const EHS: u64 = size_of::<Ehdr64>() as u64; const EHS: u64 = size_of::<Ehdr64>() as u64;
const PHS: u64 = size_of::<Phdr64>() as u64; const PHS: u16 = size_of::<Phdr64>() as u16;
const SHS: u16 = size_of::<Shdr64>() as u16; const SHS: u16 = size_of::<Shdr64>() as u16;
let segment_data_size = self.populate_sections()?; self.populate_sections()?;
self.populate_segments()?; let page_size = self.populate_segments()?;
self.file.ehdr.e_phentsize = PHS as u16; self.file.ehdr.e_phentsize = PHS;
self.file.ehdr.e_shentsize = SHS; self.file.ehdr.e_shentsize = SHS;
self.file.ehdr.e_phoff = EHS; // TODO: align self.file.ehdr.e_phoff = EHS; // TODO: align
self.file.ehdr.e_shoff = self.file.ehdr.e_phoff self.file.ehdr.e_shoff = self.file.ehdr.e_phoff
+ u64::from(self.file.ehdr.e_phnum * self.file.ehdr.e_phentsize) + u64::from(self.file.ehdr.e_phnum * self.file.ehdr.e_phentsize)
+ segment_data_size; + page_size;
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 = 0x100; // TODO self.file.ehdr.e_entry = 0x100; // TODO
@ -191,9 +194,10 @@ impl<'data> Output<'data> for ElfOutput<'data> {
// write section/segment data // write section/segment data
for sec in self.file.sections.iter_mut() { for sec in self.file.sections.iter_mut() {
sec.header.sh_offset = offset as u64; sec.header.sh_offset = offset as u64;
offset += writer.write(&sec.to_le_bytes())?; offset += write_padded(&mut writer, offset, &sec.to_le_bytes())?;
} }
eprintln!("SHT: {}", offset);
// write section header table // write section header table
for sec in self.file.sections.iter() { for sec in self.file.sections.iter() {
offset += writer.write(&sec.header.to_le_bytes())?; offset += writer.write(&sec.header.to_le_bytes())?;
@ -258,3 +262,23 @@ fn expand_path(path: &Path) -> Result<&str, Error> {
Error::IOError(boxed) Error::IOError(boxed)
}) })
} }
fn next_page(size: u64) -> u64 {
let page_size: u64 = page_size::get() as u64;
let pages_needed = (size / page_size) + 1;
page_size * pages_needed
}
fn write_padded(writer: &mut BufWriter<File>, offset: usize, data: &[u8]) -> Result<usize, Error> {
let page_size = page_size::get();
let mut written = 0usize;
written += writer.write(data)?;
let padding = page_size - (page_size % offset);
written += writer.get_mut().seek(SeekFrom::Current(padding as i64))? as usize;
Ok(written)
}

@ -1,5 +1,5 @@
use crate::common::Section;
use crate::common::SectionInfo; use crate::common::SectionInfo;
use crate::common::{Section, SectionDataIterator};
use crate::error::Error; use crate::error::Error;
const SI_TEXT: usize = 0; const SI_TEXT: usize = 0;
@ -33,7 +33,7 @@ impl<'data> SegmentData<'data> {
Ok(()) Ok(())
} }
pub fn iter_mut( pub fn sections_mut(
&mut self, &mut self,
) -> impl Iterator<Item = (&'static str, &mut Vec<SectionInfo<'data>>)> { ) -> impl Iterator<Item = (&'static str, &mut Vec<SectionInfo<'data>>)> {
self.0 self.0
@ -42,6 +42,22 @@ impl<'data> SegmentData<'data> {
.map(|(i, s)| (SEGMENT_NAMES[i], s)) .map(|(i, s)| (SEGMENT_NAMES[i], s))
} }
pub fn program_data<'local>(&'local self) -> Box<dyn Iterator<Item = u8> + 'local> {
let text_iter = self.0[SI_TEXT].iter();
let rodata_iter = self.0[SI_RODATA].iter();
let data1 = text_iter.filter_map(|si| match si.data.as_ref() {
Some(iter) => Some(iter.clone_to_box()),
None => None,
});
let data2 = rodata_iter.filter_map(|si| match si.data.as_ref() {
Some(iter) => Some(iter.clone_to_box()),
None => None,
});
Box::new(data1.chain(data2).flatten())
}
// .text + .rodata // .text + .rodata
pub fn program_size(&self) -> u64 { pub fn program_size(&self) -> u64 {
let text_iter = self.0[SI_TEXT].iter(); let text_iter = self.0[SI_TEXT].iter();

@ -18,7 +18,7 @@ impl<'data> Linker<'data> {
self.relocatables.push(relocatable); self.relocatables.push(relocatable);
} }
pub fn link<'l: 'data>(&'l self, output: &mut dyn Output<'data>) -> Result<u64, Error> { pub fn link(&'data self, output: &mut dyn Output<'data>) -> Result<u64, Error> {
let allocated = output.allocate(self.total_size()?)?; let allocated = output.allocate(self.total_size()?)?;
for r in self.relocatables.iter() { for r in self.relocatables.iter() {

Loading…
Cancel
Save