1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Goblin-powered multi-format pattern scanning with pelite-style signatures.
//!
//! `goblin-sigscan` combines:
//!
//! - pelite-inspired pattern syntax and semantics,
//! - scanner APIs over PE/ELF/Mach binaries,
//! - compile-time (`pattern!`) and runtime (`pattern::parse`) pattern parsing.
//!
//! This crate's design and pattern language are heavily inspired by pelite.
//! See the original project by casualx:
//! <https://github.com/CasualX/pelite> and
//! <https://docs.rs/pelite/latest/pelite/pattern/>.
//!
//! # Docs map
//!
//! - Syntax overview and parser API: [`mod@crate::pattern`]
//! - Parser internals/reference crate: [`goblin_sigscan_pattern`]
//! - Scanner entry points: [`Scanner`], [`Matches`], [`PreparedPattern`]
//! - Binary wrappers: [`pe64`], [`elf`], [`mach`]
//!
//! # Pattern Scanner Tutorial
//!
//! ## 1) Parse a pattern
//!
//! Runtime parse:
//!
//! ```
//! use goblin_sigscan::pattern;
//!
//! let atoms = pattern::parse("48 8B ? ? ? ? 48 89")?;
//! assert!(atoms.len() >= 3);
//! # Ok::<(), pattern::ParsePatError>(())
//! ```
//!
//! Compile-time parse via macro:
//!
//! ```no_run
//! let atoms = goblin_sigscan::pattern!("48 8B ? ? ? ? 48 89");
//! assert!(!atoms.is_empty());
//! ```
//!
//! ## 2) Size your save buffer correctly
//!
//! Save-slot length and semantics are the easiest API to misuse.
//!
//! - Use [`pattern::save_len`] for parsed atom slices.
//! - For prepared patterns, use [`PreparedPattern::required_slots`].
//! - Parsed patterns always include an implicit `Save(0)`, so slot `0` is
//! always the match start cursor (RVA/VA/mapped offset based on wrapper).
//! - Extra tail elements in larger `save` buffers are left untouched.
//!
//! ```
//! use goblin_sigscan::pattern;
//!
//! let atoms = pattern::parse("e8 ${'}")?;
//! let mut save = vec![0u64; pattern::save_len(&atoms)];
//! assert!(save.len() >= 2);
//! # Ok::<(), pattern::ParsePatError>(())
//! ```
//!
//! ## 3) Scan binary code ranges
//!
//! ```no_run
//! use std::error::Error;
//!
//! use goblin_sigscan::{pattern, pe64::PeFile};
//!
//! fn main() -> Result<(), Box<dyn Error>> {
//! // Provide real module bytes from your target binary in production code.
//! let bytes: &[u8] = &[];
//! let file = PeFile::from_bytes(bytes)?;
//! let atoms = pattern::parse("48 8B ? ? ? ? 48 89")?;
//! let mut save = vec![0u64; pattern::save_len(&atoms)];
//! let mut matches = file.scanner().matches_code(&atoms);
//! if matches.next(&mut save) {
//! let match_start = save[0];
//! let _ = match_start;
//! }
//! Ok(())
//! }
//! ```
//!
//! ## 4) Reuse prepared patterns for repeated scans
//!
//! ```no_run
//! use std::error::Error;
//!
//! use goblin_sigscan::{pattern, pe64::PeFile};
//!
//! fn main() -> Result<(), Box<dyn Error>> {
//! // Provide real module bytes from your target binary in production code.
//! let bytes: &[u8] = &[];
//! let file = PeFile::from_bytes(bytes)?;
//! let atoms = pattern::parse("e8 ${'}")?;
//! let prepared = file.scanner().prepare_pattern(&atoms);
//! let mut save = vec![0u64; prepared.required_slots()];
//! let _is_unique = file.scanner().finds_prepared(&prepared, &mut save);
//! Ok(())
//! }
//! ```
//!
//! ## 5) Syntax tutorial
//!
//! For full syntax semantics and examples, use the canonical parser tutorial:
//! [`goblin_sigscan_pattern::parse`].
//!
//! The `goblin_sigscan::pattern` module is a re-export convenience surface:
//! [`mod@crate::pattern`].
//!
//! ## Common pitfalls
//!
//! - Allocating `save` too short for the parsed pattern.
//! - Assuming slot `0` is optional (it is always present for parsed patterns).
//! - Forgetting that `[a-b]` uses an exclusive upper parse convention (`b - 1`
//! is the maximum encoded skip).
//! - Comparing benchmark runs with mismatched sample settings.
//!
//! For benchmark methodology guidance, see `scripts/README.md` in the repo.
extern crate self as goblin_sigscan;
pub use pattern;
pub use ;
pub use ;
pub use ;