|
|
@ -25,7 +25,7 @@ use super::ElfObject;
|
|
|
|
pub struct ElfOutput {
|
|
|
|
pub struct ElfOutput {
|
|
|
|
destination: PathBuf,
|
|
|
|
destination: PathBuf,
|
|
|
|
file: ELF64,
|
|
|
|
file: ELF64,
|
|
|
|
input_data: SegmentView,
|
|
|
|
segment_view: SegmentView,
|
|
|
|
writer: BufWriter<File>,
|
|
|
|
writer: BufWriter<File>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -48,23 +48,7 @@ impl ElfOutput {
|
|
|
|
let result = Self {
|
|
|
|
let result = Self {
|
|
|
|
destination,
|
|
|
|
destination,
|
|
|
|
file: elf,
|
|
|
|
file: elf,
|
|
|
|
input_data: SegmentView::default(),
|
|
|
|
segment_view: SegmentView::default(),
|
|
|
|
writer,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn from_object(object: &ElfObject, destination: PathBuf) -> Result<Self, Error> {
|
|
|
|
|
|
|
|
let other = object.elf();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let str_path = expand_path(&destination)?;
|
|
|
|
|
|
|
|
let writer = file_writer(str_path, 0o755)?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let result = Self {
|
|
|
|
|
|
|
|
destination,
|
|
|
|
|
|
|
|
file: elf_bin_from_object(other),
|
|
|
|
|
|
|
|
input_data: SegmentView::default(),
|
|
|
|
|
|
|
|
writer,
|
|
|
|
writer,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -75,7 +59,7 @@ impl ElfOutput {
|
|
|
|
let mut names = Vec::new();
|
|
|
|
let mut names = Vec::new();
|
|
|
|
let mut name_idx = 0usize;
|
|
|
|
let mut name_idx = 0usize;
|
|
|
|
|
|
|
|
|
|
|
|
for (name, sections) in self.input_data.sections_mut() {
|
|
|
|
for (name, sections) in self.segment_view.sections_mut() {
|
|
|
|
let mut data_size = 0;
|
|
|
|
let mut data_size = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for t in sections.iter() {
|
|
|
|
for t in sections.iter() {
|
|
|
@ -147,13 +131,17 @@ impl ElfOutput {
|
|
|
|
// contains .text + .rodata as one segment
|
|
|
|
// contains .text + .rodata as one segment
|
|
|
|
self.populate_segment(
|
|
|
|
self.populate_segment(
|
|
|
|
&mut offset,
|
|
|
|
&mut offset,
|
|
|
|
self.input_data.program_size(),
|
|
|
|
self.segment_view.program_size(),
|
|
|
|
SegmentType::Text,
|
|
|
|
SegmentType::Text,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
// contains .data as one segment
|
|
|
|
// contains .data as one segment
|
|
|
|
self.populate_segment(&mut offset, self.input_data.data_size(), SegmentType::Data);
|
|
|
|
self.populate_segment(
|
|
|
|
|
|
|
|
&mut offset,
|
|
|
|
|
|
|
|
self.segment_view.data_size(),
|
|
|
|
|
|
|
|
SegmentType::Data,
|
|
|
|
|
|
|
|
);
|
|
|
|
// contains .bss as one segment
|
|
|
|
// contains .bss as one segment
|
|
|
|
self.populate_segment(&mut offset, self.input_data.bss_size(), SegmentType::Bss);
|
|
|
|
self.populate_segment(&mut offset, self.segment_view.bss_size(), SegmentType::Bss);
|
|
|
|
|
|
|
|
|
|
|
|
Ok(offset)
|
|
|
|
Ok(offset)
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -161,10 +149,10 @@ impl ElfOutput {
|
|
|
|
|
|
|
|
|
|
|
|
impl Output<ElfObject> for ElfOutput {
|
|
|
|
impl Output<ElfObject> for ElfOutput {
|
|
|
|
fn process_section(&mut self, section: Section<(usize, usize)>) -> Result<(), Error> {
|
|
|
|
fn process_section(&mut self, section: Section<(usize, usize)>) -> Result<(), Error> {
|
|
|
|
self.input_data.append_section(section)
|
|
|
|
self.segment_view.append_section(section)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn finalize(mut self, objects: &Vec<ElfObject>) -> Result<PathBuf, Error> {
|
|
|
|
fn finalize(mut self, objects: &[ElfObject]) -> Result<PathBuf, Error> {
|
|
|
|
const EHS: u64 = size_of::<Ehdr64>() as u64;
|
|
|
|
const EHS: u64 = size_of::<Ehdr64>() as u64;
|
|
|
|
const PHS: u16 = size_of::<Phdr64>() as u16;
|
|
|
|
const PHS: u16 = size_of::<Phdr64>() as u16;
|
|
|
|
const SHS: u16 = size_of::<Shdr64>() as u16;
|
|
|
|
const SHS: u16 = size_of::<Shdr64>() as u16;
|
|
|
@ -207,13 +195,13 @@ impl Output<ElfObject> for ElfOutput {
|
|
|
|
offset += pad_to_next_page(&mut self.writer, offset)?;
|
|
|
|
offset += pad_to_next_page(&mut self.writer, offset)?;
|
|
|
|
eprintln!("Prog start: {}", offset);
|
|
|
|
eprintln!("Prog start: {}", offset);
|
|
|
|
// write section/segment data
|
|
|
|
// write section/segment data
|
|
|
|
for bytes in self.input_data.program_bytes(objects) {
|
|
|
|
for bytes in self.segment_view.program_bytes(objects) {
|
|
|
|
offset += self.writer.write(bytes?)?;
|
|
|
|
offset += self.writer.write(bytes?)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
offset += pad_to_next_page(&mut self.writer, offset)?;
|
|
|
|
offset += pad_to_next_page(&mut self.writer, offset)?;
|
|
|
|
|
|
|
|
|
|
|
|
eprintln!("Data start: {}", offset);
|
|
|
|
eprintln!("Data start: {}", offset);
|
|
|
|
for bytes in self.input_data.data_bytes(objects) {
|
|
|
|
for bytes in self.segment_view.data_bytes(objects) {
|
|
|
|
offset += self.writer.write(bytes?)?;
|
|
|
|
offset += self.writer.write(bytes?)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -236,20 +224,6 @@ fn file_writer(output_filename: &str, permission: u32) -> Result<BufWriter<File>
|
|
|
|
Ok(BufWriter::new(file))
|
|
|
|
Ok(BufWriter::new(file))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// init new ELF64 from an object file meant as executable output
|
|
|
|
|
|
|
|
fn elf_bin_from_object(other: &ELF64) -> ELF64 {
|
|
|
|
|
|
|
|
use elf_utilities::header::Type;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut elf = ELF64::default();
|
|
|
|
|
|
|
|
elf.ehdr.set_elf_type(Type::Exec);
|
|
|
|
|
|
|
|
elf.ehdr.e_ehsize = other.ehdr.e_ehsize;
|
|
|
|
|
|
|
|
elf.ehdr.e_version = other.ehdr.e_version;
|
|
|
|
|
|
|
|
elf.ehdr.e_ident = other.ehdr.e_ident;
|
|
|
|
|
|
|
|
elf.ehdr.e_machine = other.ehdr.e_machine;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elf
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn make_section_header(name_idx: usize, stype: ShType, size: u64) -> Shdr64 {
|
|
|
|
fn make_section_header(name_idx: usize, stype: ShType, size: u64) -> Shdr64 {
|
|
|
|
let mut h = Shdr64::default();
|
|
|
|
let mut h = Shdr64::default();
|
|
|
|
h.set_type(stype);
|
|
|
|
h.set_type(stype);
|
|
|
|