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},
};
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 size: u64,
@ -12,12 +22,26 @@ pub struct SectionInfo<'data> {
pub offset: u64,
}
#[derive(Clone)]
pub enum Section<'data> {
Text(SectionInfo<'data>),
Data(SectionInfo<'data>, bool), // readonly bool
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<'_> {
pub fn size(&self) -> Result<u64, Error> {
match self {

@ -10,6 +10,7 @@ pub enum Error {
InvalidSectionName,
InvalidSectionData,
ParseError(Box<dyn std::error::Error>),
TryFromIntError, //
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 {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
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::{
file::ELF64,
@ -56,7 +63,7 @@ impl<'data> ElfOutput<'data> {
let mut name_idx = 0usize;
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();
for t in sections.iter_mut() {
@ -94,9 +101,9 @@ impl<'data> ElfOutput<'data> {
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 {
return 0;
return;
}
let mut segment = Segment64 {
@ -120,32 +127,28 @@ impl<'data> ElfOutput<'data> {
self.file.ehdr.e_phnum += 1;
self.file.ehdr.e_phentsize = size_of::<Phdr64>() as u16;
*offset += size;
size
*offset += next_page(size);
}
fn populate_segments(&mut self) -> Result<u64, Error> {
let mut offset = 0u64;
let mut result = 0u64;
// program header/segments
// contains .text + .rodata as one segment
result += self.populate_segment(
self.populate_segment(
&mut offset,
self.segment_data.program_size(),
SegmentType::Text,
);
// contains .data as one segment
result += self.populate_segment(
self.populate_segment(
&mut offset,
self.segment_data.data_size(),
SegmentType::Data,
);
// 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> {
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;
let segment_data_size = self.populate_sections()?;
self.populate_segments()?;
self.populate_sections()?;
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_phoff = EHS; // TODO: align
self.file.ehdr.e_shoff = self.file.ehdr.e_phoff
+ 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_entry = 0x100; // TODO
@ -191,9 +194,10 @@ impl<'data> Output<'data> for ElfOutput<'data> {
// write section/segment data
for sec in self.file.sections.iter_mut() {
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
for sec in self.file.sections.iter() {
offset += writer.write(&sec.header.to_le_bytes())?;
@ -237,7 +241,7 @@ fn make_section_header(name_idx: usize, stype: ShType, size: usize) -> Shdr64 {
// section index used for name and section indexing (currently same)
let idx = 1 + (name_idx as u32); // add 0 at start
// name index
// name index
h.sh_name = idx;
// link index
h.sh_link = 0;
@ -257,4 +261,24 @@ fn expand_path(path: &Path) -> Result<&str, Error> {
let boxed = Box::new(ioe);
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::{Section, SectionDataIterator};
use crate::error::Error;
const SI_TEXT: usize = 0;
@ -33,7 +33,7 @@ impl<'data> SegmentData<'data> {
Ok(())
}
pub fn iter_mut(
pub fn sections_mut(
&mut self,
) -> impl Iterator<Item = (&'static str, &mut Vec<SectionInfo<'data>>)> {
self.0
@ -42,6 +42,22 @@ impl<'data> SegmentData<'data> {
.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
pub fn program_size(&self) -> u64 {
let text_iter = self.0[SI_TEXT].iter();

@ -18,7 +18,7 @@ impl<'data> Linker<'data> {
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()?)?;
for r in self.relocatables.iter() {

Loading…
Cancel
Save