Skip to main content

Engine

Struct Engine 

Source
pub struct Engine { /* private fields */ }
Expand description

Engine over one APK.

Implementations§

Source§

impl Engine

Source

pub fn call_graph(&self, q: &CallQuery) -> Result<CallTree>

Callers or callees of a method, depth levels deep, as a tree.

The roots are every overload of method declared by class (or the exact signature) that some DEX references; an unknown method is an error. Each method is expanded once, at its shallowest occurrence; other occurrences are marked repeated.

Source

pub fn call_graph_cancellable( &self, q: &CallQuery, cancel: &AtomicBool, ) -> Result<CallTree>

Engine::call_graph that stops, with ApkError::Cancelled, once cancel is raised.

Source§

impl Engine

Source

pub fn scan_classes( &self, prefix: Option<&str>, progress: impl Fn(usize, usize) + Sync, ) -> Result<Vec<EntryClasses>>

Enumerate the classes of every root DEX entry whose descriptor starts with prefix (a Dalvik descriptor prefix, used as is).

Entries are read in parallel, largest first; the result follows the central-directory order, and each entry’s logical DEXes and classes keep their file order. progress(done, total) runs after each entry. Problems are reported per entry / DEX, never as a failure of the call; only an unreadable APK fails it.

Source

pub fn list_classes(&self, prefix: Option<&str>) -> Result<Vec<ClassListing>>

Every class of the APK, optionally restricted to a package / class prefix (com.poc, com/poc or Lcom/poc), in DEX order. Strict: the first unreadable entry, unparsable DEX or bad class_def fails the call.

Source§

impl Engine

Source

pub fn matching_methods( &self, queries: &[Query], cancel: &AtomicBool, ) -> Result<MatchingMethods>

The signatures (Lcls;->name(params)ret) of the methods whose code matches each query, all queries in one pass.

Source§

impl Engine

Source

pub fn hierarchy(&self, q: &HierarchyQuery) -> Result<HierarchyTree>

Transitive subclasses / implementers (or supertypes) of a class, as a tree, with the classes defining method marked.

Source

pub fn hierarchy_cancellable( &self, q: &HierarchyQuery, cancel: &AtomicBool, ) -> Result<HierarchyTree>

Engine::hierarchy that stops, with ApkError::Cancelled, once cancel is raised.

Source§

impl Engine

Source

pub fn no_results_hints(&self, query: &Query, entries: usize) -> Vec<String>

One line each on why a search over entries DEX entries found nothing and what to change: case-sensitive patterns, a class no DEX references, members that do exist, direct relations only.

Source§

impl Engine

Source

pub fn manifest_summary(&self) -> Result<ManifestSummary>

Parse AndroidManifest.xml (and the XML resources it points at) into a ManifestSummary.

Source§

impl Engine

Source

pub fn prebuild(&self) -> Result<PrebuildReport>

Build (or map from L2) the locator tables of every DEX entry the caches hold, so the first query of each kind skips its table builds. Blocks until done; meant for a background thread after a warm open. Does nothing without a memory cache (the tables would be dropped).

Source

pub fn cancel_prebuild(&self)

Stop a running Engine::prebuild (and any later one) and wait for its workers to finish the table they are on.

Source§

impl Engine

Source

pub fn resources(&self) -> Result<Option<Arc<ResTable>>>

The APK’s resource table, parsed once per APK version and kept for later calls. None when the APK has no resources.arsc.

Source

pub fn release_resources(&self)

Forget the parsed resource table (and its name index); the next resource query parses it again (about a millisecond even for Douyin).

Source

pub fn xml(&self, path: &str) -> Result<String>

Decode a binary XML file of the APK (res/xml/..., a layout, the manifest), naming references and app attributes from the resource table.

Source

pub fn manifest_xml_resolved(&self) -> Result<String>

Engine::manifest_xml with @7F... references shown by name.

Source

pub fn dump_resources(&self, f: impl FnMut(ResourceRow)) -> Result<()>

Call f with every value of every resource, in id order (one row per resource and configuration).

Source

pub fn resource(&self, query: &str) -> Result<Vec<ResourceRow>>

Every configuration’s value of the resource query: an id (0x7f0d0001) or a name (string/app_name, @pkg:type/name).

Source

pub fn resolve_resource( &self, query: &str, config: Option<&Config>, ) -> Result<(Vec<String>, ResourceRow)>

Resolve the reference chain of query for a device described by config (default: Config::any_device). Returns the rendered chain (@string/a -> @string/b) and the final value.

Source

pub fn search_resources( &self, pattern: &str, literal: bool, field: ResourceField, limit: usize, ) -> Result<(Vec<ResourceRow>, usize)>

Resources whose name and/or string value matches the regex pattern (a plain substring when literal), one row per matching configuration value (names: one row per configuration). At most limit rows; the second value is the total number of matches.

Source§

impl Engine

Source

pub fn annotate_resource_ids(&self, smali: &str) -> String

