|
|
|
@ -1,10 +1,4 @@
|
|
|
|
|
use std::{
|
|
|
|
|
fs::File,
|
|
|
|
|
io::BufWriter,
|
|
|
|
|
io::{Write},
|
|
|
|
|
mem::size_of,
|
|
|
|
|
path::{PathBuf},
|
|
|
|
|
};
|
|
|
|
|
use std::{fs::File, io::BufWriter, io::Write, mem::size_of, path::PathBuf};
|
|
|
|
|
|
|
|
|
|
use elf_utilities::{
|
|
|
|
|
header::Ehdr64,
|
|
|
|
@ -19,6 +13,8 @@ use crate::{
|
|
|
|
|
|
|
|
|
|
use super::ElfObject;
|
|
|
|
|
|
|
|
|
|
const SECTION_NAMES: [&str; 5] = [".text", ".rodata", ".data", ".bss", ".shstrtab"];
|
|
|
|
|
|
|
|
|
|
pub struct ElfOutput {
|
|
|
|
|
destination: PathBuf,
|
|
|
|
|
writer: BufWriter<File>,
|
|
|
|
@ -36,6 +32,29 @@ impl ElfOutput {
|
|
|
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn write_shstrtab(
|
|
|
|
|
&mut self,
|
|
|
|
|
shstrtab: (Vec<u8>, Vec<usize>),
|
|
|
|
|
mut offset: usize,
|
|
|
|
|
name_idx: usize,
|
|
|
|
|
) -> Result<usize, Error> {
|
|
|
|
|
const SHS: u16 = size_of::<Shdr64>() as u16;
|
|
|
|
|
|
|
|
|
|
// write .shstrtab header
|
|
|
|
|
let data_offset = (offset + usize::from(SHS)) as u64;
|
|
|
|
|
let strtab_header = make_section_header(
|
|
|
|
|
shstrtab.1[name_idx],
|
|
|
|
|
ShType::StrTab,
|
|
|
|
|
data_offset,
|
|
|
|
|
shstrtab.0.len() as u64,
|
|
|
|
|
);
|
|
|
|
|
offset += self.writer.write(&strtab_header.to_le_bytes())?;
|
|
|
|
|
// write .shstrtab data
|
|
|
|
|
offset += self.writer.write(&shstrtab.0)?;
|
|
|
|
|
|
|
|
|
|
Ok(offset)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Output<ElfObject> for ElfOutput {
|
|
|
|
@ -44,10 +63,10 @@ impl Output<ElfObject> for ElfOutput {
|
|
|
|
|
const PHS: u16 = size_of::<Phdr64>() as u16;
|
|
|
|
|
const SHS: u16 = size_of::<Shdr64>() as u16;
|
|
|
|
|
|
|
|
|
|
let strtab = make_strtab();
|
|
|
|
|
let shstrtab = make_shstrtab();
|
|
|
|
|
let mut ehdr = make_elf_header();
|
|
|
|
|
ehdr.e_shnum = Loadable::section_count() as u16 + 1; // +1 for .shstrtab
|
|
|
|
|
ehdr.e_phnum = Loadable::segment_count() as u16;
|
|
|
|
|
ehdr.e_shnum = SECTION_NAMES.len() as u16;
|
|
|
|
|
ehdr.e_phnum = 3u16; // .text, .rodata + .data, .bss
|
|
|
|
|
ehdr.e_shstrndx = ehdr.e_shnum - 1; // .shstrab is always last
|
|
|
|
|
ehdr.e_entry = loadable.start_offset()?;
|
|
|
|
|
ehdr.e_phentsize = PHS;
|
|
|
|
@ -77,7 +96,7 @@ impl Output<ElfObject> for ElfOutput {
|
|
|
|
|
// write section header table (text + rodata + data + bss)
|
|
|
|
|
for sections in loadable.segment_sections() {
|
|
|
|
|
let sh = make_section_header(
|
|
|
|
|
strtab.1[name_idx],
|
|
|
|
|
shstrtab.1[name_idx],
|
|
|
|
|
ShType::ProgBits,
|
|
|
|
|
0,
|
|
|
|
|
sections.data_size(),
|
|
|
|
@ -87,19 +106,7 @@ impl Output<ElfObject> for ElfOutput {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// .shstrtab as last section header written (+ the name data including)
|
|
|
|
|
{
|
|
|
|
|
// write .shstrtab header
|
|
|
|
|
let data_offset = (offset + usize::from(SHS)) as u64;
|
|
|
|
|
let strtab_header = make_section_header(
|
|
|
|
|
strtab.1[name_idx],
|
|
|
|
|
ShType::StrTab,
|
|
|
|
|
data_offset,
|
|
|
|
|
strtab.0.len() as u64,
|
|
|
|
|
);
|
|
|
|
|
offset += self.writer.write(&strtab_header.to_le_bytes())?;
|
|
|
|
|
// write .shstrtab data
|
|
|
|
|
offset += self.writer.write(&strtab.0)?;
|
|
|
|
|
}
|
|
|
|
|
offset = self.write_shstrtab(shstrtab, offset, name_idx)?;
|
|
|
|
|
|
|
|
|
|
// program data (segments)
|
|
|
|
|
offset += pad_to_next_page(&mut self.writer, offset)?;
|
|
|
|
@ -188,11 +195,8 @@ fn make_program_header(offset: usize, size: u64, which: SegmentType) -> Phdr64 {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// strtab as bytes + indexes to individual strings
|
|
|
|
|
fn make_strtab() -> (Vec<u8>, Vec<usize>) {
|
|
|
|
|
let mut section_names = Vec::from(Loadable::section_names());
|
|
|
|
|
section_names.push(".shstrtab");
|
|
|
|
|
|
|
|
|
|
let strtab_bytes = build_string_table(section_names, true);
|
|
|
|
|
fn make_shstrtab() -> (Vec<u8>, Vec<usize>) {
|
|
|
|
|
let strtab_bytes = build_string_table(Vec::from(SECTION_NAMES), true);
|
|
|
|
|
|
|
|
|
|
let mut indexes = Vec::new();
|
|
|
|
|
let mut on_string = false;
|
|
|
|
|