#![deny(missing_docs)]
#[macro_use]
extern crate cfg_if;
#[cfg(target_os = "macos")]
#[macro_use]
extern crate lazy_static;
use std::ffi::CStr;
use std::fmt::{self, Debug};
use std::ptr;
cfg_if!(
if #[cfg(target_os = "linux")] {
pub mod linux;
pub type TargetSharedLibrary<'a> = linux::SharedLibrary<'a>;
} else if #[cfg(target_os = "macos")] {
pub mod macos;
pub type TargetSharedLibrary<'a> = macos::SharedLibrary<'a>;
} else {
}
);
macro_rules! simple_newtypes {
(
$(
$(#[$attr:meta])*
type $name:ident = $oldty:ty
where
default = $default:expr ,
display = $format:expr ;
)*
) => {
$(
$(#[$attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $name(pub $oldty);
impl Default for $name {
#[inline]
fn default() -> Self {
$name( $default )
}
}
impl From<$oldty> for $name {
fn from(x: $oldty) -> $name {
$name(x)
}
}
impl From<$name> for $oldty {
fn from($name(x): $name) -> $oldty {
x
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, $format, self.0)
}
}
)*
}
}
simple_newtypes! {
type Svma = *const u8
where
default = ptr::null(),
display = "{:p}";
type Avma = *const u8
where
default = ptr::null(),
display = "{:p}";
type Bias = isize
where
default = 0,
display = "{:#x}";
}
pub trait Segment: Sized + Debug {
type SharedLibrary: SharedLibrary<Segment = Self>;
fn name(&self) -> &CStr;
fn stated_virtual_memory_address(&self) -> Svma;
fn len(&self) -> usize;
#[inline]
fn actual_virtual_memory_address(&self, shlib: &Self::SharedLibrary) -> Avma {
let svma = self.stated_virtual_memory_address();
let bias = shlib.virtual_memory_bias();
Avma(unsafe {
svma.0.offset(bias.0)
})
}
#[inline]
fn contains_svma(&self, address: Svma) -> bool {
let start = self.stated_virtual_memory_address().0 as usize;
let end = start + self.len();
let address = address.0 as usize;
start <= address && address < end
}
#[inline]
fn contains_avma(&self, shlib: &Self::SharedLibrary, address: Avma) -> bool {
let start = self.actual_virtual_memory_address(shlib).0 as usize;
let end = start + self.len();
let address = address.0 as usize;
start <= address && address < end
}
}
pub trait SharedLibrary: Sized + Debug {
type Segment: Segment<SharedLibrary = Self>;
type SegmentIter: Debug + Iterator<Item = Self::Segment>;
fn name(&self) -> &CStr;
fn segments(&self) -> Self::SegmentIter;
fn virtual_memory_bias(&self) -> Bias;
fn each<F, C>(f: F)
where F: FnMut(&Self) -> C,
C: Into<IterationControl>;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum IterationControl {
Break,
Continue,
}
impl From<()> for IterationControl {
#[inline]
fn from(_: ()) -> Self {
IterationControl::Continue
}
}