Files
RedBear-OS/src/elf.rs
T
Andrey Turkin d2ebc7ff05 Wholesale fix of warnings
Pretty straightforward changes. This commit tries to avoid making any non-trivial fixes.
2024-09-04 10:55:01 +03:00

153 lines
4.0 KiB
Rust

#![allow(unused)]
//! ELF executables
use alloc::string::String;
use goblin::elf::section_header::SHT_SYMTAB;
#[cfg(target_arch = "x86")]
pub use goblin::elf32::{header, program_header, section_header, sym};
#[cfg(any(
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "x86_64"
))]
pub use goblin::elf64::{header, program_header, section_header, sym};
/// An ELF executable
pub struct Elf<'a> {
pub data: &'a [u8],
header: &'a header::Header,
}
impl<'a> Elf<'a> {
/// Create a ELF executable from data
pub fn from(data: &'a [u8]) -> Result<Elf<'a>, String> {
if data.len() < header::SIZEOF_EHDR {
Err(format!(
"Elf: Not enough data: {} < {}",
data.len(),
header::SIZEOF_EHDR
))
} else if &data[..header::SELFMAG] != header::ELFMAG {
Err(format!(
"Elf: Invalid magic: {:?} != {:?}",
&data[..header::SELFMAG],
header::ELFMAG
))
} else if data.get(header::EI_CLASS) != Some(&header::ELFCLASS) {
Err(format!(
"Elf: Invalid architecture: {:?} != {:?}",
data.get(header::EI_CLASS),
header::ELFCLASS
))
} else {
Ok(Elf {
data,
header: unsafe { &*(data.as_ptr() as usize as *const header::Header) },
})
}
}
pub fn sections(&'a self) -> ElfSections<'a> {
ElfSections {
data: self.data,
header: self.header,
i: 0,
}
}
pub fn symbols(&'a self) -> Option<ElfSymbols<'a>> {
let mut symtab_opt = None;
for section in self.sections() {
if section.sh_type == SHT_SYMTAB {
symtab_opt = Some(section);
break;
}
}
if let Some(symtab) = symtab_opt {
Some(ElfSymbols {
data: self.data,
symtab,
i: 0,
})
} else {
None
}
}
}
pub struct ElfSections<'a> {
data: &'a [u8],
header: &'a header::Header,
i: usize,
}
impl<'a> Iterator for ElfSections<'a> {
type Item = &'a section_header::SectionHeader;
fn next(&mut self) -> Option<Self::Item> {
if self.i < self.header.e_shnum as usize {
let item = unsafe {
&*((self.data.as_ptr() as usize
+ self.header.e_shoff as usize
+ self.i * self.header.e_shentsize as usize)
as *const section_header::SectionHeader)
};
self.i += 1;
Some(item)
} else {
None
}
}
}
pub struct ElfSegments<'a> {
data: &'a [u8],
header: &'a header::Header,
i: usize,
}
impl<'a> Iterator for ElfSegments<'a> {
type Item = &'a program_header::ProgramHeader;
fn next(&mut self) -> Option<Self::Item> {
if self.i < self.header.e_phnum as usize {
let item = unsafe {
&*((self.data.as_ptr() as usize
+ self.header.e_phoff as usize
+ self.i * self.header.e_phentsize as usize)
as *const program_header::ProgramHeader)
};
self.i += 1;
Some(item)
} else {
None
}
}
}
pub struct ElfSymbols<'a> {
data: &'a [u8],
symtab: &'a section_header::SectionHeader,
i: usize,
}
impl<'a> Iterator for ElfSymbols<'a> {
type Item = &'a sym::Sym;
fn next(&mut self) -> Option<Self::Item> {
if self.i < (self.symtab.sh_size as usize) / sym::SIZEOF_SYM {
let item = unsafe {
&*((self.data.as_ptr() as usize
+ self.symtab.sh_offset as usize
+ self.i * sym::SIZEOF_SYM) as *const sym::Sym)
};
self.i += 1;
Some(item)
} else {
None
}
}
}