Skip to content

Cross-DEX method calls not executed by VM #10

Description

@haeter525

Summary

The Dalvik VM is bound to a single DEX, so a method whose bytecode lives in a different DEX of a multi-dex APK is never executed. When a method in classes.dex invokes one defined in classes2.dex, the direct/static dispatch lookup misses the single-DEX method map and the call is silently downgraded to an external API miss (stub or no-op). dextrace run <apk> therefore only produces correct results when every method actually executed happens to live in the one DEX that was loaded.

Root cause

# src/dextrace/vm/engine.py  (_do_invoke, direct/static path)
callee_code_off = self._sig_to_codeoff.get(callee_sig)
if callee_code_off is None:
    self._handle_external_miss(callee_sig, insn, state)
    return None

self._sig_to_codeoff, self._parser, self._disasm, self._resolver, and self._hierarchy are all built from a single dex_bytes. A code_off is a byte offset valid only within its own DEX, so the engine has no way to reach a callee defined in another DEX — the lookup misses and real bytecode is skipped.

Fix

Make the VM module-aware: build one DexModule (parser, resolver, disasm, local method map) per DEX, resolve direct/static calls through a global map, and carry the current module through the execution loop and CallFrame.

# global dispatch map: sig -> (module_id, code_off), stable order (classes.dex first)
location = self._sig_to_location.get(callee_sig)
if location is None:
    self._handle_external_miss(callee_sig, insn, state)
    return None
callee_module_id, callee_code_off = location
# switch active module on invoke; restore caller's module on return

Cross-DEX virtual dispatch and inheritance additionally require merging ClassHierarchy across all DEXes (vtable values become (module_id, code_off)) — a separable follow-up.

Affected locations

File Line(s) Context
src/dextrace/vm/engine.py 137-162 Per-DEX state built from single dex_bytes
src/dextrace/vm/engine.py 708-711 Direct/static dispatch misses cross-DEX callee
src/dextrace/vm/engine.py 692-694 Virtual dispatch via single-DEX ClassHierarchy
src/dextrace/vm/class_hierarchy.py 71-90 Vtables built from one DEX; values are bare code_off
src/dextrace/cli/cmd_run.py 137-139 dextrace run loads only the entry DEX

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions