#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::useless_conversion)]
#![deny(missing_docs)]
use memmap::MmapOptions;
use scroll::{ctx::SizeWith, Pread, Pwrite};
use indexmap::map::IndexMap;
use std::fs::File;
use std::path::Path;
#[macro_use]
extern crate bitflags;
mod error;
pub use error::Error;
mod arch_info;
mod pod;
pub use pod::*;
mod serialize;
pub use serialize::*;
mod instr_builder;
pub use instr_builder::*;
pub mod dump;
#[doc(hidden)]
pub type Result<T> = std::result::Result<T, error::Error>;
impl Routine {
pub fn new(arch_id: ArchitectureIdentifier) -> Routine {
let (routine_convention, subroutine_convention) = match arch_id {
ArchitectureIdentifier::Virtual => {
let routine_convention = RoutineConvention {
volatile_registers: vec![],
param_registers: vec![],
retval_registers: vec![],
frame_register: RegisterDesc {
flags: RegisterFlags::VIRTUAL,
combined_id: 0,
bit_count: 0,
bit_offset: 0,
},
shadow_space: 0,
purge_stack: true,
};
(routine_convention.clone(), routine_convention)
}
_ => unimplemented!(),
};
Routine {
header: Header { arch_id },
vip: Vip(0),
routine_convention,
subroutine_convention,
spec_subroutine_conventions: vec![],
explored_blocks: IndexMap::new(),
}
}
pub fn create_block(&mut self, vip: Vip) -> Option<&mut BasicBlock> {
if !self.explored_blocks.contains_key(&vip) {
let basic_block = BasicBlock {
vip,
sp_offset: 0,
sp_index: 0,
last_temporary_index: 0,
instructions: vec![],
prev_vip: vec![],
next_vip: vec![],
};
self.explored_blocks.insert(vip, basic_block);
Some(self.explored_blocks.get_mut(&vip).unwrap())
} else {
None
}
}
pub fn remove_block(&mut self, vip: Vip) -> Option<BasicBlock> {
self.explored_blocks.remove(&vip)
}
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Routine> {
let source = Box::new(unsafe { MmapOptions::new().map(&File::open(path.as_ref())?)? });
source.pread_with::<Routine>(0, scroll::LE)
}
pub fn from_vec(source: &[u8]) -> Result<Routine> {
source.as_ref().pread_with::<Routine>(0, scroll::LE)
}
pub fn into_bytes(self) -> Result<Vec<u8>> {
let size = Routine::size_with(&self);
let mut buffer = vec![0; size];
buffer.pwrite_with::<Routine>(self, 0, scroll::LE)?;
Ok(buffer)
}
}