use super::{ElfReader, IntoElfReader, Path, PathBuf};
use crate::{Result, logging, os::RawFile};
use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
#[derive(Debug)]
pub struct ElfBinary<'bytes> {
path: PathBuf,
bytes: Cow<'bytes, [u8]>,
}
impl<'bytes> ElfBinary<'bytes> {
pub fn new(path: impl Into<PathBuf>, bytes: &'bytes [u8]) -> Self {
Self {
path: path.into(),
bytes: Cow::Borrowed(bytes),
}
}
pub fn owned(path: impl Into<PathBuf>, bytes: impl Into<Vec<u8>>) -> Self {
Self {
path: path.into(),
bytes: Cow::Owned(bytes.into()),
}
}
}
impl<'bytes> ElfReader for ElfBinary<'bytes> {
fn path(&self) -> &Path {
&self.path
}
fn read(&mut self, buf: &mut [u8], offset: usize) -> crate::Result<()> {
let bytes = self.bytes.as_ref();
if offset + buf.len() > bytes.len() {
return Err(
crate::IoError::ReadOutOfBounds(Box::new(crate::ReadBoundsError::new(
offset,
buf.len(),
bytes.len(),
)))
.into(),
);
}
buf.copy_from_slice(&bytes[offset..offset + buf.len()]);
Ok(())
}
fn as_fd(&self) -> Option<isize> {
None
}
}
pub struct ElfFile {
inner: RawFile,
}
impl ElfFile {
pub unsafe fn from_owned_fd(path: impl AsRef<Path>, raw_fd: i32) -> Self {
let path = path.as_ref();
ElfFile {
inner: RawFile::from_owned_fd(path, raw_fd),
}
}
pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref();
logging::debug!("Opening ELF file: {}", path);
let inner = RawFile::from_path(path)?;
Ok(ElfFile { inner })
}
}
impl ElfReader for ElfFile {
fn path(&self) -> &Path {
self.inner.path()
}
fn read(&mut self, buf: &mut [u8], offset: usize) -> Result<()> {
self.inner.read(buf, offset)
}
fn as_fd(&self) -> Option<isize> {
self.inner.as_fd()
}
}
impl<'a> ElfReader for &'a [u8] {
fn path(&self) -> &Path {
Path::new("<memory>")
}
fn read(&mut self, buf: &mut [u8], offset: usize) -> Result<()> {
if offset + buf.len() > self.len() {
return Err(
crate::IoError::ReadOutOfBounds(Box::new(crate::ReadBoundsError::new(
offset,
buf.len(),
self.len(),
)))
.into(),
);
}
buf.copy_from_slice(&self[offset..offset + buf.len()]);
Ok(())
}
fn as_fd(&self) -> Option<isize> {
None
}
}
impl<'a> IntoElfReader<'a> for &'a str {
type Reader = ElfFile;
fn into_reader(self) -> Result<Self::Reader> {
ElfFile::from_path(self)
}
}
impl<'a> IntoElfReader<'a> for String {
type Reader = ElfFile;
fn into_reader(self) -> Result<Self::Reader> {
ElfFile::from_path(self)
}
}
impl<'a> IntoElfReader<'a> for &'a Path {
type Reader = ElfFile;
fn into_reader(self) -> Result<Self::Reader> {
ElfFile::from_path(self)
}
}
impl<'a> IntoElfReader<'a> for PathBuf {
type Reader = ElfFile;
fn into_reader(self) -> Result<Self::Reader> {
ElfFile::from_path(self)
}
}
impl<'a> IntoElfReader<'a> for &'a PathBuf {
type Reader = ElfFile;
fn into_reader(self) -> Result<Self::Reader> {
ElfFile::from_path(self)
}
}
impl<'a> IntoElfReader<'a> for &'a [u8] {
type Reader = ElfBinary<'a>;
fn into_reader(self) -> Result<Self::Reader> {
Ok(ElfBinary::new("<memory>", self))
}
}
impl<'a> IntoElfReader<'a> for &'a Vec<u8> {
type Reader = ElfBinary<'a>;
fn into_reader(self) -> Result<Self::Reader> {
Ok(ElfBinary::new("<memory>", self.as_slice()))
}
}
impl<'a> IntoElfReader<'a> for Vec<u8> {
type Reader = ElfBinary<'static>;
fn into_reader(self) -> Result<Self::Reader> {
Ok(ElfBinary::owned("<memory>", self))
}
}
impl<'a> IntoElfReader<'a> for Box<[u8]> {
type Reader = ElfBinary<'static>;
fn into_reader(self) -> Result<Self::Reader> {
Ok(ElfBinary::owned("<memory>", self.into_vec()))
}
}
impl<'a> IntoElfReader<'a> for ElfFile {
type Reader = ElfFile;
fn into_reader(self) -> Result<Self::Reader> {
Ok(self)
}
}
impl<'a, 'b> IntoElfReader<'a> for ElfBinary<'b>
where
'b: 'a,
{
type Reader = ElfBinary<'b>;
fn into_reader(self) -> Result<Self::Reader> {
Ok(self)
}
}