|
|
@ -22,21 +22,21 @@ use crate::{
|
|
|
|
use super::segment::*;
|
|
|
|
use super::segment::*;
|
|
|
|
use super::ElfObject;
|
|
|
|
use super::ElfObject;
|
|
|
|
|
|
|
|
|
|
|
|
pub struct ElfOutput<'data> {
|
|
|
|
pub struct ElfOutput {
|
|
|
|
destination: PathBuf,
|
|
|
|
destination: PathBuf,
|
|
|
|
file: ELF64,
|
|
|
|
file: ELF64,
|
|
|
|
input_data: OutputData<'data>,
|
|
|
|
input_data: OutputData,
|
|
|
|
writer: BufWriter<File>,
|
|
|
|
writer: BufWriter<File>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<'data> ElfOutput<'data> {
|
|
|
|
impl ElfOutput {
|
|
|
|
pub fn new(destination: PathBuf) -> Result<Self, Error> {
|
|
|
|
pub fn new(destination: PathBuf) -> Result<Self, Error> {
|
|
|
|
use elf_utilities::header::{Class, Data, Machine, Type, Version, OSABI};
|
|
|
|
use elf_utilities::header::{Class, Data, Machine, Type, Version, OSABI};
|
|
|
|
|
|
|
|
|
|
|
|
let mut elf = ELF64::default();
|
|
|
|
let mut elf = ELF64::default();
|
|
|
|
elf.ehdr.set_elf_type(Type::Exec);
|
|
|
|
elf.ehdr.set_elf_type(Type::Exec);
|
|
|
|
elf.ehdr.set_class(Class::Bit64);
|
|
|
|
elf.ehdr.set_class(Class::Bit64);
|
|
|
|
elf.ehdr.set_machine(Machine::Intel386);
|
|
|
|
elf.ehdr.set_machine(Machine::X8664);
|
|
|
|
elf.ehdr.set_object_version(Version::Current);
|
|
|
|
elf.ehdr.set_object_version(Version::Current);
|
|
|
|
elf.ehdr.set_file_version(Version::Current);
|
|
|
|
elf.ehdr.set_file_version(Version::Current);
|
|
|
|
elf.ehdr.set_osabi(OSABI::Linux);
|
|
|
|
elf.ehdr.set_osabi(OSABI::Linux);
|
|
|
@ -79,9 +79,7 @@ impl<'data> ElfOutput<'data> {
|
|
|
|
let mut data_size = 0;
|
|
|
|
let mut data_size = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for t in sections.iter() {
|
|
|
|
for t in sections.iter() {
|
|
|
|
if let Some(bytes) = t.data {
|
|
|
|
data_size += t.data_size;
|
|
|
|
data_size += bytes.len();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if data_size == 0 {
|
|
|
|
if data_size == 0 {
|
|
|
@ -103,7 +101,7 @@ impl<'data> ElfOutput<'data> {
|
|
|
|
let string_table = build_string_table(names, true);
|
|
|
|
let string_table = build_string_table(names, true);
|
|
|
|
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() as u64),
|
|
|
|
contents: Contents64::Raw(string_table),
|
|
|
|
contents: Contents64::Raw(string_table),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
self.file.add_section(section);
|
|
|
|
self.file.add_section(section);
|
|
|
@ -131,7 +129,7 @@ impl<'data> ElfOutput<'data> {
|
|
|
|
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_filesz = 0;
|
|
|
|
page_size = 0;
|
|
|
|
page_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -161,12 +159,12 @@ impl<'data> ElfOutput<'data> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<'data> Output<'data> for ElfOutput<'data> {
|
|
|
|
impl Output<ElfObject> for ElfOutput {
|
|
|
|
fn process_section(&mut self, section: Section<'data>) -> Result<(), Error> {
|
|
|
|
fn process_section(&mut self, section: Section) -> Result<(), Error> {
|
|
|
|
self.input_data.append_section(section)
|
|
|
|
self.input_data.append_section(section)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn finalize(mut self) -> Result<PathBuf, Error> {
|
|
|
|
fn finalize(mut self, objects: &Vec<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;
|
|
|
@ -209,14 +207,14 @@ impl<'data> Output<'data> for ElfOutput<'data> {
|
|
|
|
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() {
|
|
|
|
for bytes in self.input_data.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() {
|
|
|
|
for bytes in self.input_data.data_bytes(objects) {
|
|
|
|
offset += self.writer.write(bytes)?;
|
|
|
|
offset += self.writer.write(bytes?)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self.writer.flush()?;
|
|
|
|
self.writer.flush()?;
|
|
|
@ -252,7 +250,7 @@ fn elf_bin_from_object(other: &ELF64) -> ELF64 {
|
|
|
|
elf
|
|
|
|
elf
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn make_section_header(name_idx: usize, stype: ShType, size: usize) -> 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);
|
|
|
|
|
|
|
|
|
|
|
@ -262,7 +260,7 @@ fn make_section_header(name_idx: usize, stype: ShType, size: usize) -> Shdr64 {
|
|
|
|
h.sh_name = idx;
|
|
|
|
h.sh_name = idx;
|
|
|
|
// link index
|
|
|
|
// link index
|
|
|
|
h.sh_link = 0;
|
|
|
|
h.sh_link = 0;
|
|
|
|
h.sh_size = size as u64;
|
|
|
|
h.sh_size = size;
|
|
|
|
// filled at finalize()
|
|
|
|
// filled at finalize()
|
|
|
|
// h.sh_offset = offset;
|
|
|
|
// h.sh_offset = offset;
|
|
|
|
|
|
|
|
|
|
|
|