|
|
|
@ -14,14 +14,16 @@ use elf_utilities::{
|
|
|
|
|
segment::{Phdr64, Segment64, Type as SeType, PF_R, PF_W, PF_X},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use crate::{common::{Loadable, Output, Section, SegmentType}, error::Error};
|
|
|
|
|
use crate::{
|
|
|
|
|
common::{Loadable, Output, SegmentType},
|
|
|
|
|
error::Error,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use super::ElfObject;
|
|
|
|
|
|
|
|
|
|
pub struct ElfOutput {
|
|
|
|
|
destination: PathBuf,
|
|
|
|
|
file: ELF64,
|
|
|
|
|
loadable: Loadable,
|
|
|
|
|
writer: BufWriter<File>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -44,18 +46,17 @@ impl ElfOutput {
|
|
|
|
|
let result = Self {
|
|
|
|
|
destination,
|
|
|
|
|
file: elf,
|
|
|
|
|
loadable: Loadable::default(),
|
|
|
|
|
writer,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn populate_sections(&mut self) -> Result<(), Error> {
|
|
|
|
|
fn populate_sections(&mut self, loadable: &Loadable) -> Result<(), Error> {
|
|
|
|
|
let mut names = Vec::new();
|
|
|
|
|
let mut name_idx = 0usize;
|
|
|
|
|
|
|
|
|
|
for (name, sections) in self.loadable.sections_mut() {
|
|
|
|
|
for (name, sections) in loadable.sections() {
|
|
|
|
|
let mut data_size = 0;
|
|
|
|
|
|
|
|
|
|
for t in sections.iter() {
|
|
|
|
@ -121,40 +122,28 @@ impl ElfOutput {
|
|
|
|
|
*offset += page_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn populate_segments(&mut self) -> Result<u64, Error> {
|
|
|
|
|
fn populate_segments(&mut self, loadable: &Loadable) -> Result<u64, Error> {
|
|
|
|
|
let mut offset = 0u64;
|
|
|
|
|
// program header/segments
|
|
|
|
|
// contains .text + .rodata as one segment
|
|
|
|
|
self.populate_segment(
|
|
|
|
|
&mut offset,
|
|
|
|
|
self.loadable.program_size(),
|
|
|
|
|
SegmentType::Text,
|
|
|
|
|
);
|
|
|
|
|
self.populate_segment(&mut offset, loadable.program_size(), SegmentType::Text);
|
|
|
|
|
// contains .data as one segment
|
|
|
|
|
self.populate_segment(
|
|
|
|
|
&mut offset,
|
|
|
|
|
self.loadable.data_size(),
|
|
|
|
|
SegmentType::Data,
|
|
|
|
|
);
|
|
|
|
|
self.populate_segment(&mut offset, loadable.data_size(), SegmentType::Data);
|
|
|
|
|
// contains .bss as one segment
|
|
|
|
|
self.populate_segment(&mut offset, self.loadable.bss_size(), SegmentType::Bss);
|
|
|
|
|
self.populate_segment(&mut offset, loadable.bss_size(), SegmentType::Bss);
|
|
|
|
|
|
|
|
|
|
Ok(offset)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Output<ElfObject> for ElfOutput {
|
|
|
|
|
fn process_section(&mut self, section: Section) -> Result<(), Error> {
|
|
|
|
|
self.loadable.process_section(section)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn finalize(mut self, objects: &[ElfObject]) -> Result<PathBuf, Error> {
|
|
|
|
|
fn finalize(mut self, objects: &[ElfObject], loadable: &Loadable) -> Result<PathBuf, Error> {
|
|
|
|
|
const EHS: u64 = size_of::<Ehdr64>() as u64;
|
|
|
|
|
const PHS: u16 = size_of::<Phdr64>() as u16;
|
|
|
|
|
const SHS: u16 = size_of::<Shdr64>() as u16;
|
|
|
|
|
|
|
|
|
|
self.populate_sections()?;
|
|
|
|
|
let page_size = self.populate_segments()?;
|
|
|
|
|
self.populate_sections(loadable)?;
|
|
|
|
|
let page_size = self.populate_segments(loadable)?;
|
|
|
|
|
|
|
|
|
|
self.file.ehdr.e_shnum = self.file.sections.len() as u16;
|
|
|
|
|
self.file.ehdr.e_entry = 4096; // TODO
|
|
|
|
@ -191,13 +180,13 @@ impl Output<ElfObject> for ElfOutput {
|
|
|
|
|
offset += pad_to_next_page(&mut self.writer, offset)?;
|
|
|
|
|
eprintln!("Prog start: {}", offset);
|
|
|
|
|
// write section/segment data
|
|
|
|
|
for bytes in self.loadable.program_bytes(objects) {
|
|
|
|
|
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 self.loadable.data_bytes(objects) {
|
|
|
|
|
for bytes in loadable.data_bytes(objects) {
|
|
|
|
|
offset += self.writer.write(bytes?)?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|