Skip to content

Add per-function analysis limit overrides (reanalyze_function, get_function_analysis_limits) - #12

Open
merhovon wants to merge 3 commits into
symgraph:masterfrom
merhovon:feature/per-function-analysis-limits
Open

Add per-function analysis limit overrides (reanalyze_function, get_function_analysis_limits)#12
merhovon wants to merge 3 commits into
symgraph:masterfrom
merhovon:feature/per-function-analysis-limits

Conversation

@merhovon

@merhovon merhovon commented Sep 6, 2026

Copy link
Copy Markdown

Problem

Some functions never produce HLIL/MLIL/LLIL through get_code() / get_function_low_level_il() — they silently fall back to disassembly (fallback_used: true) or report "<IL> not available for this function", even after Analysis > Reanalyze in the GUI. Two distinct root causes were observed while debugging a large, real-world binary (110k+ functions):

  1. Recursion depth limit — Binary Ninja's log shows Function at 0x... has exceeded maximum recursion depth for Analyze requests. Caused by analysis.limits.expressionValueComputeMaxDepth (default 512) being too low for that function's MLIL SSA value computation.
  2. Analysis time limit — no error logged at all; the analysis is silently deferred. Caused by analysis.limits.maxFunctionAnalysisTime (default 20000ms) being exceeded, typically on large/complex functions (many basic blocks, high cyclomatic complexity, many call sites).

Previously, the only fix was to change the global setting in settings.json and fully restart Binary Ninja (a plain Reanalyze does not pick up the new limit), which is slow and affects every function/binary, not just the problematic one.

Solution

Binary Ninja already supports per-function overrides via Function Resource Settings (Settings.set_integer(key, value, resource=func, scope=SettingsScope.SettingsResourceScope)), persisted in the BNDB. This PR adds two MCP tools that use this mechanism directly, with no BN restart required:

  • get_function_analysis_limits(filename, function_name_or_address) — read-only. Reports the effective expressionValueComputeMaxDepth / maxFunctionAnalysisTime for one function (BinaryView default unless already overridden), analysis_skipped state, and current HLIL/MLIL/LLIL availability.
  • reanalyze_function(filename, function_name_or_address, expression_depth=None, max_analysis_time=None) — sets a Function Resource Setting override for either limit (only the ones explicitly passed), clears analysis_skipped first if needed (per the BN API docs: reanalyze() is a no-op while analysis_skipped is True), then calls func.reanalyze() + bv.update_analysis_and_wait() and returns the resulting IL availability immediately.

Example agent workflow

get_code(..., format="decompile")  -> fallback_used: true
get_function_analysis_limits(...)   -> check current limits / availability
reanalyze_function(..., max_analysis_time=0)      # cheap, fixes the more common cause first
# if still unavailable, escalate gradually:
reanalyze_function(..., expression_depth=8192)
reanalyze_function(..., expression_depth=16384)
...
get_code(..., format="decompile")  -> fallback_used: false

Testing

Live-tested against a real 110k+ function binary in a running Binary Ninja instance:

  • A small/simple function hitting the recursion-depth log message was fixed by raising expressionValueComputeMaxDepth.
  • A large function (66 basic blocks, cyclomatic complexity 34) with no log error at all was fixed by max_analysis_time=0, going from fallback_used: true/no IL to full HLIL/MLIL/LLIL availability in the same session, without restarting Binary Ninja.

No existing tools/behavior were changed; both additions are new, additive tools following the existing code patterns (@handle_exceptions/@require_binja decorators in tools.py, @mcp.tool(annotations=...) registration in server.py).

…nction_analysis_limits)

Adds two tools to fix functions that only ever return disassembly:
- get_function_analysis_limits: read-only, reports the effective
  analysis.limits.expressionValueComputeMaxDepth /
  analysis.limits.maxFunctionAnalysisTime for one function plus current
  HLIL/MLIL/LLIL availability.
- reanalyze_function: sets a Function Resource Setting override for either
  limit (persisted in the BNDB), clears analysis_skipped if needed, then
  calls func.reanalyze() + bv.update_analysis_and_wait().

This avoids having to change global settings.json values and fully restart
Binary Ninja to recover IL for a single problematic function (some functions
hit analysis.limits.expressionValueComputeMaxDepth, others hit
analysis.limits.maxFunctionAnalysisTime - both silently degrade get_code()
to a disasm fallback with no actionable error).
Copilot AI lite review requested due to automatic review settings September 6, 2026 15:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

get_function_analysis_limits currently reads settings in a way that likely ignores per-function resource overrides (or misuses get_integer’s parameters), so it may return incorrect limits for the function.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds two new MCP tools to inspect and override Binary Ninja per-function analysis limits (via Function Resource Settings) and trigger a targeted reanalysis, addressing cases where IL/decompilation stays unavailable due to recursion-depth or analysis-time limits.

Changes:

  • Add get_function_analysis_limits to report per-function effective limits, analysis_skipped, and HLIL/MLIL/LLIL availability.
  • Add reanalyze_function to optionally set per-function overrides and reanalyze the function in-session (no BN restart).
  • Minor tweak to bookmarks tag emoji literal representation in server.py.
File summaries
File Description
src/binassist_mcp/tools.py Implements the per-function limits inspection and targeted reanalysis/override logic on the Binary Ninja side.
src/binassist_mcp/server.py Registers the two new MCP tools and wires them into the existing BinaryView/context-manager flow (plus a small bookmarks emoji change).
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +2786 to +2789
"expression_depth": settings.get_integer(
"analysis.limits.expressionValueComputeMaxDepth", func),
"max_analysis_time": settings.get_integer(
"analysis.limits.maxFunctionAnalysisTime", func),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants