first draft implementation using xmas_elf
parent
0d7f5a3206
commit
8f0fadf570
@ -1,3 +1,5 @@
|
|||||||
/target
|
/target
|
||||||
|
|
||||||
/assets
|
/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
|
use crate::error::Error;
|
||||||
/// 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>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Relocatable<'a> {
|
use super::Section;
|
||||||
pub fn new(origin: &'a str) -> Self {
|
|
||||||
Self {
|
|
||||||
origin,
|
|
||||||
symbols: Vec::new(),
|
|
||||||
texts: Vec::new(),
|
|
||||||
data: Vec::new(),
|
|
||||||
bss: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Relocatable<'_> {
|
pub type BSI<'data> = Box<dyn Iterator<Item = Result<Section<'data>, Error>> + 'data>;
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
/// Contains all the needed getters to construct a final
|
||||||
write!(
|
/// mushed and relocated executable from an object file
|
||||||
f,
|
pub trait Relocatable: Display {
|
||||||
"==={}===\nSymbols:\n{:?}\nTexts:\n??",
|
fn origin(&self) -> &Path; // not same as section's path since this one's supposed to be cannonical
|
||||||
self.origin, self.symbols //, self.texts
|
|
||||||
)
|
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