mirror of
https://github.com/Noratrieb/rustv32i.git
synced 2026-01-16 14:25:02 +01:00
make generic
This commit is contained in:
parent
d336c4af7d
commit
d7425f460f
3 changed files with 361 additions and 146 deletions
95
src/elf.rs
95
src/elf.rs
|
|
@ -4,11 +4,24 @@ pub struct Elf<'a> {
|
|||
pub content: &'a [u8],
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Addr(pub u64);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Offset(pub u64);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ElfClass {
|
||||
Elf32,
|
||||
Elf64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Header {
|
||||
pub e_entry: u32,
|
||||
pub e_phoff: u32,
|
||||
pub e_shoff: u32,
|
||||
pub class: ElfClass,
|
||||
pub e_entry: Addr,
|
||||
pub e_phoff: Offset,
|
||||
pub e_shoff: Offset,
|
||||
pub e_flags: u32,
|
||||
pub e_ehsize: u16,
|
||||
pub e_phentsize: u16,
|
||||
|
|
@ -19,7 +32,7 @@ pub struct Header {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Phdr {
|
||||
pub struct Phdr32 {
|
||||
pub p_type: u32,
|
||||
pub p_offset: u32,
|
||||
pub p_vaddr: u32,
|
||||
|
|
@ -36,28 +49,74 @@ impl Elf<'_> {
|
|||
if ident[..4] != *b"\x7fELF" {
|
||||
bail!("not an elf file (invalid magic)");
|
||||
}
|
||||
// ELFCLASS32
|
||||
|
||||
let class = match ident[4] {
|
||||
// ELFCLASS32
|
||||
1 => ElfClass::Elf32,
|
||||
// ELFCLASS64
|
||||
2 => ElfClass::Elf64,
|
||||
_ => bail!("not a ELF32 or ELF64 file (EI_CLASS={})", ident[4]),
|
||||
};
|
||||
|
||||
// EV_CURRENT
|
||||
if ident[5] != 1 {
|
||||
bail!("not a ELF32 file (EI_CLASS={})", ident[5]);
|
||||
bail!("not a LE file (EI_DATA={})", ident[5]);
|
||||
}
|
||||
// EV_CURRENT
|
||||
if ident[6] != 1 {
|
||||
bail!("invalid ELF version (EI_VERSION={})", ident[6]);
|
||||
}
|
||||
// ELFOSABI_NONE
|
||||
if ident[7] != 0 {
|
||||
bail!("invalid OS ABI (EI_OSABI={})", ident[7]);
|
||||
}
|
||||
if ident[8] != 0 {
|
||||
bail!("invalid OS ABI version (EI_ABIVERSION={})", ident[8]);
|
||||
}
|
||||
|
||||
let (e_type, rest) = rest.split_u16()?;
|
||||
// ET_EXEC|ET_DYN
|
||||
if e_type != 2 && e_type != 3 {
|
||||
bail!("not an executable: {e_type}");
|
||||
bail!("not an executable: (e_type={e_type})");
|
||||
}
|
||||
|
||||
let (e_machine, rest) = rest.split_u16()?;
|
||||
// EM_RISCV
|
||||
if e_machine != 243 {
|
||||
bail!("not a RISC-V executable");
|
||||
bail!("not a RISC-V executable (e_machine={e_machine})");
|
||||
}
|
||||
|
||||
let (_e_version, rest) = rest.split_u32()?;
|
||||
let (e_version, rest) = rest.split_u32()?;
|
||||
// e_version
|
||||
if e_version != 1 {
|
||||
bail!("invalid OS ABI version (e_version={e_version})");
|
||||
}
|
||||
|
||||
let (e_entry, e_phoff, e_shoff, rest) = match class {
|
||||
ElfClass::Elf32 => {
|
||||
let (e_entry, rest) = rest.split_u32()?;
|
||||
let (e_phoff, rest) = rest.split_u32()?;
|
||||
let (e_shoff, rest) = rest.split_u32()?;
|
||||
(
|
||||
Addr(e_entry as u64),
|
||||
Offset(e_phoff as u64),
|
||||
Offset(e_shoff as u64),
|
||||
rest,
|
||||
)
|
||||
}
|
||||
ElfClass::Elf64 => {
|
||||
let (e_entry, rest) = rest.split_u64()?;
|
||||
let (e_phoff, rest) = rest.split_u64()?;
|
||||
let (e_shoff, rest) = rest.split_u64()?;
|
||||
(
|
||||
Addr(e_entry as u64),
|
||||
Offset(e_phoff as u64),
|
||||
Offset(e_shoff as u64),
|
||||
rest,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let (e_entry, rest) = rest.split_u32()?;
|
||||
let (e_phoff, rest) = rest.split_u32()?;
|
||||
let (e_shoff, rest) = rest.split_u32()?;
|
||||
let (e_flags, rest) = rest.split_u32()?;
|
||||
let (e_ehsize, rest) = rest.split_u16()?;
|
||||
let (e_phentsize, rest) = rest.split_u16()?;
|
||||
|
|
@ -67,6 +126,7 @@ impl Elf<'_> {
|
|||
let (e_shstrndx, _) = rest.split_u16()?;
|
||||
|
||||
Ok(Header {
|
||||
class,
|
||||
e_entry,
|
||||
e_phoff,
|
||||
e_shoff,
|
||||
|
|
@ -80,10 +140,10 @@ impl Elf<'_> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn segments(&self) -> Result<Vec<Phdr>> {
|
||||
pub fn segments_32(&self) -> Result<Vec<Phdr32>> {
|
||||
let header = self.header()?;
|
||||
|
||||
let (_, phdrs) = self.content.split_bytes(header.e_phoff as usize)?;
|
||||
let (_, phdrs) = self.content.split_bytes(header.e_phoff.0 as usize)?;
|
||||
let (mut phdrs, _) = phdrs.split_bytes((header.e_phentsize * header.e_phnum) as usize)?;
|
||||
|
||||
let mut parsed_phdrs = vec![];
|
||||
|
|
@ -101,7 +161,7 @@ impl Elf<'_> {
|
|||
let (p_flags, phdr) = phdr.split_u32()?;
|
||||
let (p_align, _) = phdr.split_u32()?;
|
||||
|
||||
parsed_phdrs.push(Phdr {
|
||||
parsed_phdrs.push(Phdr32 {
|
||||
p_type,
|
||||
p_offset,
|
||||
p_vaddr,
|
||||
|
|
@ -121,6 +181,7 @@ pub trait SplitAtCheckedErr {
|
|||
fn split_bytes(&self, split: usize) -> Result<(&[u8], &[u8])>;
|
||||
fn split_u16(&self) -> Result<(u16, &[u8])>;
|
||||
fn split_u32(&self) -> Result<(u32, &[u8])>;
|
||||
fn split_u64(&self) -> Result<(u64, &[u8])>;
|
||||
}
|
||||
impl SplitAtCheckedErr for [u8] {
|
||||
fn split_bytes(&self, mid: usize) -> Result<(&[u8], &[u8])> {
|
||||
|
|
@ -137,4 +198,8 @@ impl SplitAtCheckedErr for [u8] {
|
|||
let (bytes, rest) = self.split_bytes(4)?;
|
||||
Ok((u32::from_le_bytes(bytes.try_into().unwrap()), rest))
|
||||
}
|
||||
fn split_u64(&self) -> Result<(u64, &[u8])> {
|
||||
let (bytes, rest) = self.split_bytes(8)?;
|
||||
Ok((u64::from_le_bytes(bytes.try_into().unwrap()), rest))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue