Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/hexgraph/sandbox/probes/pyghidra_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,25 @@ def open_target(artifact, *, cold_analyze=True, read_only=False):


def _slow_analyzer(name: str) -> bool:
"""The auto-analysis passes disabled under the fast profile — matched by suffix so it's
architecture-agnostic ("PowerPC/ARM/x86 … Constant Reference Analyzer"). Mirrors the Jython
FAST_PROFILE_SCRIPT: drop the O(n^2) Call-Fixup Installer, the per-processor constant/scalar
propagation, and the decompile-EVERY-function passes; KEEP function/call-graph/reference
discovery (HexGraph decompiles on demand)."""
"""The auto-analysis passes disabled under the fast profile — matched by name, with the
constant-prop passes matched by suffix so it's architecture-agnostic ("PowerPC/ARM/x86 …
Constant Reference Analyzer"). Mirrors the Jython FAST_PROFILE_SCRIPT: drop the O(n^2)
Call-Fixup Installer, the per-processor constant/scalar propagation, the decompile-EVERY-function
passes, and the Non-Returning Functions analyzers (their ClearFlowAndRepair wedges on a monolith);
KEEP function/call-graph/reference discovery (HexGraph decompiles on demand)."""
if "." in name:
return False
if name in ("Call-Fixup Installer", "Decompiler Parameter ID", "Decompiler Switch Analysis",
"Aggressive Instruction Finder"):
return True
# Non-Returning Functions ("- Discovered"/"- Known"): when a heavily-called routine is flagged
# non-returning, the analyzer's ClearFlowAndRepair walks the instruction-flow graph (a CodeManager
# DB lookup per node) to repair downstream flow. On a monolith with dense/mis-disassembled code
# that traversal explodes — observed wedged for >40h in FindNoReturnFunctionsAnalyzer.repairDamagedLocations
# on a ~900 MB image. Flow past no-return calls stays intact; we lose only the auto no-return marking,
# which does not affect on-demand xrefs/decompiles.
if name.startswith("Non-Returning Functions"):
return True
return name.endswith("Constant Reference Analyzer") or name.endswith("Scalar Operand References")


Expand Down
8 changes: 7 additions & 1 deletion tests/test_ghidra_fast_profile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Ghidra's analysis of a 100 MB+ monolith is bounded by a fast profile that disables the passes
proven pathological on a huge binary (Call-Fixup Installer's O(n^2) AddressSet, the per-processor
Constant Reference Analyzer, the decompile-every-function passes) while KEEPING the call-graph/
Constant Reference Analyzer, the decompile-every-function passes, and the Non-Returning Functions
analyzers whose ClearFlowAndRepair wedges on a monolith) while KEEPING the call-graph/
reference analyzers. Since the PyGhidra re-platform these are pure host-side helpers in `pyghidra_lib`
(`_slow_analyzer` + `_FAST_PROFILE_BYTES`), applied in-process by `_analyze` before AutoAnalysisManager
runs. The analysis otherwise runs to completion — `re_analyze` runs it detached with a generous budget
Expand All @@ -25,6 +26,11 @@ def test_fast_profile_disables_the_proven_slow_passes():
# processor-agnostic match for the constant-propagation passes ("PowerPC/ARM/x86 … "):
assert L._slow_analyzer("PowerPC Constant Reference Analyzer")
assert L._slow_analyzer("ARM Scalar Operand References")
# Non-Returning Functions analyzers: ClearFlowAndRepair wedges on a monolith (both variants).
assert L._slow_analyzer("Non-Returning Functions - Discovered")
assert L._slow_analyzer("Non-Returning Functions - Known")
# ...but a dotted SUB-option of it is still never disabled (the "." rule wins):
assert not L._slow_analyzer("Non-Returning Functions - Discovered.Create Analysis Bookmarks")


def test_fast_profile_keeps_the_call_graph_analyzers():
Expand Down
Loading