Repository navigation
Conversation
StringLocator assumed the string_data_items are written in string_ids order and back to back: it took the region bounds from the first and last entry, mapped a match to the offset of the item that follows it, and subtracted one from that index. The format does not require that layout, and dexlayout (or the vendor tools that repackage system APKs) permutes the items, so findrefs returned the wrong methods or nothing at all: a reversed layout collapses the region to start > end, a partial permutation returns neighbouring indexes. Method and field queries that resolve names through the locator are affected the same way. Take the region from the smallest and largest offset, and end a match at the first terminator behind its start: a match that reaches past it runs through the terminator into the following item and names no string. When the offsets are in index order, the item behind a match still carries the next index and a single dict lookup resolves it, so d8/r8 output keeps the old cost; a permuted layout searches the ascending offsets instead. Building the map also stops unpacking every entry by hand, which leaves the string locator faster than before (-35% on the supplied DEX workload, no gated regression). tests/dex_fixture.py gains reorder_string_data(), which rewrites a fixture in a given order and recomputes the signature and checksum, so the new tests cover the ordered layout, a full reversal, and a middle permutation, plus the findrefs output for each.
fix(findrefs): resolve a string match through its own string_data_item
String data items are not written in string_ids order, so mapping a match through the following item and subtracting one returns a wrong index or nothing at all. Take the region from the smallest and largest offset and resolve the match with a binary search over the physical offsets, the same way asc-rs does. The lookup needs one bisect and one dict hit per match, with no terminator scan. On the reference workload this is faster than the previous neighbour-offset scheme: string_locator -32.5%, type_locator -56.1%, field_locator -11.2%, method_locator -9.3%, no gated regression.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.1.2-post4
Fixed
findrefsreturned wrong or missing matches on DEX files whose string data is not written instring_idsorder.StringLocatorassumed the string data items were laid out in index order and mapped a match through the offset of the following item, then subtracted one. The DEX format does not require that order, and layout passes such as dexlayout (used when repackaging system APKs) permute the items. As a result:start > end, so every string was missed;getDeviceIdquery reportingDisplay.getDeviceProductInfo.Method and field lookups that resolve names through the same locator were affected too, not only
findrefs string.The locator now takes the region from the smallest and largest
string_data_offand resolves each match with a binary search over the physical offsets, returning the index of the item that actually holds the match. This matches theasc-rsimplementation and makes no assumption about item order.getclassslowdown introduced by smali formatting. Method descriptor normalization moved out of the decompiler hot path and into the smali formatter only, removing repeated string rewriting on every invoke.Performance
Measured against the previous baseline on the same workload:
unit/string_locatorunit/type_locatorunit/field_locatorunit/method_locatorunit/field_locator_fuzzy_class_onlyunit/field_locator_fuzzy_class_fieldNo gated metric regressed. The new lookup costs one
bisectplus one dict hit per match; it needs no terminator scan, which matters on DEX files that embed multi-hundred-kilobyte string payloads (a backwards\x00scan across such an item was measured ~5x slower on Windows, wherememrchris unavailable).Tests
findrefsoutput equality across layouts.146tests pass.Upgrade
No API changes.
droidascis on PyPI;pip install -U droidasc.