Merge remote-tracking branch 'origin/master'
This commit is contained in:
93
sub/xpat/src/hexdump.rs
Normal file
93
sub/xpat/src/hexdump.rs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
use crate::scannable::{ChunkIter, Scannable};
|
||||||
|
use core::ops::{Bound, Range, RangeBounds, RangeFull};
|
||||||
|
use core::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
const SEP: &str = " | ";
|
||||||
|
|
||||||
|
pub struct HexDump<'s, T: Scannable + ?Sized, R: RangeBounds<usize>>(pub &'s T, pub R);
|
||||||
|
|
||||||
|
pub fn hex<
|
||||||
|
's,
|
||||||
|
T: Scannable + ?Sized,
|
||||||
|
R: RangeBounds<usize>
|
||||||
|
>(
|
||||||
|
data: &'s T,
|
||||||
|
range:R
|
||||||
|
) -> HexDump<'s, T, R> {
|
||||||
|
HexDump(data, range)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<'s, T: Scannable> HexDump<'s, T, RangeFull> {
|
||||||
|
pub fn new(scannable: &'s T) -> Self {
|
||||||
|
Self(scannable, ..)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<'s, T: Scannable + ?Sized, R: RangeBounds<usize>> Display for HexDump<'s, T, R> {
|
||||||
|
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
|
||||||
|
// calculate the end and the start addresses
|
||||||
|
let (start, end) = {
|
||||||
|
let r = self.0.range();
|
||||||
|
let start = match self.1.start_bound() {
|
||||||
|
Bound::Included(i) => *i,
|
||||||
|
Bound::Excluded(i) => i.saturating_add(1),
|
||||||
|
Bound::Unbounded => 0,
|
||||||
|
}.max(r.start);
|
||||||
|
let end = match self.1.end_bound() {
|
||||||
|
Bound::Included(i) => *i,
|
||||||
|
Bound::Excluded(i) => i.saturating_sub(1),
|
||||||
|
Bound::Unbounded => usize::MAX,
|
||||||
|
}.min(r.end);
|
||||||
|
(start, end)
|
||||||
|
};
|
||||||
|
|
||||||
|
// if there is nothing to print then just return...
|
||||||
|
// this also prevents the ilog below from crashing :)
|
||||||
|
if end == 0 || start > end {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// the number of digits the address column should have
|
||||||
|
let digits = (end.ilog(16) as usize + 1).max(4);
|
||||||
|
|
||||||
|
for (mut addr, chunk) in ChunkIter::new(self.0, start) {
|
||||||
|
for chunk in chunk.chunks(16) {
|
||||||
|
|
||||||
|
//╶───╴Column╶────────────────────────────────╴
|
||||||
|
write!(f, "{:0digits$X}{SEP}", addr, digits = digits)?;
|
||||||
|
|
||||||
|
//╶───╴Bytes╶─────────────────────────────────╴
|
||||||
|
for (i, byte) in chunk.iter().enumerate() {
|
||||||
|
if i != 0 { write!(f, " ")?; }
|
||||||
|
write!(f, "{byte:02X}")?;
|
||||||
|
}
|
||||||
|
for i in (chunk.len()..16) {
|
||||||
|
match i {
|
||||||
|
0 => write!(f, " ")?,
|
||||||
|
_ => write!(f, " ")?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//╶───╴Text╶──────────────────────────────────╴
|
||||||
|
write!(f, "{SEP}")?;
|
||||||
|
for &byte in chunk {
|
||||||
|
match byte {
|
||||||
|
0x20..0x7e => write!(f, "{}", char::from(byte))?,
|
||||||
|
_ => write!(f, ".")?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeln!(f)?;
|
||||||
|
addr += chunk.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut last_addr = 0usize;
|
||||||
|
let fchunk = self.0.chunk_at(0);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ pub mod atoms {
|
|||||||
|
|
||||||
pub mod scannable;
|
pub mod scannable;
|
||||||
pub mod scanner;
|
pub mod scanner;
|
||||||
|
pub mod hexdump;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Export Preludes:
|
// Export Preludes:
|
||||||
@@ -16,6 +16,7 @@ pub mod prelude {
|
|||||||
pub use sub_macros::pattern;
|
pub use sub_macros::pattern;
|
||||||
pub use crate::atoms::Pattern;
|
pub use crate::atoms::Pattern;
|
||||||
pub use crate::scanner::Scanner;
|
pub use crate::scanner::Scanner;
|
||||||
|
pub use crate::hexdump::hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod public {
|
pub mod public {
|
||||||
@@ -24,5 +25,7 @@ pub mod public {
|
|||||||
pub use crate::scanner::{
|
pub use crate::scanner::{
|
||||||
exec, scan_for_aob, make_aob
|
exec, scan_for_aob, make_aob
|
||||||
};
|
};
|
||||||
|
pub use crate::scannable::ChunkIter;
|
||||||
|
pub use crate::hexdump::HexDump;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ pub trait Scannable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Scannable for [u8] {
|
impl Scannable for [u8] {
|
||||||
fn range(&self) -> Range<usize> { 0..self.len() }
|
fn range(&self) -> Range<usize> { 0..self.len() }
|
||||||
fn chunk_at(&self, address: usize) -> Option<&[u8]> {
|
fn chunk_at(&self, address: usize) -> Option<&[u8]> {
|
||||||
@@ -31,4 +30,35 @@ impl Scannable for (usize, &[u8]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn next_chunk(&self, _address: usize) -> Option<(usize, &[u8])> { None }
|
fn next_chunk(&self, _address: usize) -> Option<(usize, &[u8])> { None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ChunkIter<'l, T: Scannable + ?Sized>(&'l T, usize, bool);
|
||||||
|
|
||||||
|
impl<'l, T: Scannable + ?Sized> ChunkIter<'l, T> {
|
||||||
|
pub const fn new(scannable : &'l T, start: usize) -> Self {
|
||||||
|
Self(scannable, start, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'l, T: Scannable + ?Sized> Iterator for ChunkIter<'l, T> {
|
||||||
|
type Item = (usize, &'l [u8]);
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
|
||||||
|
// if this is the first time being called, use chunk_at instead of next_chunk
|
||||||
|
if self.2 {
|
||||||
|
self.2 = false;
|
||||||
|
if let Some(chunk) = self.0.chunk_at(self.1) {
|
||||||
|
return Some((self.1, chunk))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.0.next_chunk(self.1) {
|
||||||
|
None => None,
|
||||||
|
Some((addr, block)) => {
|
||||||
|
self.1 = addr;
|
||||||
|
Some((addr, block))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -326,7 +326,7 @@ pub fn scan_for_aob<Binary: Scannable + ?Sized>(
|
|||||||
let chunk = match bin.chunk_at(address) {
|
let chunk = match bin.chunk_at(address) {
|
||||||
Some(chunk) => chunk,
|
Some(chunk) => chunk,
|
||||||
|
|
||||||
// the address is out of bounds, try to shift the address so its back in b ounds
|
// the address is out of bounds, try to shift the address so its back in bounds
|
||||||
None => match bin.next_chunk(address) {
|
None => match bin.next_chunk(address) {
|
||||||
|
|
||||||
// the next chunk is in bounds so we will just correct the address and use that chunk instead
|
// the next chunk is in bounds so we will just correct the address and use that chunk instead
|
||||||
|
|||||||
Reference in New Issue
Block a user