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

@ -4,8 +4,6 @@ use super::Section;
use crate::error::Error; use crate::error::Error;
pub trait Output<'data> { pub trait Output<'data> {
fn allocate(&mut self, size: u64) -> Result<u64, Error>;
fn append_section(&mut self, section: Section<'data>) -> Result<(), Error>; fn append_section(&mut self, section: Section<'data>) -> Result<(), Error>;
// fn prepare_symbol<V, S>(&mut self, symbol: impl Lazy<V, S>) -> Result<&mut Self, Error>; // fn prepare_symbol<V, S>(&mut self, symbol: impl Lazy<V, S>) -> Result<&mut Self, Error>;
@ -16,11 +14,6 @@ pub trait Output<'data> {
pub struct DummyOutput; pub struct DummyOutput;
impl<'data> Output<'data> for DummyOutput { impl<'data> Output<'data> for DummyOutput {
fn allocate(&mut self, size: u64) -> Result<u64, Error> {
eprintln!("Allocating: {}", size);
Ok(size)
}
fn append_section(&mut self, section: Section<'data>) -> Result<(), Error> { fn append_section(&mut self, section: Section<'data>) -> Result<(), Error> {
eprintln!("Appending section: {}", section); eprintln!("Appending section: {}", section);
Ok(()) Ok(())

@ -4,21 +4,22 @@ use std::{
fmt::{Display, Formatter}, fmt::{Display, Formatter},
}; };
pub trait CBI<'data, T>: Iterator<Item = T> { // pub trait CBI<'data, T>: Iterator<Item = T> {
fn clone_to_box(&self) -> Box<dyn CBI<'data, T> + 'data>; // 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 { // 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> { // fn clone_to_box(&self) -> Box<dyn CBI<'data, T> + 'data> {
Box::new(self.clone()) // Box::new(self.clone())
} // }
} // }
pub type SectionDataIterator<'data> = Box<dyn CBI<'data, u8> + 'data>; // pub type SectionDataIterator<'data> = Box<dyn CBI<'data, u8> + 'data>;
#[derive(Clone)]
pub struct SectionInfo<'data> { pub struct SectionInfo<'data> {
pub size: u64, pub size: u64,
pub data: Option<SectionDataIterator<'data>>, pub data: Option<&'data [u8]>,
pub offset: u64, pub offset: u64,
} }
@ -29,19 +30,6 @@ pub enum Section<'data> {
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 {

@ -52,12 +52,12 @@ impl Relocatable for ElfObject {
Type::ProgBits => { Type::ProgBits => {
if s.header.sh_size > 0 { if s.header.sh_size > 0 {
if let Some(di) = match &s.contents { if let Some(di) = match &s.contents {
Contents64::Raw(v) => Some(v.iter()), Contents64::Raw(v) => Some(v),
_ => None, _ => None,
} { } {
let si = SectionInfo { let si = SectionInfo {
size: s.header.sh_size, size: s.header.sh_size,
data: Some(Box::new(di.copied())), data: Some(di),
offset: s.header.sh_offset, offset: s.header.sh_offset,
}; };
let s_name: &str = &s.name; let s_name: &str = &s.name;

@ -25,7 +25,7 @@ use super::ElfObject;
pub struct ElfOutput<'data> { pub struct ElfOutput<'data> {
destination: PathBuf, destination: PathBuf,
file: ELF64, file: ELF64,
segment_data: SegmentData<'data>, input_data: InputData<'data>,
} }
impl<'data> ElfOutput<'data> { impl<'data> ElfOutput<'data> {
@ -44,7 +44,7 @@ impl<'data> ElfOutput<'data> {
Self { Self {
destination, destination,
file: elf, file: elf,
segment_data: SegmentData::new(), input_data: InputData::new(),
} }
} }
@ -54,34 +54,32 @@ impl<'data> ElfOutput<'data> {
Self { Self {
destination, destination,
file: elf_bin_from_object(other), file: elf_bin_from_object(other),
segment_data: SegmentData::new(), input_data: InputData::new(),
} }
} }
fn populate_sections(&mut self) -> Result<u64, Error> { fn populate_sections(&mut self) -> Result<(), Error> {
let mut names = Vec::new(); let mut names = Vec::new();
let mut name_idx = 0usize; let mut name_idx = 0usize;
let mut result = 0u64;
for (name, sections) in self.segment_data.sections_mut() { for (name, sections) in self.input_data.sections_mut() {
let mut data = Vec::new(); let mut data_size = 0;
for t in sections.iter_mut() { for t in sections.iter() {
if let Some(iter) = &mut t.data { if let Some(bytes) = t.data {
data.extend(iter.as_mut()); data_size += bytes.len();
} }
} }
if data.is_empty() { if data_size == 0{
continue; continue;
} }
result += data.len() as u64;
names.push(name); names.push(name);
let section = Section64 { let section = Section64 {
name: name.into(), name: name.into(),
header: make_section_header(name_idx, ShType::ProgBits, data.len()), header: make_section_header(name_idx, ShType::ProgBits, data_size),
contents: Contents64::Raw(data), contents: Contents64::Raw(Vec::new()), // placeholder only
}; };
name_idx += name.len() + 1; name_idx += name.len() + 1;
self.file.add_section(section); self.file.add_section(section);
@ -90,7 +88,6 @@ impl<'data> ElfOutput<'data> {
let name = ".shstrtab"; let name = ".shstrtab";
names.push(name); names.push(name);
let string_table = build_string_table(names, true); let string_table = build_string_table(names, true);
result += string_table.len() as u64;
let section = Section64 { let section = Section64 {
name: name.into(), name: name.into(),
header: make_section_header(name_idx, ShType::StrTab, string_table.len()), header: make_section_header(name_idx, ShType::StrTab, string_table.len()),
@ -98,7 +95,7 @@ impl<'data> ElfOutput<'data> {
}; };
self.file.add_section(section); self.file.add_section(section);
Ok(result) Ok(())
} }
fn populate_segment(&mut self, offset: &mut u64, size: u64, which: SegmentType) { fn populate_segment(&mut self, offset: &mut u64, size: u64, which: SegmentType) {
@ -114,12 +111,15 @@ impl<'data> ElfOutput<'data> {
segment.header.p_memsz = size; segment.header.p_memsz = size;
segment.header.p_offset = *offset; segment.header.p_offset = *offset;
let mut page_size = next_page(size);
match which { match which {
SegmentType::Text => segment.header.p_flags = PF_R | PF_X, SegmentType::Text => segment.header.p_flags = PF_R | PF_X,
SegmentType::Data => segment.header.p_flags = PF_R | PF_W, SegmentType::Data => segment.header.p_flags = PF_R | PF_W,
SegmentType::Bss => { SegmentType::Bss => {
segment.header.p_flags = PF_R; segment.header.p_flags = PF_R;
segment.header.p_memsz = 0; segment.header.p_memsz = 0;
page_size = 0;
} }
} }
@ -127,7 +127,7 @@ 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 += next_page(size); *offset += page_size;
} }
fn populate_segments(&mut self) -> Result<u64, Error> { fn populate_segments(&mut self) -> Result<u64, Error> {
@ -136,29 +136,25 @@ impl<'data> ElfOutput<'data> {
// contains .text + .rodata as one segment // contains .text + .rodata as one segment
self.populate_segment( self.populate_segment(
&mut offset, &mut offset,
self.segment_data.program_size(), self.input_data.program_size(),
SegmentType::Text, SegmentType::Text,
); );
// contains .data as one segment // contains .data as one segment
self.populate_segment( self.populate_segment(
&mut offset, &mut offset,
self.segment_data.data_size(), self.input_data.data_size(),
SegmentType::Data, SegmentType::Data,
); );
// contains .bss as one segment // contains .bss as one segment
self.populate_segment(&mut offset, self.segment_data.bss_size(), SegmentType::Bss); self.populate_segment(&mut offset, self.input_data.bss_size(), SegmentType::Bss);
Ok(offset) Ok(offset)
} }
} }
impl<'data> Output<'data> for ElfOutput<'data> { impl<'data> Output<'data> for ElfOutput<'data> {
fn allocate(&mut self, size: u64) -> Result<u64, Error> {
Ok(size)
}
fn append_section(&mut self, section: Section<'data>) -> Result<(), Error> { fn append_section(&mut self, section: Section<'data>) -> Result<(), Error> {
self.segment_data.append_section(section) self.input_data.append_section(section)
} }
fn finalize(mut self) -> Result<PathBuf, Error> { fn finalize(mut self) -> Result<PathBuf, Error> {
@ -169,20 +165,19 @@ impl<'data> Output<'data> for ElfOutput<'data> {
self.populate_sections()?; self.populate_sections()?;
let page_size = self.populate_segments()?; let page_size = self.populate_segments()?;
self.file.ehdr.e_shnum = self.file.sections.len() as u16;
self.file.ehdr.e_entry = 4096; // TODO
self.file.ehdr.e_phentsize = PHS; 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;
self.file.ehdr.e_shoff = self.file.ehdr.e_phoff self.file.ehdr.e_shoff = self.file.ehdr.e_phoff + (usize::from(self.file.ehdr.e_phentsize) * self.file.segments.len()) as u64;
+ u64::from(self.file.ehdr.e_phnum * self.file.ehdr.e_phentsize)
+ page_size;
self.file.ehdr.e_shnum = self.file.sections.len() as u16;
self.file.ehdr.e_entry = 0x100; // TODO
let str_path = expand_path(&self.destination)?; let str_path = expand_path(&self.destination)?;
let mut writer = file_writer(str_path, 0o755)?; let mut writer = file_writer(str_path, 0o755)?;
let mut offset = 0; let mut offset = 0;
// write ELF header
offset += writer.write(&self.file.ehdr.to_le_bytes())?; offset += writer.write(&self.file.ehdr.to_le_bytes())?;
// write program header table // write program header table
@ -191,17 +186,32 @@ impl<'data> Output<'data> for ElfOutput<'data> {
offset += writer.write(&seg.header.to_le_bytes())?; offset += writer.write(&seg.header.to_le_bytes())?;
} }
// write section/segment data eprintln!("SH start: {}", offset);
// write section header table
for sec in self.file.sections.iter_mut() { for sec in self.file.sections.iter_mut() {
sec.header.sh_offset = offset as u64; if sec.header.get_type() == ShType::StrTab {
offset += write_padded(&mut writer, offset, &sec.to_le_bytes())?; sec.header.sh_offset = offset as u64 + u64::from(SHS);
}
offset += writer.write(&sec.header.to_le_bytes())?;
if sec.header.get_type() == ShType::StrTab {
offset += writer.write(&sec.to_le_bytes())?;
}
} }
eprintln!("SHT: {}", offset); // program data (segments)
// write section header table offset += pad_to_next_page(&mut writer, offset)?;
for sec in self.file.sections.iter() { eprintln!("Prog start: {}", offset);
offset += writer.write(&sec.header.to_le_bytes())?; // write section/segment data
for bytes in self.input_data.program_bytes() {
offset += writer.write(bytes)?;
}
offset += pad_to_next_page(&mut writer, offset)?;
eprintln!("Data start: {}", offset);
for bytes in self.input_data.data_bytes() {
offset += writer.write(bytes)?;
} }
writer.flush()?; writer.flush()?;
Ok(self.destination) Ok(self.destination)
@ -213,7 +223,7 @@ fn file_writer(output_filename: &str, permission: u32) -> Result<BufWriter<File>
let file = std::fs::OpenOptions::new() let file = std::fs::OpenOptions::new()
.create(true) .create(true)
.read(true) .truncate(true)
.write(true) .write(true)
.mode(permission) .mode(permission)
.open(output_filename)?; .open(output_filename)?;
@ -271,14 +281,13 @@ fn next_page(size: u64) -> u64 {
page_size * pages_needed page_size * pages_needed
} }
fn write_padded(writer: &mut BufWriter<File>, offset: usize, data: &[u8]) -> Result<usize, Error> { fn pad_to_next_page(writer: &mut BufWriter<File>, offset: usize) -> Result<usize, Error> {
let page_size = page_size::get(); let page_size = page_size::get();
let mut written = 0usize;
written += writer.write(data)?; let padding = page_size - (offset % page_size);
let padding = page_size - (page_size % offset);
written += writer.get_mut().seek(SeekFrom::Current(padding as i64))? as usize; eprintln!("Padding from: {} with: {}", offset, padding);
writer.seek(SeekFrom::Current(padding.try_into()?))?;
Ok(written) Ok(padding)
} }

@ -1,5 +1,5 @@
use crate::common::SectionInfo; use crate::common::SectionInfo;
use crate::common::{Section, SectionDataIterator}; use crate::common::{Section};
use crate::error::Error; use crate::error::Error;
const SI_TEXT: usize = 0; const SI_TEXT: usize = 0;
@ -15,9 +15,9 @@ pub enum SegmentType {
const SEGMENT_NAMES: [&str; 4] = [".text", ".rodata", ".data", ".bss"]; const SEGMENT_NAMES: [&str; 4] = [".text", ".rodata", ".data", ".bss"];
pub struct SegmentData<'data>([Vec<SectionInfo<'data>>; 4]); pub struct InputData<'data>([Vec<SectionInfo<'data>>; 4]);
impl<'data> SegmentData<'data> { impl<'data> InputData<'data> {
pub fn new() -> Self { pub fn new() -> Self {
Self([Vec::new(), Vec::new(), Vec::new(), Vec::new()]) Self([Vec::new(), Vec::new(), Vec::new(), Vec::new()])
} }
@ -42,20 +42,18 @@ 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> { pub fn program_bytes<'local>(&'local self) -> impl Iterator<Item = &'local [u8]> {
let text_iter = self.0[SI_TEXT].iter(); let text_iter = self.0[SI_TEXT].iter();
let rodata_iter = self.0[SI_RODATA].iter(); let rodata_iter = self.0[SI_RODATA].iter();
let data1 = text_iter.filter_map(|si| match si.data.as_ref() { let data1 = text_iter.filter_map(|si| si.data);
Some(iter) => Some(iter.clone_to_box()), let data2 = rodata_iter.filter_map(|si| si.data);
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()) data1.chain(data2)
}
pub fn data_bytes<'local>(&'local self) -> impl Iterator<Item = &'local [u8]> {
self.0[SI_DATA].iter().filter_map(|si| si.data)
} }
// .text + .rodata // .text + .rodata
@ -92,7 +90,7 @@ impl<'data> SegmentData<'data> {
} }
} }
impl Default for SegmentData<'_> { impl Default for InputData<'_> {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }

@ -19,27 +19,13 @@ impl<'data> Linker<'data> {
} }
pub fn link(&'data 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() { for r in self.relocatables.iter() {
for s in r.sections() { for s in r.sections() {
output.append_section(s?)?; output.append_section(s?)?;
} }
} }
Ok(allocated) Ok(0)
}
fn total_size(&self) -> Result<u64, Error> {
let mut result = 0u64;
for o in self.relocatables.iter() {
for s in o.sections() {
result += s?.size()?;
}
}
Ok(result)
} }
} }

Loading…
Cancel
Save