pub struct Engine { /* private fields */ }Expand description
Engine over one APK.
Implementations§
Source§impl Engine
impl Engine
Sourcepub fn call_graph(&self, q: &CallQuery) -> Result<CallTree>
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.
Sourcepub fn call_graph_cancellable(
&self,
q: &CallQuery,
cancel: &AtomicBool,
) -> Result<CallTree>
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
impl Engine
Sourcepub fn scan_classes(
&self,
prefix: Option<&str>,
progress: impl Fn(usize, usize) + Sync,
) -> Result<Vec<EntryClasses>>
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.
Sourcepub fn list_classes(&self, prefix: Option<&str>) -> Result<Vec<ClassListing>>
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
impl Engine
Sourcepub fn matching_methods(
&self,
queries: &[Query],
cancel: &AtomicBool,
) -> Result<MatchingMethods>
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
impl Engine
Sourcepub fn hierarchy(&self, q: &HierarchyQuery) -> Result<HierarchyTree>
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.
Sourcepub fn hierarchy_cancellable(
&self,
q: &HierarchyQuery,
cancel: &AtomicBool,
) -> Result<HierarchyTree>
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
impl Engine
Sourcepub fn manifest_summary(&self) -> Result<ManifestSummary>
pub fn manifest_summary(&self) -> Result<ManifestSummary>
Parse AndroidManifest.xml (and the XML resources it points at) into
a ManifestSummary.
Source§impl Engine
impl Engine
Sourcepub fn prebuild(&self) -> Result<PrebuildReport>
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).
Sourcepub fn cancel_prebuild(&self)
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
impl Engine
Sourcepub fn resources(&self) -> Result<Option<Arc<ResTable>>>
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.
Sourcepub fn release_resources(&self)
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).
Sourcepub fn xml(&self, path: &str) -> Result<String>
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.
Sourcepub fn manifest_xml_resolved(&self) -> Result<String>
pub fn manifest_xml_resolved(&self) -> Result<String>
Engine::manifest_xml with @7F... references shown by name.
Sourcepub fn dump_resources(&self, f: impl FnMut(ResourceRow)) -> Result<()>
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).
Sourcepub fn resource(&self, query: &str) -> Result<Vec<ResourceRow>>
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).
Sourcepub fn resolve_resource(
&self,
query: &str,
config: Option<&Config>,
) -> Result<(Vec<String>, ResourceRow)>
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.
Sourcepub fn search_resources(
&self,
pattern: &str,
literal: bool,
field: ResourceField,
limit: usize,
) -> Result<(Vec<ResourceRow>, usize)>
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
impl Engine
Sourcepub fn annotate_resource_ids(&self, smali: &str) -> String
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
impl Engine
Sourcepub fn find_refs_rules(
&self,
rules: &[Query],
opts: FindOptions,
cancel: &AtomicBool,
sink: &mut dyn FnMut(usize, RefBatch),
) -> Result<RefSummary>
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.
Sourcepub fn search_target_entry_rules(
&self,
target: &SearchTarget,
entry: &Entry,
rules: &[&CompiledQuery],
aggregate: bool,
cancel: &AtomicBool,
) -> Vec<RefBatch>
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
impl Engine
Sourcepub fn cached_refs(
&self,
target: &SearchTarget,
query: &Query,
aggregate: bool,
) -> Option<Vec<RefBatch>>
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.
Sourcepub fn store_refs(&self, query: &Query, aggregate: bool, batches: &[RefBatch])
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).
Sourcepub fn search_target_entry_dedup(
&self,
target: &SearchTarget,
entry: &Entry,
query: &CompiledQuery,
aggregate: bool,
cancel: &AtomicBool,
claim: &Claim,
) -> RefBatch
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.
Sourcepub fn search_target_entry_rules_dedup(
&self,
target: &SearchTarget,
entry: &Entry,
rules: &[&CompiledQuery],
aggregate: bool,
cancel: &AtomicBool,
claim: &Claim,
) -> Vec<RefBatch>
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
impl Engine
Sourcepub fn new(apk_path: impl AsRef<Path>) -> Engine
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).
Sourcepub fn with_limits(self, limits: Limits) -> Engine
pub fn with_limits(self, limits: Limits) -> Engine
Refuse entries that inflate past limits (zip bombs).
pub fn with_threads(self, threads: impl Into<Threads>) -> Engine
pub fn with_debug(self, debug: bool) -> Engine
Sourcepub fn with_logger(
self,
logger: impl Fn(&str) + Send + Sync + 'static,
) -> Engine
pub fn with_logger( self, logger: impl Fn(&str) + Send + Sync + 'static, ) -> Engine
Route debug output somewhere other than stdout.
Sourcepub fn with_cache(self, config: CacheConfig) -> Engine
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.
Use cache (shared with other engines) instead of a private one.
pub fn apk_path(&self) -> &Path
pub fn cache_stats(&self) -> CacheStats
Sourcepub fn resident_bytes(&self) -> usize
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).
Sourcepub fn memory_cache_bytes(&self) -> usize
pub fn memory_cache_bytes(&self) -> usize
Bytes currently charged to the in-memory cache: entry bytes plus the locator tables built for them.
Sourcepub fn release_memory_cache(&self) -> usize
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.
Sourcepub fn memory_cache_mapped_bytes(&self) -> usize
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.
Sourcepub fn memory_cache_mapped_table_bytes(&self) -> usize
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.
Sourcepub fn flush_cache_writes(&self)
pub fn flush_cache_writes(&self)
Block until every queued disk-cache write has been renamed into place.
Sourcepub fn close_cache_writes(&self)
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.
Sourcepub fn open(&self) -> Result<Apk>
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.
Sourcepub fn resolve_path(apk_path: &Path, base: &Path) -> PathBuf
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.
Sourcepub fn can_open(apk_path: &Path) -> bool
pub fn can_open(apk_path: &Path) -> bool
Whether apk_path opens: a readable file, or a program with code.
Sourcepub fn program_notes(&self) -> Vec<String>
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.
Sourcepub fn search_target(&self) -> Result<SearchTarget>
pub fn search_target(&self) -> Result<SearchTarget>
Open the APK for Engine::search_target.
Sourcepub fn search_target_entry(
&self,
target: &SearchTarget,
entry: &Entry,
query: &CompiledQuery,
aggregate: bool,
cancel: &AtomicBool,
) -> RefBatch
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.
Sourcepub fn dex_entries(&self) -> Result<Vec<Entry>>
pub fn dex_entries(&self) -> Result<Vec<Entry>>
Root-level DEX entries, smallest compressed first.
Sourcepub fn apk_key(&self, apk: &Apk) -> Option<ApkKey>
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.
Sourcepub fn entry_bytes(
&self,
apk: &Apk,
key: Option<&ApkKey>,
entry: &Entry,
) -> Result<DexBytes>
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.
Sourcepub fn get_class_dex(&self, descriptor: &str) -> Result<Option<ClassHit>>
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).
Sourcepub fn get_class_dex_cancellable(
&self,
descriptor: &str,
cancel: &AtomicBool,
) -> Result<Option<ClassHit>>
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.
Sourcepub fn get_class(&self, descriptor: &str) -> Result<ClassSource>
pub fn get_class(&self, descriptor: &str) -> Result<ClassSource>
Locate, rebuild and disassemble a class.
pub fn get_class_with( &self, descriptor: &str, opts: SmaliOptions, ) -> Result<ClassSource>
Sourcepub fn get_class_method(
&self,
descriptor: &str,
opts: SmaliOptions,
method: Option<&str>,
) -> Result<ClassSource>
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.
Sourcepub fn get_class_method_cancellable(
&self,
descriptor: &str,
opts: SmaliOptions,
method: Option<&str>,
cancel: &AtomicBool,
) -> Result<ClassSource>
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.
Sourcepub fn find_refs(
&self,
query: &Query,
sink: impl FnMut(RefBatch),
) -> Result<RefSummary>
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.
Sourcepub fn find_refs_with(
&self,
query: &Query,
aggregate: bool,
cancel: &AtomicBool,
sink: &mut dyn FnMut(RefBatch),
) -> Result<RefSummary>
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.
Sourcepub fn find_refs_opts(
&self,
query: &Query,
opts: FindOptions,
cancel: &AtomicBool,
sink: &mut dyn FnMut(RefBatch),
) -> Result<RefSummary>
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.
Sourcepub fn find_refs_text(
&self,
query: &Query,
cancel: &AtomicBool,
sink: &mut dyn FnMut(RefBatch),
) -> Result<RefSummary>
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.
Sourcepub fn fill_context(
&self,
rows: &mut [RefResult],
ctx: RefContext,
) -> Result<Vec<String>>
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.
Sourcepub fn manifest_xml(&self) -> Result<String>
pub fn manifest_xml(&self) -> Result<String>
Decode AndroidManifest.xml.