Name the resource ids of smali: a const (or .array-data element) whose literal is a resource of this APK gets # @type/name appended, e.g. const v0, 0x7f0b001c # @layout/activity_main. Unchanged when the APK has no (readable) resource table: names are a convenience, never a reason for the class itself to fail.

Source§

impl Engine

Source

pub fn find_refs_rules( &self, rules: &[Query], opts: FindOptions, cancel: &AtomicBool, sink: &mut dyn FnMut(usize, RefBatch), ) -> Result<RefSummary>

Several queries in one pass: each DEX is loaded once and scanned once per index kind for all of them. sink gets (rule index, batch), one batch per rule and entry, entries in completion order.

Each rule shares L3 with Engine::find_refs_opts: rules an earlier run left there are replayed, only the others are searched, and each of those is kept under its own key.

Source

pub fn search_target_entry_rules( &self, target: &SearchTarget, entry: &Entry, rules: &[&CompiledQuery], aggregate: bool, cancel: &AtomicBool, ) -> Vec<RefBatch>

Engine::search_target_entry for a rule set: one batch per rule.

Source§

impl Engine

Source

pub fn cached_refs( &self, target: &SearchTarget, query: &Query, aggregate: bool, ) -> Option<Vec<RefBatch>>

The rows an earlier search of query on this APK left in L3: what Engine::find_refs_with replays, so the one-APK and the sweep paths share results.

Source

pub fn store_refs(&self, query: &Query, aggregate: bool, batches: &[RefBatch])

Keep the batches of a complete search of query on this APK in L3 (not when one failed, see Engine::cached_refs).

Source

pub fn search_target_entry_dedup( &self, target: &SearchTarget, entry: &Entry, query: &CompiledQuery, aggregate: bool, cancel: &AtomicBool, claim: &Claim, ) -> RefBatch

Engine::search_target_entry for an entry claimed in a DexDedup: a leading entry is searched and its rows offered to the entries that follow it; a following one reuses them when its bytes hash the same.

Source

pub fn search_target_entry_rules_dedup( &self, target: &SearchTarget, entry: &Entry, rules: &[&CompiledQuery], aggregate: bool, cancel: &AtomicBool, claim: &Claim, ) -> Vec<RefBatch>

Engine::search_target_entry_rules for an entry claimed with DexDedup::claim_rules for these rules.

Source§

impl Engine

Source

pub fn new(apk_path: impl AsRef<Path>) -> Engine

An engine over apk_path: an APK, a jar, a bare DEX file, or a program of several read as one (a directory, or paths joined with ,; see Apk::open).

Source

pub fn with_limits(self, limits: Limits) -> Engine

Refuse entries that inflate past limits (zip bombs).

Source

pub fn with_threads(self, threads: impl Into<Threads>) -> Engine

Source

pub fn with_debug(self, debug: bool) -> Engine

Source

