use lief_ffi as ffi;
use super::coff;
use super::elf;
use super::macho;
use super::pe;
use crate::common::FromFFI;
use std::io::{Read, Seek};
use std::path::Path;
#[derive(Debug)]
pub enum Binary {
ELF(elf::Binary),
PE(pe::Binary),
MachO(macho::FatBinary),
COFF(coff::Binary),
}
impl Binary {
pub fn parse<P: AsRef<Path>>(path: P) -> Option<Binary> {
let path_str = path.as_ref().to_str().unwrap();
cxx::let_cxx_string!(__cxx_s = path_str);
if ffi::ELF_Utils::is_elf(&__cxx_s) {
if let Some(elf) = elf::Binary::parse(path) {
return Some(Binary::ELF(elf));
}
return None;
}
cxx::let_cxx_string!(__cxx_s = path_str);
if ffi::PE_Utils::is_pe(&__cxx_s) {
if let Some(pe) = pe::Binary::parse(path) {
return Some(Binary::PE(pe));
}
return None;
}
cxx::let_cxx_string!(__cxx_s = path_str);
if ffi::MachO_Utils::is_macho(&__cxx_s) {
if let Some(fat) = macho::FatBinary::parse(path) {
return Some(Binary::MachO(fat));
}
return None;
}
cxx::let_cxx_string!(__cxx_s = path_str);
if ffi::COFF_Utils::is_coff(&__cxx_s) {
if let Some(coff) = coff::Binary::parse(path) {
return Some(Binary::COFF(coff));
}
return None;
}
None
}
pub fn from<R: Read + Seek>(reader: &mut R) -> Option<Binary> {
let mut buffer = std::vec::Vec::new();
if reader.read_to_end(&mut buffer).is_err() {
return None;
}
let mut ffi_stream =
unsafe { ffi::RustStream::from_rust(buffer.as_mut_ptr(), buffer.len()) };
buffer.clear();
if ffi_stream.is_elf() {
return Some(Binary::ELF(elf::Binary::from_ffi(
ffi_stream.pin_mut().as_elf(),
)));
}
if ffi_stream.is_macho() {
return Some(Binary::MachO(macho::FatBinary::from_ffi(
ffi_stream.pin_mut().as_macho(),
)));
}
if ffi_stream.is_pe() {
return Some(Binary::PE(pe::Binary::from_ffi(
ffi_stream.pin_mut().as_pe(),
)));
}
if ffi_stream.is_coff() {
return Some(Binary::COFF(coff::Binary::from_ffi(
ffi_stream.pin_mut().as_coff(),
)));
}
None
}
}