Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
abbiecnt committed Sep 14, 2024
1 parent e1f7d11 commit d123874
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 104 deletions.
7 changes: 7 additions & 0 deletions src/find.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use core::ptr::NonNull;

pub trait Find {
fn find(&self, pattern: &[u8]) -> Option<NonNull<u8>>;

fn rfind(&self, pattern: &[u8]) -> Option<NonNull<u8>>;
}
8 changes: 6 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
//! # Inka
mod base;
mod find;
mod program;
mod section;
mod symbol;

pub use base::Base;
pub use find::Find;
pub use program::{program, Program};
pub use section::Section;

pub type Name = &'static str;
pub use symbol::Symbol;

pub type Name = &'static str;
112 changes: 21 additions & 91 deletions src/program.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Base, Section};
use crate::{Base, Find, Section};
use core::ops::Index;
use core::ptr::NonNull;
use core::slice::{from_raw_parts, SliceIndex};
Expand All @@ -8,15 +8,12 @@ use rayon::iter::IndexedParallelIterator;
use rayon::slice::ParallelSlice;
use std::sync::LazyLock;

/// Returns a reference to the global [`Program`] instance.
#[inline]
pub fn program() -> &'static Program {
static PROGRAM: LazyLock<Program> = LazyLock::new(Program::init);
&PROGRAM
}

/// Represents the `Program`'s in-memory layout, providing access to its base address, size,
/// and sections.
#[derive(Debug)]
pub struct Program {
base: Base,
Expand All @@ -25,35 +22,23 @@ pub struct Program {
}

impl Program {
/// Returns a base pointer of this program in memory.
#[inline]
pub fn base(&self) -> Base {
self.base
}

/// Returns the length of this program in memory.
#[inline]
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.len
}

/// Returns a slice containing the entire program.
#[inline]
pub fn as_slice(&self) -> &[u8] {
// SAFETY: todo!()
unsafe { from_raw_parts(self.base.as_nonnull().as_ptr(), self.len) }
}

/// Returns `true` if the program contains the byte pattern.
///
/// # Examples
/// ```
/// use inka::program;
///
/// let result = program().contains(&[0]);
/// assert!(result);
/// ```
pub fn contains(&self, pattern: &[u8]) -> bool {
self.find(pattern).is_some()
}
Expand All @@ -66,81 +51,6 @@ impl Program {
self.sections.iter().find(|section| section.name() == name)
}

/// Returns the pointer of the first byte that matches the byte pattern.
///
/// Returns [`None`] if the pattern doesn’t match.
///
/// # Examples
/// ```
/// use inka::program;
///
/// let data = &[
/// 0x7c, 0x73, 0xe1, 0x3d,
/// 0x1a, 0x7d, 0xb3, 0x00,
/// 0xd2, 0x6c, 0x61, 0xf9,
/// 0x5f, 0x00, 0xf1, 0x10,
/// 0x80, 0x5e, 0x5f, 0xbf,
/// ];
///
/// let pattern = &[
/// 0x7c, 0x73, 0xe1, 0x3d,
/// 0x1a, 0x7d, 0xb3, 0x00,
/// 0xd2,
/// ];
///
/// let ptr = program()
/// .find(pattern)
/// .unwrap();
///
/// assert_eq!(data.as_ptr(), ptr.as_ptr());
/// ```
pub fn find(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
assert!(!pattern.is_empty());

self.as_slice()
.par_windows(pattern.len())
.position_first(|window| window == pattern)
.map(|offset| unsafe { self.base.add(offset) })
}

/// Returns the pointer of the first byte of the last match of the pattern.
///
/// Returns [`None`] if the pattern doesn’t match.
///
/// # Examples
///
/// ```
/// use inka::program;
///
/// let data = &[
/// 0x7c, 0x73, 0xe1, 0x3d,
/// 0x1a, 0x7d, 0xb3, 0x00,
/// 0xd2, 0x6c, 0x61, 0xf9,
/// 0x5f, 0x00, 0xf1, 0x10,
/// 0x80, 0x5e, 0x5f, 0xbf,
/// ];
///
/// let pattern = &[
/// 0x7c, 0x73, 0xe1, 0x3d,
/// 0x1a, 0x7d, 0xb3, 0x00,
/// 0xd2,
/// ];
///
/// let ptr = program()
/// .rfind(pattern)
/// .unwrap();
///
/// assert_eq!(data.as_ptr(), ptr.as_ptr());
/// ```
pub fn rfind(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
assert!(!pattern.is_empty());

self.as_slice()
.par_windows(pattern.len())
.position_last(|window| window == pattern)
.map(|offset| unsafe { self.base.add(offset) })
}

fn init() -> Self {
let base = Base::program();
let pe = unsafe { PeView::module(base.as_nonnull().as_ptr()) };
Expand Down Expand Up @@ -169,6 +79,26 @@ impl Program {
}
}

impl Find for Program {
fn find(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
assert!(!pattern.is_empty());

self.as_slice()
.par_windows(pattern.len())
.position_first(|window| window == pattern)
.map(|offset| unsafe { self.base.add(offset) })
}

fn rfind(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
assert!(!pattern.is_empty());

self.as_slice()
.par_windows(pattern.len())
.position_last(|window| window == pattern)
.map(|offset| unsafe { self.base.add(offset) })
}
}

impl<I: SliceIndex<[u8]>> Index<I> for Program {
type Output = I::Output;

Expand Down
21 changes: 10 additions & 11 deletions src/section.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::{Base, Name};
use crate::{Base, Find, Name};
use core::ops::Index;
use core::ptr::NonNull;
use core::slice::{from_raw_parts, SliceIndex};
use rayon::iter::IndexedParallelIterator;
use rayon::slice::ParallelSlice;

/// Represents a `Section` of the program in memory, providing access to its name, base address, and length.
#[derive(Debug)]
pub struct Section {
name: Name,
Expand All @@ -19,13 +18,11 @@ impl Section {
self.name
}

/// Returns a base pointer of this section.
#[inline]
pub fn base(&self) -> Base {
self.base
}

/// Returns the length of this section.
#[inline]
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
Expand All @@ -43,7 +40,14 @@ impl Section {
self.find(pattern).is_some()
}

pub fn find(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
#[inline]
pub(crate) fn new(name: &'static str, base: Base, len: usize) -> Self {
Self { name, base, len }
}
}

impl Find for Section {
fn find(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
assert!(!pattern.is_empty());

self.as_slice()
Expand All @@ -52,19 +56,14 @@ impl Section {
.map(|offset| unsafe { self.base.add(offset) })
}

pub fn rfind(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
fn rfind(&self, pattern: &[u8]) -> Option<NonNull<u8>> {
assert!(!pattern.is_empty());

self.as_slice()
.par_windows(pattern.len())
.position_last(|window| window == pattern)
.map(|offset| unsafe { self.base.add(offset) })
}

#[inline]
pub(crate) fn new(name: &'static str, base: Base, len: usize) -> Self {
Self { name, base, len }
}
}

impl<I: SliceIndex<[u8]>> Index<I> for Section {
Expand Down
13 changes: 13 additions & 0 deletions src/symbol.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::{Base, Name};

#[derive(Debug)]
pub struct Symbol {
name: Name,
base: Base,
}

impl Symbol {
pub fn demangle(&self) -> String {
todo!()
}
}

0 comments on commit d123874

Please sign in to comment.