pub fn with_logger( self, logger: impl Fn(&str) + Send + Sync + 'static, ) -> Engine

Route debug output somewhere other than stdout.

Source

pub fn with_cache(self, config: CacheConfig) -> Engine

Enable caching of inflated entries. A disk cache whose directory holds foreign files is dropped with a warning through the logger (set it first), instead of every write failing silently in the background.

Source

pub fn with_shared_cache(self, cache: &SharedCache) -> Engine

Use cache (shared with other engines) instead of a private one.

Source

pub fn apk_path(&self) -> &Path

Source

pub fn threads(&self) -> usize

The thread count for a search starting now.

Source

pub fn cache_stats(&self) -> CacheStats

Source

pub fn resident_bytes(&self) -> usize

Heap this engine holds outside the memory cache, roughly: the class graph and the parsed resource table it keeps for later calls. A host keeping many engines counts it against its memory budget (SharedCache::set_reserved).

Source

pub fn memory_cache_bytes(&self) -> usize

Bytes currently charged to the in-memory cache: entry bytes plus the locator tables built for them.

Source

pub fn release_memory_cache(&self) -> usize

Drop this APK’s entries from the in-memory cache (shared or not), and its parsed resource table, and return the DEX bytes released; queries still holding them keep them alive.

Source

pub fn memory_cache_mapped_bytes(&self) -> usize

Entry bytes of the in-memory cache that are mapped from the disk cache (file-backed pages the OS can reclaim) rather than held on the heap.

Source

pub fn memory_cache_mapped_table_bytes(&self) -> usize

Bytes of the in-memory cache’s locator tables that are viewed in L2 files (file-backed pages shared with other processes) rather than held on the heap.

Source

pub fn flush_cache_writes(&self)

Block until every queued disk-cache write has been renamed into place.

Source

pub fn close_cache_writes(&self)

Engine::flush_cache_writes for process exit: also stops queueing, so a worker still holding the engine cannot start a writer thread that exiting would kill mid-write. Run on drop.

Source

pub fn open(&self) -> Result<Apk>

Open the APK, or reuse the one opened last while Apk::version_of finds the same files, sizes and times.

Source

pub fn resolve_path(apk_path: &Path, base: &Path) -> PathBuf

apk_path (what Engine::new takes) with relative paths resolved against base, each path of a program on its own.

Source

pub fn can_open(apk_path: &Path) -> bool

Whether apk_path opens: a readable file, or a program with code.

Source

pub fn program_notes(&self) -> Vec<String>

One line per archive of a program left out of its code (no root DEX, e.g. a jar deodexed into oat/, or not a zip); none for one file.

Source

pub fn search_target(&self) -> Result<SearchTarget>

Open the APK for Engine::search_target.

Source

pub fn search_target_entry( &self, target: &SearchTarget, entry: &Entry, query: &CompiledQuery, aggregate: bool, cancel: &AtomicBool, ) -> RefBatch

Search one entry of target (what Engine::find_refs_with runs per entry), through this engine’s caches.

Source

pub fn dex_entries(&self) -> Result<Vec<Entry>>

Root-level DEX entries, smallest compressed first.

Source

pub fn apk_key(&self, apk: &Apk) -> Option<ApkKey>

Cache key for apk when caching is enabled. Hashing the central directory is done once per APK version; later calls only stat.

Source

pub fn entry_bytes( &self, apk: &Apk, key: Option<&ApkKey>, entry: &Entry, ) -> Result<DexBytes>

Inflated bytes of entry, through the caches when enabled. Stored entries are copied only when an in-memory cache wants to keep them.

Source

pub fn get_class_dex(&self, descriptor: &str) -> Result<Option<ClassHit>>

Find the DEX that defines descriptor (Lcom/poc/Main;).

DEX entries are inflated in parallel, smallest first. Entries that are not cached are first streamed only as far as their id tables and string data to answer the probe cheaply; only a hit is inflated fully.

A class several DEX files define resolves as a class loader would: the first archive of a program, then classes.dex, classes2.dex, … ([load_ranks]). Once a DEX defines it, DEX files after it are no longer read; workers still inflating one at that moment finish on their own in the background. A program reads every archive, to name the others that define the class too (ClassHit::also_defined_in).

Source

pub fn get_class_dex_cancellable( &self, descriptor: &str, cancel: &AtomicBool, ) -> Result<Option<ClassHit>>

Engine::get_class_dex that stops, with ApkError::Cancelled, once cancel is raised.

Source

pub fn get_class(&self, descriptor: &str) -> Result<ClassSource>

Locate, rebuild and disassemble a class.

Source

pub fn get_class_with( &self, descriptor: &str, opts: SmaliOptions, ) -> Result<ClassSource>

Source

pub fn get_class_method( &self, descriptor: &str, opts: SmaliOptions, method: Option<&str>, ) -> Result<ClassSource>

Engine::get_class_with that renders only the method whose name(params)ret is method (no fields) when one is given. A malformed signature is rejected before the APK is read; a class without such a method is an error. The rebuilt DEX still holds the whole class.

Source

pub fn get_class_method_cancellable( &self, descriptor: &str, opts: SmaliOptions, method: Option<&str>, cancel: &AtomicBool, ) -> Result<ClassSource>

Engine::get_class_method that stops looking for the class, with ApkError::Cancelled, once cancel is raised.

Source

pub fn find_refs( &self, query: &Query, sink: impl FnMut(RefBatch), ) -> Result<RefSummary>

Search every DEX entry for references. sink receives one batch per entry in completion order. Returns a summary once all entries finish.

Source

pub fn find_refs_with( &self, query: &Query, aggregate: bool, cancel: &AtomicBool, sink: &mut dyn FnMut(RefBatch), ) -> Result<RefSummary>

find_refs with control over aggregation and cancellation. An invalid pattern is reported once, up front, instead of once per DEX.

Source

pub fn find_refs_opts( &self, query: &Query, opts: FindOptions, cancel: &AtomicBool, sink: &mut dyn FnMut(RefBatch), ) -> Result<RefSummary>

find_refs with every option: aggregation, context, cancellation.

Source

pub fn find_refs_text( &self, query: &Query, cancel: &AtomicBool, sink: &mut dyn FnMut(RefBatch), ) -> Result<RefSummary>

The rows of Engine::find_refs (one per method, no context) as text: each batch holds them in RefBatch::text, exactly the RefResult::lines find_refs would give, with no structured rows. A broad query renders and replays much faster this way.

Source

pub fn fill_context( &self, rows: &mut [RefResult], ctx: RefContext, ) -> Result<Vec<String>>

Fill the context of rows an earlier Engine::find_refs returned (typically one page of them): only their DEX files are loaded, from the cache when it holds them. Returns the entries that failed to load.

Source

pub fn manifest_xml(&self) -> Result<String>

Decode AndroidManifest.xml.

Trait Implementations§

Source§

impl Drop for Engine

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

§

impl !Freeze for Engine

§

impl !RefUnwindSafe for Engine

§

impl !UnwindSafe for Engine

§

impl Forget for Engine

§

impl Move for Engine

§

impl Send for Engine

§

impl Sync for Engine

§

impl Unpin for Engine

§

impl UnsafeUnpin for Engine

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.