|
|
|
@ -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)
|
|
|
|
|
}
|
|
|
|
|