first draft implementation using xmas_elf
parent
0d7f5a3206
commit
8f0fadf570
@ -1,3 +1,5 @@
|
||||
/target
|
||||
|
||||
/assets
|
||||
|
||||
/docs
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,110 @@
|
||||
use std::iter::Cloned;
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
parts::{Section, SectionInfo, SectionIterResult},
|
||||
};
|
||||
use xmas_elf::{
|
||||
sections::{SectionData, SectionHeader, SectionIter as ElfIter, ShType},
|
||||
ElfFile,
|
||||
};
|
||||
|
||||
impl<'data> Section<'data> {
|
||||
pub fn iterate(
|
||||
elf: &'data ElfFile<'data>,
|
||||
iter: &mut ElfIter<'data, 'data>,
|
||||
) -> SectionIterResult<'data> {
|
||||
if let Some(h) = iter.next() {
|
||||
let h_result = h.get_type().map_err(|e| Error::MissingSectionHeader(e));
|
||||
return match h_result {
|
||||
Ok(h_type) => match h_type {
|
||||
// text, [ro]data
|
||||
ShType::ProgBits => {
|
||||
let s_name = h.get_name(&elf).unwrap_or("null");
|
||||
match section_data_to_iterator(elf, h) {
|
||||
Ok(i) => Section::from_name(s_name, &h, Some(Box::new(i))),
|
||||
Err(err) => SectionIterResult::Err(err),
|
||||
}
|
||||
}
|
||||
// bss
|
||||
ShType::NoBits => {
|
||||
let si = SectionInfo {
|
||||
size: h.size(),
|
||||
data: None,
|
||||
offset: h.offset(),
|
||||
};
|
||||
let s = Section::Bss(si);
|
||||
SectionIterResult::Ok(s)
|
||||
}
|
||||
_ => SectionIterResult::Skip,
|
||||
},
|
||||
Err(err) => SectionIterResult::Err(err),
|
||||
};
|
||||
}
|
||||
|
||||
SectionIterResult::None
|
||||
}
|
||||
|
||||
fn from_name(
|
||||
name: &str,
|
||||
header: &SectionHeader,
|
||||
data: Option<Box<dyn Iterator<Item = u8> + 'data>>,
|
||||
) -> SectionIterResult<'data> {
|
||||
if name.starts_with(".text") {
|
||||
if header.size() == 0 {
|
||||
return SectionIterResult::Skip; // empty texts
|
||||
}
|
||||
let iter = match data {
|
||||
Some(i) => i,
|
||||
None => return SectionIterResult::Err(Error::MissingSectionData(".text")),
|
||||
};
|
||||
let si = SectionInfo {
|
||||
size: header.size(),
|
||||
data: Some(iter),
|
||||
offset: header.offset(),
|
||||
};
|
||||
return SectionIterResult::Ok(Section::Text(si));
|
||||
} else if name.starts_with(".rodata") || name.starts_with(".data") {
|
||||
if header.size() == 0 {
|
||||
return SectionIterResult::Skip; // empty data
|
||||
}
|
||||
let iter = match data {
|
||||
Some(i) => i,
|
||||
None => return SectionIterResult::Err(Error::MissingSectionData(".data")),
|
||||
};
|
||||
let si = SectionInfo {
|
||||
size: header.size(),
|
||||
data: Some(iter),
|
||||
offset: header.offset(),
|
||||
};
|
||||
return SectionIterResult::Ok(Section::Data(si));
|
||||
} else if name.starts_with(".bss") {
|
||||
let si = SectionInfo {
|
||||
size: header.size(),
|
||||
data: None,
|
||||
offset: header.offset(),
|
||||
};
|
||||
return SectionIterResult::Ok(Section::Bss(si));
|
||||
}
|
||||
|
||||
SectionIterResult::Skip
|
||||
}
|
||||
}
|
||||
|
||||
fn section_data_to_iterator<'file>(
|
||||
elf: &'file ElfFile,
|
||||
header: SectionHeader<'file>,
|
||||
) -> Result<Cloned<std::slice::Iter<'file, u8>>, Error> {
|
||||
let data = header
|
||||
.get_data(&elf)
|
||||
.map_err(|e| Error::MissingSectionData(e))?;
|
||||
|
||||
match data {
|
||||
SectionData::Empty => Ok(([]).iter().cloned()),
|
||||
SectionData::Undefined(bytes) => {
|
||||
let iter = bytes.iter().cloned();
|
||||
Ok(iter)
|
||||
}
|
||||
_ => Err(Error::InvalidSectionData), // TODO: more context needed
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
use crate::{
|
||||
error::Error,
|
||||
parts::{Section, SectionIterResult},
|
||||
};
|
||||
use xmas_elf::sections::SectionIter as ElfIter;
|
||||
use xmas_elf::ElfFile;
|
||||
|
||||
pub struct SectionIter<'data> {
|
||||
pub elf: &'data ElfFile<'data>,
|
||||
pub iter: ElfIter<'data, 'data>,
|
||||
}
|
||||
|
||||
impl<'data> Iterator for SectionIter<'data> {
|
||||
type Item = Result<Section<'data>, Error>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match Section::iterate(&self.elf, &mut self.iter) {
|
||||
SectionIterResult::Err(err) => Some(Err(err)),
|
||||
SectionIterResult::None => None,
|
||||
SectionIterResult::Skip => self.next(),
|
||||
SectionIterResult::Ok(r) => Some(Ok(r)),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +1,15 @@
|
||||
use crate::parts::{Symbol, Text, Data, Bss};
|
||||
use std::fmt::Display;
|
||||
use std::path::Path;
|
||||
|
||||
/// Contains all the needed references to construct a final
|
||||
/// mushed and relocated executable from an object file
|
||||
pub struct Relocatable<'a> {
|
||||
pub origin: &'a str,
|
||||
pub symbols: Vec<Symbol<'a>>,
|
||||
pub texts: Vec<Text<'a>>,
|
||||
pub data: Vec<Data<'a>>,
|
||||
pub bss: Vec<Bss<'a>>,
|
||||
}
|
||||
use crate::error::Error;
|
||||
|
||||
impl<'a> Relocatable<'a> {
|
||||
pub fn new(origin: &'a str) -> Self {
|
||||
Self {
|
||||
origin,
|
||||
symbols: Vec::new(),
|
||||
texts: Vec::new(),
|
||||
data: Vec::new(),
|
||||
bss: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
use super::Section;
|
||||
|
||||
impl std::fmt::Display for Relocatable<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"==={}===\nSymbols:\n{:?}\nTexts:\n??",
|
||||
self.origin, self.symbols //, self.texts
|
||||
)
|
||||
}
|
||||
pub type BSI<'data> = Box<dyn Iterator<Item = Result<Section<'data>, Error>> + 'data>;
|
||||
/// Contains all the needed getters to construct a final
|
||||
/// mushed and relocated executable from an object file
|
||||
pub trait Relocatable: Display {
|
||||
fn origin(&self) -> &Path; // not same as section's path since this one's supposed to be cannonical
|
||||
|
||||
fn sections(&self) -> BSI<'_>;
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
use crate::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub type SectionDataIterator<'data> = Box<dyn Iterator<Item = u8> + 'data>;
|
||||
|
||||
pub struct SectionInfo<'data> {
|
||||
pub size: u64,
|
||||
pub data: Option<SectionDataIterator<'data>>,
|
||||
pub offset: u64,
|
||||
}
|
||||
|
||||
pub enum Section<'data> {
|
||||
Text(SectionInfo<'data>),
|
||||
Data(SectionInfo<'data>),
|
||||
Bss(SectionInfo<'data>),
|
||||
}
|
||||
|
||||
impl Section<'_> {
|
||||
pub fn size(&self) -> Result<u64, Error> {
|
||||
match self {
|
||||
Section::Text(s) => Ok(s.size),
|
||||
Section::Data(s) => Ok(s.size),
|
||||
Section::Bss(s) => Ok(s.size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SectionInfo<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"size: {}, data: {}, offset: {}",
|
||||
self.size,
|
||||
self.data.is_some(),
|
||||
self.offset,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Section<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Section::Text(s) => writeln!(f, "TEXT {}", s),
|
||||
Section::Data(s) => writeln!(f, "DATA {}", s),
|
||||
Section::Bss(s) => writeln!(f, "BSS {}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SectionIterResult<'data> {
|
||||
Ok(Section<'data>),
|
||||
Err(Error),
|
||||
Skip,
|
||||
None,
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
|
||||
|
||||
pub struct Text<'a> {
|
||||
pub bytes: &'a [u8],
|
||||
}
|
||||
|
||||
pub struct Data<'a> {
|
||||
pub bytes: &'a [u8],
|
||||
}
|
||||
|
||||
pub struct Bss<'a> {
|
||||
pub bytes: &'a [u8],
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
pub struct Storage {
|
||||
origin: PathBuf,
|
||||
bytes: Vec<u8>, // for storing the total if needed
|
||||
}
|
||||
|
||||
impl Storage {
|
||||
pub fn new(origin: PathBuf) -> Self {
|
||||
Self {
|
||||
origin,
|
||||
bytes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn origin(&self) -> Result<PathBuf, Error> {
|
||||
std::fs::canonicalize(&self.origin).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
pub fn iter(&mut self) -> Result<impl Iterator<Item = &u8>, Error> {
|
||||
self.bytes = std::fs::read(&self.origin)?;
|
||||
|
||||
Ok(self.bytes.iter())
|
||||
}
|
||||
|
||||
pub fn bytes(&mut self) -> Result<&[u8], Error> {
|
||||
self.bytes = std::fs::read(&self.origin)?;
|
||||
|
||||
Ok(&self.bytes)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue