use super::{Header, Relocation, Section, String, Symbol};
use crate::assembly::Instructions;
use crate::common::FromFFI;
use crate::common::into_optional;
use crate::{declare_iterator, declare_lazy_iterator};
use lief_ffi as ffi;
use std::path::Path;
pub struct Binary {
ptr: cxx::UniquePtr<ffi::COFF_Binary>,
}
impl FromFFI<ffi::COFF_Binary> for Binary {
fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Binary>) -> Self {
Self { ptr }
}
}
impl Binary {
pub fn parse<P: AsRef<Path>>(path: P) -> Option<Self> {
cxx::let_cxx_string!(__cxx_s = path.as_ref().to_str().unwrap());
let ffi = ffi::COFF_Binary::parse(&__cxx_s);
if ffi.is_null() {
return None;
}
Some(Binary::from_ffi(ffi))
}
pub fn header(&self) -> Header<'_> {
Header::from_ffi(self.ptr.header())
}
pub fn sections(&self) -> Sections<'_> {
Sections::new(self.ptr.sections())
}
pub fn relocations(&self) -> Relocations<'_> {
Relocations::new(self.ptr.relocations())
}
pub fn symbols(&self) -> Symbols<'_> {
Symbols::new(self.ptr.symbols())
}
pub fn functions(&self) -> Functions<'_> {
Functions::new(self.ptr.functions())
}
pub fn string_table(&self) -> Strings<'_> {
Strings::new(self.ptr.string_table())
}
pub fn find_string(&self, offset: u32) -> Option<String<'_>> {
into_optional(self.ptr.find_string(offset))
}
pub fn find_function(&self, name: &str) -> Option<Symbol<'_>> {
cxx::let_cxx_string!(__cxx_s = name);
into_optional(self.ptr.find_function(&__cxx_s))
}
pub fn find_demangled_function(&self, name: &str) -> Option<Symbol<'_>> {
cxx::let_cxx_string!(__cxx_s = name);
into_optional(self.ptr.find_demangled_function(&__cxx_s))
}
pub fn disassemble_slice(&self, slice: &[u8], address: u64) -> InstructionsIt<'_> {
unsafe {
InstructionsIt::new(self.ptr.disassemble_buffer(
slice.as_ptr(),
slice.len().try_into().unwrap(),
address,
))
}
}
pub fn disassemble_function(&self, name: &str) -> InstructionsIt<'_> {
cxx::let_cxx_string!(__cxx_s = name.to_string());
InstructionsIt::new(self.ptr.disassemble_function(&__cxx_s))
}
pub fn disassemble_symbol(&self, symbol: &Symbol) -> InstructionsIt<'_> {
InstructionsIt::new(self.ptr.disassemble_symbol(symbol.ptr.as_ref().unwrap()))
}
}
impl std::fmt::Display for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.ptr.to_string())
}
}
impl std::fmt::Debug for Binary {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("COFF Binary").finish()
}
}
declare_iterator!(
Relocations,
Relocation<'a>,
ffi::COFF_Relocation,
ffi::COFF_Binary,
ffi::COFF_Binary_it_relocations
);
declare_iterator!(
Sections,
Section<'a>,
ffi::COFF_Section,
ffi::COFF_Binary,
ffi::COFF_Binary_it_sections
);
declare_iterator!(
Symbols,
Symbol<'a>,
ffi::COFF_Symbol,
ffi::COFF_Binary,
ffi::COFF_Binary_it_symbols
);
declare_iterator!(
Strings,
String<'a>,
ffi::COFF_String,
ffi::COFF_Binary,
ffi::COFF_Binary_it_strings
);
declare_iterator!(
Functions,
Symbol<'a>,
ffi::COFF_Symbol,
ffi::COFF_Binary,
ffi::COFF_Binary_it_functions
);
declare_lazy_iterator!(
InstructionsIt,
Instructions,
ffi::asm_Instruction,
ffi::COFF_Binary,
ffi::COFF_Binary_it_instructions
);