add xmas-elf support together with elf-utils
parent
951358daac
commit
0e1c83bbed
@ -1,3 +1,5 @@
|
|||||||
mod elf;
|
mod elf;
|
||||||
|
mod xelf;
|
||||||
|
|
||||||
pub use elf::*;
|
pub use elf::*;
|
||||||
|
pub use xelf::*;
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
use crate::common::{Lazy, Symbol};
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::linker::Linker;
|
||||||
|
use xmas_elf::ElfFile;
|
||||||
|
|
||||||
|
mod object;
|
||||||
|
|
||||||
|
pub use object::XElfObject;
|
||||||
|
|
||||||
|
impl Linker<'_> {
|
||||||
|
// shortcut to avoid turbofish
|
||||||
|
pub fn xelf() -> Self {
|
||||||
|
Self::new(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'data> Lazy<&'data str, ElfFile<'data>> for Symbol<'data> {
|
||||||
|
fn value(&self, src: &ElfFile<'data>) -> Result<&'data str, Error> {
|
||||||
|
src.get_string(self.index)
|
||||||
|
.map_err(|e| Error::MissingSectionData(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolved(&self) -> bool {
|
||||||
|
self.str_ref.is_some()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
use std::{
|
||||||
|
convert::TryFrom,
|
||||||
|
fmt::Display,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::common::{Relocatable, Section, SectionInfo, Storage};
|
||||||
|
use crate::{common::BSI, error::Error};
|
||||||
|
use xmas_elf::{ElfFile, sections::{SectionData, SectionHeader}};
|
||||||
|
use xmas_elf::{header::Type as ElfType, sections::ShType};
|
||||||
|
|
||||||
|
pub struct XElfObject<'data> {
|
||||||
|
origin: PathBuf,
|
||||||
|
elf: ElfFile<'data>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'data> XElfObject<'data> {
|
||||||
|
pub fn new(storage: &'data mut Storage) -> Result<Self, Error> {
|
||||||
|
let origin = storage.origin()?;
|
||||||
|
let elf = ElfFile::new(storage.bytes()?).map_err(|_| Error::InvalidObjectType(0))?;
|
||||||
|
|
||||||
|
is_relocatable(&elf)?;
|
||||||
|
let result = XElfObject { origin, elf };
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data(&self, h: &SectionHeader<'data>) -> Result<std::slice::Iter<'data, u8>, Error> {
|
||||||
|
match h.get_data(&self.elf) {
|
||||||
|
Ok(SectionData::Undefined(ba)) => Ok(ba.iter()),
|
||||||
|
Ok(_) => Err(Error::InvalidSectionData),
|
||||||
|
Err(_) => Err(Error::InvalidSectionData),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Relocatable for XElfObject<'_> {
|
||||||
|
fn origin(&self) -> &Path {
|
||||||
|
&self.origin
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sections(&self) -> BSI<'_> {
|
||||||
|
let iter = self.elf.section_iter().filter_map(move |h| {
|
||||||
|
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(&self.elf).unwrap_or("null");
|
||||||
|
if h.size() > 0 {
|
||||||
|
match self.data(&h) {
|
||||||
|
Ok(data_iter) => {
|
||||||
|
let si = SectionInfo {
|
||||||
|
size: h.size(),
|
||||||
|
data: Some(Box::new(data_iter.copied())),
|
||||||
|
offset: h.offset(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match Section::try_from((s_name, si)) {
|
||||||
|
Ok(s) => Some(Ok(s)),
|
||||||
|
Err(Error::InvalidSectionName) => None, // skip
|
||||||
|
Err(err) => Some(Err(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => Some(Err(err)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// bss
|
||||||
|
ShType::NoBits => Some(Ok(Section::Bss(SectionInfo {
|
||||||
|
size: h.size(),
|
||||||
|
data: None,
|
||||||
|
offset: h.offset(),
|
||||||
|
}))),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
Err(err) => Some(Err(err)),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
Box::new(iter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for XElfObject<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"==={:?}===\n>Symbols:\n{}\n>Sections:\n",
|
||||||
|
self.origin().file_name().unwrap(),
|
||||||
|
"TODO"
|
||||||
|
)?;
|
||||||
|
|
||||||
|
for section in self.sections() {
|
||||||
|
let u = section.unwrap();
|
||||||
|
write!(f, "{}", u)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_relocatable(elf: &ElfFile) -> Result<(), Error> {
|
||||||
|
let raw_type = elf.header.pt2.type_();
|
||||||
|
let elf_type: ElfType = raw_type.as_type();
|
||||||
|
if elf_type != ElfType::Relocatable {
|
||||||
|
return Err(Error::InvalidObjectType(raw_type.0.into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue